Advertisement
Gamestabled

OoT/3D collision with seams blender script

Oct 29th, 2022 (edited)
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.49 KB | None | 0 0
  1. import bpy
  2. import math
  3. from cmath import sqrt
  4. from io import SEEK_CUR
  5. import struct
  6.  
  7. # Create new mesh and a new object
  8. def create_mesh(ob_name, coords, edges, faces):
  9. me = bpy.data.meshes.new(ob_name + "Mesh")
  10. ob = bpy.data.objects.new(ob_name, me)
  11.  
  12. me.from_pydata(coords, edges, faces)
  13. me.update()
  14.  
  15. bpy.context.collection.objects.link(ob)
  16. return ob
  17.  
  18. #SCENE_FILE = "C:\\Users\\gamestabled\\Desktop\\Games\\N64\\OoT\\scenes\\Bmori1_scene"
  19. SCENE_FILE = "C:\\Users\\gamestabled\\Desktop\\Games\\3DS\\OoT3D(USA)\\romfs\\scene\\bmori1_info.zsi"
  20. SCENE_NAME = "forest"
  21.  
  22. MAP_SCALE = (1.0 / 100.0)
  23.  
  24. EPSILON_OOT3D = 0.00008
  25. EPSILON_OOT = 0.008
  26.  
  27. MODE_OOT3D = 0
  28. MODE_OOT = 1
  29.  
  30. def check_and_set_mode(scene_file):
  31. global CUR_MODE
  32.  
  33. magic = scene_file.read(4)
  34. if magic == b"ZSI\x01":
  35. CUR_MODE = MODE_OOT3D
  36. else:
  37. print("didn't see ZSI header, assuming this is an oot scene")
  38. CUR_MODE = MODE_OOT
  39.  
  40. def epsilon():
  41. if CUR_MODE == MODE_OOT3D:
  42. return EPSILON_OOT3D
  43. else:
  44. return EPSILON_OOT
  45.  
  46. def read_poylgon_oot3d(scene_file):
  47. polyType = struct.unpack('<h', scene_file.read(2))[0]
  48. vtx1 = struct.unpack('<h', scene_file.read(2))[0] & 0x1FFF
  49. vtx2 = struct.unpack('<h', scene_file.read(2))[0] & 0x1FFF
  50. vtx3 = struct.unpack('<h', scene_file.read(2))[0] & 0x1FFF
  51. unk_08 = struct.unpack('<h', scene_file.read(2))[0]
  52. normal_x = struct.unpack('<h', scene_file.read(2))[0] * (1.0 / 32767.0)
  53. normal_y = struct.unpack('<h', scene_file.read(2))[0] * (1.0 / 32767.0)
  54. normal_z = struct.unpack('<h', scene_file.read(2))[0] * (1.0 / 32767.0)
  55. dist = struct.unpack('<f', scene_file.read(4))[0]
  56.  
  57. return (polyType, (vtx1, vtx2, vtx3), unk_08, (normal_x, normal_y, normal_z), dist)
  58.  
  59. def read_polygon_oot(scene_file):
  60. polyType = struct.unpack('>h', scene_file.read(2))[0]
  61. vtx1 = struct.unpack('>h', scene_file.read(2))[0] & 0x1FFF
  62. vtx2 = struct.unpack('>h', scene_file.read(2))[0] & 0x1FFF
  63. vtx3 = struct.unpack('>h', scene_file.read(2))[0] & 0x1FFF
  64. normal_x = struct.unpack('>h', scene_file.read(2))[0] * (1.0 / 32767.0)
  65. normal_y = struct.unpack('>h', scene_file.read(2))[0] * (1.0 / 32767.0)
  66. normal_z = struct.unpack('>h', scene_file.read(2))[0] * (1.0 / 32767.0)
  67. dist = struct.unpack('>h', scene_file.read(2))[0]
  68.  
  69. return (polyType, (vtx1, vtx2, vtx3), 0, (normal_x, normal_y, normal_z), dist)
  70.  
  71. def read_poylgon(scene_file):
  72. if CUR_MODE == MODE_OOT3D:
  73. return read_poylgon_oot3d(scene_file)
  74. else:
  75. return read_polygon_oot(scene_file)
  76.  
  77. # going to ignore alternate setups for now
  78. def get_vtx_and_poly_info_from_scene_file_oot3d(scene_file):
  79.  
  80. scene_file.seek(0x10)
  81. while(1):
  82. cmd1 = struct.unpack('<i', scene_file.read(4))[0]
  83. cmd2 = struct.unpack('<i', scene_file.read(4))[0]
  84. cmdType = cmd1 & 0xFF
  85.  
  86. if cmdType == 0x14:
  87. print("Found no collision header commands")
  88. return (None, None, None, None)
  89.  
  90. if cmdType == 0x03:
  91. scene_file.seek(cmd2 + 0x10)
  92.  
  93. box_min_x = struct.unpack('<h', scene_file.read(2))[0]
  94. box_min_y = struct.unpack('<h', scene_file.read(2))[0]
  95. box_min_z = struct.unpack('<h', scene_file.read(2))[0]
  96.  
  97. box_max_x = struct.unpack('<h', scene_file.read(2))[0]
  98. box_max_y = struct.unpack('<h', scene_file.read(2))[0]
  99. box_max_z = struct.unpack('<h', scene_file.read(2))[0]
  100.  
  101. numVtxs = struct.unpack('<h', scene_file.read(2))[0]
  102. numPolygons = struct.unpack('<h', scene_file.read(2))[0]
  103. numSurfaceTypes = struct.unpack('<h', scene_file.read(2))[0]
  104. numCamDataList = struct.unpack('<h', scene_file.read(2))[0]
  105.  
  106. scene_file.seek(0x04, SEEK_CUR)
  107. vtxsOffset = struct.unpack('<i', scene_file.read(4))[0]
  108. polygonsOffset = struct.unpack('<i', scene_file.read(4))[0]
  109. return (numVtxs, vtxsOffset + 0x10, numPolygons, polygonsOffset + 0x10)
  110.  
  111.  
  112. # going to ignore alternate setups for now
  113. def get_vtx_and_poly_info_from_scene_file_oot(scene_file):
  114. while(1):
  115. cmdType = struct.unpack('>B', scene_file.read(1))[0]
  116. data1 = struct.unpack('>B', scene_file.read(1))[0]
  117. pad = struct.unpack('>h', scene_file.read(2))[0]
  118. segment = struct.unpack('>I', scene_file.read(4))[0]
  119.  
  120. if cmdType == 0x14:
  121. print("Found no collision header commands")
  122. return (None, None, None, None)
  123.  
  124. if cmdType == 0x03:
  125. offset = segment & 0xFFFFFF
  126. scene_file.seek(offset)
  127.  
  128. box_min_x = struct.unpack('>h', scene_file.read(2))[0]
  129. box_min_y = struct.unpack('>h', scene_file.read(2))[0]
  130. box_min_z = struct.unpack('>h', scene_file.read(2))[0]
  131.  
  132. box_max_x = struct.unpack('>h', scene_file.read(2))[0]
  133. box_max_y = struct.unpack('>h', scene_file.read(2))[0]
  134. box_max_z = struct.unpack('>h', scene_file.read(2))[0]
  135.  
  136. numVtxs = struct.unpack('>h', scene_file.read(2))[0]
  137. pad = struct.unpack('>h', scene_file.read(2))[0]
  138. vtxsSegment = struct.unpack('>I', scene_file.read(4))[0]
  139. vtxsOffset = vtxsSegment & 0xFFFFFF
  140.  
  141. numPolygons = struct.unpack('>h', scene_file.read(2))[0]
  142. pad = struct.unpack('>h', scene_file.read(2))[0]
  143. polygonsSegment = struct.unpack('>I', scene_file.read(4))[0]
  144. polygonsOffset = polygonsSegment & 0xFFFFFF
  145.  
  146. # surfaceTypesSegment = struct.unpack('>I', scene_file.read(4))[0]
  147. # bgCamInfoSegment = struct.unpack('>I', scene_file.read(4))[0]
  148. # numWaterBoxes = struct.unpack('>h', scene_file.read(2))[0]
  149. # pad = struct.unpack('>h', scene_file.read(2))[0]
  150. # waterBoxesSegment = struct.unpack('>I', scene_file.read(4))[0]
  151.  
  152. return (numVtxs, vtxsOffset, numPolygons, polygonsOffset)
  153.  
  154. def get_vtx_and_poly_info_from_scene_file(scene_file):
  155. if CUR_MODE == MODE_OOT3D:
  156. return get_vtx_and_poly_info_from_scene_file_oot3d(scene_file)
  157. else:
  158. return get_vtx_and_poly_info_from_scene_file_oot(scene_file)
  159.  
  160.  
  161. def read_vtx_oot3d(scene_file):
  162. vtx_x = struct.unpack('<h', scene_file.read(2))[0]
  163. vtx_y = struct.unpack('<h', scene_file.read(2))[0]
  164. vtx_z = struct.unpack('<h', scene_file.read(2))[0]
  165. return (vtx_x, vtx_y, vtx_z)
  166.  
  167. def read_vtx_oot(scene_file):
  168. vtx_x = struct.unpack('>h', scene_file.read(2))[0]
  169. vtx_y = struct.unpack('>h', scene_file.read(2))[0]
  170. vtx_z = struct.unpack('>h', scene_file.read(2))[0]
  171. return (vtx_x, vtx_y, vtx_z)
  172.  
  173. def read_vtx(scene_file):
  174. if CUR_MODE == MODE_OOT3D:
  175. return read_vtx_oot3d(scene_file)
  176. else:
  177. return read_vtx_oot(scene_file)
  178.  
  179. with open(SCENE_FILE, 'rb') as scene_file:
  180.  
  181. check_and_set_mode(scene_file)
  182. scene_file.seek(0)
  183.  
  184. (numVtxs, vtxsOffset, numPolygons, polygonsOffset) = get_vtx_and_poly_info_from_scene_file(scene_file)
  185.  
  186. #read the vtx data
  187. scene_file.seek(vtxsOffset)
  188. vtxs = []
  189. for i in range(0, numVtxs):
  190. (vtx_x, vtx_y, vtx_z) = read_vtx(scene_file)
  191. vtxs.append((- vtx_x * MAP_SCALE, vtx_z * MAP_SCALE, vtx_y * MAP_SCALE))
  192.  
  193. #read the polys data
  194. scene_file.seek(polygonsOffset)
  195. faces = []
  196.  
  197. extensions = []
  198. num_small_y = 0
  199.  
  200. for i in range(0, numPolygons):
  201.  
  202. (polytype, (vtx1, vtx2, vtx3), unk_08, (normal_x, normal_y, normal_z), dist) = read_poylgon(scene_file)
  203.  
  204. faces.append((vtx1, vtx2, vtx3))
  205.  
  206. #let's try to compute the quads that extend the face
  207. tri_vtxs = [vtx1, vtx2, vtx3]
  208. if normal_y > epsilon():
  209.  
  210. for (a, b) in ((0, 1), (1, 2), (2, 0)):
  211. vtx_1 = vtxs[tri_vtxs[a]]
  212. vtx_2 = vtxs[tri_vtxs[b]]
  213.  
  214. vtx_1_x = - vtx_1[0] / MAP_SCALE
  215. vtx_1_z = vtx_1[1] / MAP_SCALE
  216. vtx_2_x = - vtx_2[0] / MAP_SCALE
  217. vtx_2_z = vtx_2[1] / MAP_SCALE
  218.  
  219. edge_d_z = vtx_2_z - vtx_1_z
  220. edge_d_x = vtx_2_x - vtx_1_x
  221.  
  222. if edge_d_z != 0 and edge_d_x != 0:
  223. edge_xz_slope = float(edge_d_z)/edge_d_x
  224. extend_rect_xz_slope = -1.0/edge_xz_slope
  225. extend_delta_z = 0.0 * math.sin(math.atan(extend_rect_xz_slope))
  226. extend_delta_x = 0.0 * math.cos(math.atan(extend_rect_xz_slope))
  227.  
  228. extend_1_x = vtx_1_x + extend_delta_x
  229. extend_1_z = vtx_1_z + extend_delta_z
  230.  
  231. extend_1_x_b = vtx_1_x - extend_delta_x
  232. extend_1_z_b = vtx_1_z - extend_delta_z
  233.  
  234. extend_2_x = vtx_2_x + extend_delta_x
  235. extend_2_z = vtx_2_z + extend_delta_z
  236.  
  237. extend_2_x_b = vtx_2_x - extend_delta_x
  238. extend_2_z_b = vtx_2_z - extend_delta_z
  239.  
  240. extend_1_y = (((-(normal_x * extend_1_x)) - (normal_z * extend_1_z)) - dist) / normal_y
  241. extend_2_y = (((-(normal_x * extend_2_x)) - (normal_z * extend_2_z)) - dist) / normal_y
  242.  
  243. extend_1_y_b = (((-(normal_x * extend_1_x_b)) - (normal_z * extend_1_z_b)) - dist) / normal_y
  244. extend_2_y_b = (((-(normal_x * extend_2_x_b)) - (normal_z * extend_2_z_b)) - dist) / normal_y
  245.  
  246. 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)))
  247. 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)))
  248.  
  249. # add extension quads
  250. for (v1, v2, (extend_1_x, extend_1_y, extend_1_z), (extend_2_x, extend_2_y, extend_2_z)) in extensions:
  251. ext_index_2 = len(vtxs)
  252. vtxs.append((- extend_1_x * MAP_SCALE, extend_1_z * MAP_SCALE, extend_1_y * MAP_SCALE))
  253. ext_index_3 = len(vtxs)
  254. vtxs.append((- extend_2_x * MAP_SCALE, extend_2_z * MAP_SCALE, extend_2_y * MAP_SCALE))
  255. faces.append((v1, ext_index_2, ext_index_3, v2))
  256.  
  257. create_mesh(SCENE_NAME, vtxs, [], faces)
  258.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement