|
| 1 | +from typing import List |
| 2 | + |
| 3 | +import bpy |
| 4 | + |
| 5 | +from bsp_tool.branches.respawn import titanfall as r1 |
| 6 | + |
| 7 | + |
| 8 | +def sanitise(path: str) -> str: |
| 9 | + return path.lower().replace("\\", "/") |
| 10 | + |
| 11 | + |
| 12 | +# faster mesh construction |
| 13 | +def vertex_lump_and_indices_of_mesh(bsp, mesh_index: int) -> (str, List[int]): |
| 14 | + mesh = bsp.MESHES[mesh_index] |
| 15 | + vertex_lump_name = (mesh.flags & r1.MeshFlags.MASK_VERTEX).name |
| 16 | + material_sort = bsp.MATERIAL_SORTS[mesh.material_sort] |
| 17 | + start = mesh.first_mesh_index |
| 18 | + finish = start + mesh.num_triangles * 3 |
| 19 | + indices = [i + material_sort.vertex_offset for i in bsp.MESH_INDICES[start:finish]] |
| 20 | + return vertex_lump_name, indices |
| 21 | + |
| 22 | + |
| 23 | +def remap_indices(indices: List[int]) -> (List[int], List[int]): |
| 24 | + subset = list(set(indices)) |
| 25 | + new_indices = [subset.index(i) for i in indices] |
| 26 | + return new_indices, subset |
| 27 | + # new_index -> subset -> VertexLump |
| 28 | + |
| 29 | + |
| 30 | +def bsp_model_to_blender_mesh(bsp, model_index: int) -> str: |
| 31 | + lumps = {"LIT_BUMP": bsp.VERTEX_LIT_BUMP, |
| 32 | + "LIT_FLAT": bsp.VERTEX_LIT_FLAT, |
| 33 | + "UNLIT": bsp.VERTEX_UNLIT, |
| 34 | + "UNLIT_TS": bsp.VERTEX_UNLIT_TS} |
| 35 | + |
| 36 | + all_position_indices = list() |
| 37 | + for mesh_index in range(bsp.MODELS[0].num_meshes): |
| 38 | + vertex_lump_name, indices = vertex_lump_and_indices_of_mesh(bsp, mesh_index) |
| 39 | + # TODO: generate uvs per vertex per face |
| 40 | + # -- same with surface normals |
| 41 | + vertex_lump = lumps[vertex_lump_name[7:]] |
| 42 | + position_indices = [vertex_lump[i].position for i in indices] |
| 43 | + all_position_indices.extend(position_indices) |
| 44 | + |
| 45 | + indices, positions = remap_indices(position_indices) |
| 46 | + vertices = [bsp.VERTICES[i].as_tuple() for i in positions] |
| 47 | + assert len(indices) % 3 == 0, "everything should be triangles" |
| 48 | + triangles = [(indices[i], indices[i+1], indices[i+2]) for i in range(0, len(indices), 3)] |
| 49 | + # TODO: can we pass vertices & triangles as generators? memory savings |
| 50 | + |
| 51 | + mesh_name = f"BspModel.{model_index:04d}" |
| 52 | + mesh = bsp.data.meshes.new(mesh_name) |
| 53 | + mesh.from_pydata(vertices, [], triangles) |
| 54 | + # TODO: vertex: normal, colour, uv, lightmap_uv |
| 55 | + # -- attributes: bsp.mesh->lightmap_index, bsp.material_sort->cubemap_index |
| 56 | + # -- bsp.mesh -> material |
| 57 | + # -- bsp.mesh.flags->VertexReservedX->transparency flags |
| 58 | + # --- split into worldspawn opaque, decal & transparent |
| 59 | + return mesh_name |
| 60 | + # model = bpy.data.models.new(mesh_name, mesh) |
| 61 | + # bpy.context.scene.collection.children.add(model) |
0 commit comments