Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import bpy
- import math
- from cmath import sqrt
- from io import SEEK_CUR
- import struct
- # Create new mesh and a new object
- def create_mesh(ob_name, coords, edges, faces):
- me = bpy.data.meshes.new(ob_name + "Mesh")
- ob = bpy.data.objects.new(ob_name, me)
- me.from_pydata(coords, edges, faces)
- me.update()
- bpy.context.collection.objects.link(ob)
- return ob
- #SCENE_FILE = "C:\\Users\\gamestabled\\Desktop\\Games\\N64\\OoT\\scenes\\Bmori1_scene"
- SCENE_FILE = "C:\\Users\\gamestabled\\Desktop\\Games\\3DS\\OoT3D(USA)\\romfs\\scene\\bmori1_info.zsi"
- SCENE_NAME = "forest"
- MAP_SCALE = (1.0 / 100.0)
- EPSILON_OOT3D = 0.00008
- EPSILON_OOT = 0.008
- MODE_OOT3D = 0
- MODE_OOT = 1
- def check_and_set_mode(scene_file):
- global CUR_MODE
- magic = scene_file.read(4)
- if magic == b"ZSI\x01":
- CUR_MODE = MODE_OOT3D
- else:
- print("didn't see ZSI header, assuming this is an oot scene")
- CUR_MODE = MODE_OOT
- def epsilon():
- if CUR_MODE == MODE_OOT3D:
- return EPSILON_OOT3D
- else:
- return EPSILON_OOT
- def read_poylgon_oot3d(scene_file):
- polyType = struct.unpack('<h', scene_file.read(2))[0]
- vtx1 = struct.unpack('<h', scene_file.read(2))[0] & 0x1FFF
- vtx2 = struct.unpack('<h', scene_file.read(2))[0] & 0x1FFF
- vtx3 = struct.unpack('<h', scene_file.read(2))[0] & 0x1FFF
- unk_08 = struct.unpack('<h', scene_file.read(2))[0]
- normal_x = struct.unpack('<h', scene_file.read(2))[0] * (1.0 / 32767.0)
- normal_y = struct.unpack('<h', scene_file.read(2))[0] * (1.0 / 32767.0)
- normal_z = struct.unpack('<h', scene_file.read(2))[0] * (1.0 / 32767.0)
- dist = struct.unpack('<f', scene_file.read(4))[0]
- return (polyType, (vtx1, vtx2, vtx3), unk_08, (normal_x, normal_y, normal_z), dist)
- def read_polygon_oot(scene_file):
- polyType = struct.unpack('>h', scene_file.read(2))[0]
- vtx1 = struct.unpack('>h', scene_file.read(2))[0] & 0x1FFF
- vtx2 = struct.unpack('>h', scene_file.read(2))[0] & 0x1FFF
- vtx3 = struct.unpack('>h', scene_file.read(2))[0] & 0x1FFF
- normal_x = struct.unpack('>h', scene_file.read(2))[0] * (1.0 / 32767.0)
- normal_y = struct.unpack('>h', scene_file.read(2))[0] * (1.0 / 32767.0)
- normal_z = struct.unpack('>h', scene_file.read(2))[0] * (1.0 / 32767.0)
- dist = struct.unpack('>h', scene_file.read(2))[0]
- return (polyType, (vtx1, vtx2, vtx3), 0, (normal_x, normal_y, normal_z), dist)
- def read_poylgon(scene_file):
- if CUR_MODE == MODE_OOT3D:
- return read_poylgon_oot3d(scene_file)
- else:
- return read_polygon_oot(scene_file)
- # going to ignore alternate setups for now
- def get_vtx_and_poly_info_from_scene_file_oot3d(scene_file):
- scene_file.seek(0x10)
- while(1):
- cmd1 = struct.unpack('<i', scene_file.read(4))[0]
- cmd2 = struct.unpack('<i', scene_file.read(4))[0]
- cmdType = cmd1 & 0xFF
- if cmdType == 0x14:
- print("Found no collision header commands")
- return (None, None, None, None)
- if cmdType == 0x03:
- scene_file.seek(cmd2 + 0x10)
- box_min_x = struct.unpack('<h', scene_file.read(2))[0]
- box_min_y = struct.unpack('<h', scene_file.read(2))[0]
- box_min_z = struct.unpack('<h', scene_file.read(2))[0]
- box_max_x = struct.unpack('<h', scene_file.read(2))[0]
- box_max_y = struct.unpack('<h', scene_file.read(2))[0]
- box_max_z = struct.unpack('<h', scene_file.read(2))[0]
- numVtxs = struct.unpack('<h', scene_file.read(2))[0]
- numPolygons = struct.unpack('<h', scene_file.read(2))[0]
- numSurfaceTypes = struct.unpack('<h', scene_file.read(2))[0]
- numCamDataList = struct.unpack('<h', scene_file.read(2))[0]
- scene_file.seek(0x04, SEEK_CUR)
- vtxsOffset = struct.unpack('<i', scene_file.read(4))[0]
- polygonsOffset = struct.unpack('<i', scene_file.read(4))[0]
- return (numVtxs, vtxsOffset + 0x10, numPolygons, polygonsOffset + 0x10)
- # going to ignore alternate setups for now
- def get_vtx_and_poly_info_from_scene_file_oot(scene_file):
- while(1):
- cmdType = struct.unpack('>B', scene_file.read(1))[0]
- data1 = struct.unpack('>B', scene_file.read(1))[0]
- pad = struct.unpack('>h', scene_file.read(2))[0]
- segment = struct.unpack('>I', scene_file.read(4))[0]
- if cmdType == 0x14:
- print("Found no collision header commands")
- return (None, None, None, None)
- if cmdType == 0x03:
- offset = segment & 0xFFFFFF
- scene_file.seek(offset)
- box_min_x = struct.unpack('>h', scene_file.read(2))[0]
- box_min_y = struct.unpack('>h', scene_file.read(2))[0]
- box_min_z = struct.unpack('>h', scene_file.read(2))[0]
- box_max_x = struct.unpack('>h', scene_file.read(2))[0]
- box_max_y = struct.unpack('>h', scene_file.read(2))[0]
- box_max_z = struct.unpack('>h', scene_file.read(2))[0]
- numVtxs = struct.unpack('>h', scene_file.read(2))[0]
- pad = struct.unpack('>h', scene_file.read(2))[0]
- vtxsSegment = struct.unpack('>I', scene_file.read(4))[0]
- vtxsOffset = vtxsSegment & 0xFFFFFF
- numPolygons = struct.unpack('>h', scene_file.read(2))[0]
- pad = struct.unpack('>h', scene_file.read(2))[0]
- polygonsSegment = struct.unpack('>I', scene_file.read(4))[0]
- polygonsOffset = polygonsSegment & 0xFFFFFF
- # surfaceTypesSegment = struct.unpack('>I', scene_file.read(4))[0]
- # bgCamInfoSegment = struct.unpack('>I', scene_file.read(4))[0]
- # numWaterBoxes = struct.unpack('>h', scene_file.read(2))[0]
- # pad = struct.unpack('>h', scene_file.read(2))[0]
- # waterBoxesSegment = struct.unpack('>I', scene_file.read(4))[0]
- return (numVtxs, vtxsOffset, numPolygons, polygonsOffset)
- def get_vtx_and_poly_info_from_scene_file(scene_file):
- if CUR_MODE == MODE_OOT3D:
- return get_vtx_and_poly_info_from_scene_file_oot3d(scene_file)
- else:
- return get_vtx_and_poly_info_from_scene_file_oot(scene_file)
- def read_vtx_oot3d(scene_file):
- vtx_x = struct.unpack('<h', scene_file.read(2))[0]
- vtx_y = struct.unpack('<h', scene_file.read(2))[0]
- vtx_z = struct.unpack('<h', scene_file.read(2))[0]
- return (vtx_x, vtx_y, vtx_z)
- def read_vtx_oot(scene_file):
- vtx_x = struct.unpack('>h', scene_file.read(2))[0]
- vtx_y = struct.unpack('>h', scene_file.read(2))[0]
- vtx_z = struct.unpack('>h', scene_file.read(2))[0]
- return (vtx_x, vtx_y, vtx_z)
- def read_vtx(scene_file):
- if CUR_MODE == MODE_OOT3D:
- return read_vtx_oot3d(scene_file)
- else:
- return read_vtx_oot(scene_file)
- with open(SCENE_FILE, 'rb') as scene_file:
- check_and_set_mode(scene_file)
- scene_file.seek(0)
- (numVtxs, vtxsOffset, numPolygons, polygonsOffset) = get_vtx_and_poly_info_from_scene_file(scene_file)
- #read the vtx data
- scene_file.seek(vtxsOffset)
- vtxs = []
- for i in range(0, numVtxs):
- (vtx_x, vtx_y, vtx_z) = read_vtx(scene_file)
- vtxs.append((- vtx_x * MAP_SCALE, vtx_z * MAP_SCALE, vtx_y * MAP_SCALE))
- #read the polys data
- scene_file.seek(polygonsOffset)
- faces = []
- extensions = []
- num_small_y = 0
- for i in range(0, numPolygons):
- (polytype, (vtx1, vtx2, vtx3), unk_08, (normal_x, normal_y, normal_z), dist) = read_poylgon(scene_file)
- faces.append((vtx1, vtx2, vtx3))
- #let's try to compute the quads that extend the face
- tri_vtxs = [vtx1, vtx2, vtx3]
- if normal_y > epsilon():
- for (a, b) in ((0, 1), (1, 2), (2, 0)):
- vtx_1 = vtxs[tri_vtxs[a]]
- vtx_2 = vtxs[tri_vtxs[b]]
- vtx_1_x = - vtx_1[0] / MAP_SCALE
- vtx_1_z = vtx_1[1] / MAP_SCALE
- vtx_2_x = - vtx_2[0] / MAP_SCALE
- vtx_2_z = vtx_2[1] / MAP_SCALE
- edge_d_z = vtx_2_z - vtx_1_z
- edge_d_x = vtx_2_x - vtx_1_x
- if edge_d_z != 0 and edge_d_x != 0:
- edge_xz_slope = float(edge_d_z)/edge_d_x
- extend_rect_xz_slope = -1.0/edge_xz_slope
- extend_delta_z = 0.0 * math.sin(math.atan(extend_rect_xz_slope))
- extend_delta_x = 0.0 * math.cos(math.atan(extend_rect_xz_slope))
- extend_1_x = vtx_1_x + extend_delta_x
- extend_1_z = vtx_1_z + extend_delta_z
- extend_1_x_b = vtx_1_x - extend_delta_x
- extend_1_z_b = vtx_1_z - extend_delta_z
- extend_2_x = vtx_2_x + extend_delta_x
- extend_2_z = vtx_2_z + extend_delta_z
- extend_2_x_b = vtx_2_x - extend_delta_x
- extend_2_z_b = vtx_2_z - extend_delta_z
- extend_1_y = (((-(normal_x * extend_1_x)) - (normal_z * extend_1_z)) - dist) / normal_y
- extend_2_y = (((-(normal_x * extend_2_x)) - (normal_z * extend_2_z)) - dist) / normal_y
- extend_1_y_b = (((-(normal_x * extend_1_x_b)) - (normal_z * extend_1_z_b)) - dist) / normal_y
- extend_2_y_b = (((-(normal_x * extend_2_x_b)) - (normal_z * extend_2_z_b)) - dist) / normal_y
- extensions.append((tri_vtxs[a], tri_vtxs[b], (extend_1_x, extend_1_y, extend_1_z), (extend_2_x, extend_2_y, extend_2_z)))
- extensions.append((tri_vtxs[a], tri_vtxs[b], (extend_1_x_b, extend_1_y_b, extend_1_z_b), (extend_2_x_b, extend_2_y_b, extend_2_z_b)))
- # add extension quads
- for (v1, v2, (extend_1_x, extend_1_y, extend_1_z), (extend_2_x, extend_2_y, extend_2_z)) in extensions:
- ext_index_2 = len(vtxs)
- vtxs.append((- extend_1_x * MAP_SCALE, extend_1_z * MAP_SCALE, extend_1_y * MAP_SCALE))
- ext_index_3 = len(vtxs)
- vtxs.append((- extend_2_x * MAP_SCALE, extend_2_z * MAP_SCALE, extend_2_y * MAP_SCALE))
- faces.append((v1, ext_index_2, ext_index_3, v2))
- create_mesh(SCENE_NAME, vtxs, [], faces)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement