From 706c32431d450bfebf42031dd826e496dca8032f Mon Sep 17 00:00:00 2001 From: William Herald Snyder Date: Sun, 1 Nov 2020 11:48:07 -0500 Subject: [PATCH] msh_reader refined, more chunks implemented --- addons/io_scene_swbf_msh/msh_model.py | 1 + addons/io_scene_swbf_msh/msh_reader.py | 23 ++---- addons/io_scene_swbf_msh/msh_scene.py | 2 + addons/io_scene_swbf_msh/msh_scene_read.py | 82 +++++++++++++--------- addons/io_scene_swbf_msh/msh_to_blend.py | 29 ++++---- 5 files changed, 71 insertions(+), 66 deletions(-) diff --git a/addons/io_scene_swbf_msh/msh_model.py b/addons/io_scene_swbf_msh/msh_model.py index 589a274..4f1e29b 100644 --- a/addons/io_scene_swbf_msh/msh_model.py +++ b/addons/io_scene_swbf_msh/msh_model.py @@ -12,6 +12,7 @@ class ModelType(Enum): CLOTH = 2 BONE = 3 STATIC = 4 + SHADOWVOLUME = 6 class CollisionPrimitiveShape(Enum): SPHERE = 0 diff --git a/addons/io_scene_swbf_msh/msh_reader.py b/addons/io_scene_swbf_msh/msh_reader.py index c652683..3203955 100644 --- a/addons/io_scene_swbf_msh/msh_reader.py +++ b/addons/io_scene_swbf_msh/msh_reader.py @@ -3,18 +3,17 @@ import io import struct class Reader: - def __init__(self, file, chunk_id: str, parent=None, indent=0): + def __init__(self, file, parent=None, indent=0): self.file = file self.size: int = 0 self.size_pos = None self.parent = parent - self.header = chunk_id - self.indent = " " * indent + self.indent = " " * indent #for print debugging def __enter__(self): self.size_pos = self.file.tell() - self.file.seek(4,1) #skip header, will add check later + self.header = self.read_bytes(4).decode("utf-8") self.size = self.read_u32() padding_length = 4 - (self.size % 4) if self.size % 4 > 0 else 0 @@ -84,8 +83,8 @@ class Reader: - def read_child(self, child_id: str): - child = Reader(self.file, chunk_id=child_id, parent=self, indent=int(len(self.indent) / 2) + 1) + def read_child(self): + child = Reader(self.file, parent=self, indent=int(len(self.indent) / 2) + 1) return child @@ -103,16 +102,4 @@ class Reader: return self.end_pos - self.file.tell() >= 8 - MAX_SIZE: int = 2147483647 - 8 - -''' -with open("/Users/will/Desktop/spacedoortest/spa1_prop_impdoor.msh", "rb") as tst_stream: - with Reader(tst_stream, "HEDR") as hedr: - print(hedr.peak_next_header()) -''' - - - - - diff --git a/addons/io_scene_swbf_msh/msh_scene.py b/addons/io_scene_swbf_msh/msh_scene.py index 6c6f7fd..53266be 100644 --- a/addons/io_scene_swbf_msh/msh_scene.py +++ b/addons/io_scene_swbf_msh/msh_scene.py @@ -44,6 +44,8 @@ class Scene: materials: Dict[str, Material] = field(default_factory=dict) models: List[Model] = field(default_factory=list) + skeleton: List[int] = field(default_factory=list) + def create_scene(generate_triangle_strips: bool, apply_modifiers: bool, export_target: str) -> Scene: """ Create a msh Scene from the active Blender scene. """ diff --git a/addons/io_scene_swbf_msh/msh_scene_read.py b/addons/io_scene_swbf_msh/msh_scene_read.py index 9faa78f..36657f8 100644 --- a/addons/io_scene_swbf_msh/msh_scene_read.py +++ b/addons/io_scene_swbf_msh/msh_scene_read.py @@ -16,7 +16,7 @@ def read_scene(input_file) -> Scene: scene.models = [] scene.materials = {} - with Reader(file=input_file, chunk_id="HEDR") as hedr: + with Reader(file=input_file) as hedr: while hedr.could_have_child(): @@ -24,7 +24,7 @@ def read_scene(input_file) -> Scene: if "MSH2" in next_header: - with hedr.read_child("MSH2") as msh2: + with hedr.read_child() as msh2: materials_list = [] @@ -33,26 +33,37 @@ def read_scene(input_file) -> Scene: next_header = msh2.peak_next_header() if "SINF" in next_header: - with msh2.read_child("SINF") as sinf: + with msh2.read_child() as sinf: pass elif "MATL" in next_header: - with msh2.read_child("MATL") as matl: + with msh2.read_child() as matl: materials_list += _read_matl_and_get_materials_list(matl) for i,mat in enumerate(materials_list): scene.materials[mat.name] = mat elif "MODL" in next_header: while ("MODL" in msh2.peak_next_header()): - with msh2.read_child("MODL") as modl: + with msh2.read_child() as modl: scene.models.append(_read_modl(modl, materials_list)) else: - with hedr.read_child("NULL") as unknown: + with hedr.read_child() as unknown: pass + elif "SKL2" in next_header: + with hedr.read_child() as skl2: + num_bones = skl2.read_u32() + scene.skeleton = [skl2.read_u32(5)[0] for i in range(num_bones)] + print("Skeleton models: ") + for crc_hash in scene.skeleton: + for model in scene.models: + if crc_hash == crc(model.name): + print("\t" + model.name + " with type: " + str(model.model_type)) + + else: - with hedr.read_child("NULL") as unknown: + with hedr.read_child() as unknown: pass return scene @@ -64,7 +75,7 @@ def _read_matl_and_get_materials_list(matl: Reader) -> List[Material]: num_mats = matl.read_u32() for _ in range(num_mats): - with matl.read_child("MATD") as matd: + with matl.read_child() as matd: materials_list.append(_read_matd(matd)) return materials_list @@ -80,36 +91,36 @@ def _read_matd(matd: Reader) -> Material: next_header = matd.peak_next_header() if "NAME" in next_header: - with matd.read_child("NAME") as name: + with matd.read_child() as name: mat.name = name.read_string() elif "DATA" in next_header: - with matd.read_child("DATA") as data: + with matd.read_child() as data: data.read_f32(4) # Diffuse Color (Seams to get ignored by modelmunge) mat.specular_color = data.read_f32(4) data.read_f32(4) # Ambient Color (Seams to get ignored by modelmunge and Zero(?)) data.read_f32() # Specular Exponent/Decay (Gets ignored by RedEngine in SWBFII for all known materials) elif "ATRB" in next_header: - with matd.read_child("ATRB") as atrb: + with matd.read_child() as atrb: mat.flags = atrb.read_u8() mat.rendertype = atrb.read_u8() mat.data = atrb.read_u8(2) elif "TX0D" in next_header: - with matd.read_child("TX0D") as tx0d: + with matd.read_child() as tx0d: mat.texture0 = tx0d.read_string() elif "TX1D" in next_header: - with matd.read_child("TX1D") as tx1d: + with matd.read_child() as tx1d: mat.texture1 = tx1d.read_string() elif "TX2D" in next_header: - with matd.read_child("TX2D") as tx2d: + with matd.read_child() as tx2d: mat.texture2 = tx2d.read_string() elif "TX3D" in next_header: - with matd.read_child("TX3D") as tx3d: + with matd.read_child() as tx3d: mat.texture3 = tx3d.read_string() else: @@ -127,50 +138,50 @@ def _read_modl(modl: Reader, materials_list: List[Material]) -> Model: next_header = modl.peak_next_header() if "MTYP" in next_header: - with modl.read_child("MTYP") as mtyp: + with modl.read_child() as mtyp: model.model_type = ModelType(mtyp.read_u32()) elif "MNDX" in next_header: - with modl.read_child("MNDX") as mndx: + with modl.read_child() as mndx: pass elif "NAME" in next_header: - with modl.read_child("NAME") as name: + with modl.read_child() as name: model.name = name.read_string() elif "PRNT" in next_header: - with modl.read_child("PRNT") as prnt: + with modl.read_child() as prnt: model.parent = prnt.read_string() elif "FLGS" in next_header: - with modl.read_child("FLGS") as flgs: + with modl.read_child() as flgs: model.hidden = flgs.read_u32() elif "TRAN" in next_header: - with modl.read_child("TRAN") as tran: + with modl.read_child() as tran: model.transform = _read_tran(tran) elif "GEOM" in next_header: model.geometry = [] - with modl.read_child("GEOM") as geom: + with modl.read_child() as geom: next_header_modl = geom.peak_next_header() if "SEGM" in next_header_modl: - with geom.read_child("SEGM") as segm: + with geom.read_child() as segm: model.geometry.append(_read_segm(segm, materials_list)) elif "SWCI" in next_header: prim = CollisionPrimitive() - with modl.read_child("SWCI") as swci: - prim.shape.value = swci.read_u32() + with modl.read_child() as swci: + prim.shape = CollisionPrimitiveShape(swci.read_u32()) prim.radius = swci.read_f32() prim.height = swci.read_f32() prim.length = swci.read_f32() model.collisionprimitive = prim else: - with modl.read_child("NULL") as unknown: + with modl.read_child() as unknown: pass return model @@ -198,18 +209,18 @@ def _read_segm(segm: Reader, materials_list: List[Material]) -> GeometrySegment: next_header = segm.peak_next_header() if "MATI" in next_header: - with segm.read_child("MATI") as mati: + with segm.read_child() as mati: geometry_seg.material_name = materials_list[mati.read_u32()].name elif "POSL" in next_header: - with segm.read_child("POSL") as posl: + with segm.read_child() as posl: num_positions = posl.read_u32() for _ in range(num_positions): geometry_seg.positions.append(Vector(posl.read_f32(3))) elif "NRML" in next_header: - with segm.read_child("NRML") as nrml: + with segm.read_child() as nrml: num_normals = nrml.read_u32() for _ in range(num_positions): @@ -218,21 +229,21 @@ def _read_segm(segm: Reader, materials_list: List[Material]) -> GeometrySegment: elif "CLRL" in next_header: geometry_seg.colors = [] - with segm.read_child("CLRL") as clrl: + with segm.read_child() as clrl: num_colors = clrl.read_u32() for _ in range(num_colors): geometry_seg.colors += unpack_color(clrl.read_u32()) elif "UV0L" in next_header: - with segm.read_child("UV0L") as uv0l: + with segm.read_child() as uv0l: num_texcoords = uv0l.read_u32() for _ in range(num_texcoords): geometry_seg.texcoords.append(Vector(uv0l.read_f32(2))) elif "NDXL" in next_header: - with segm.read_child("NDXL") as ndxl: + with segm.read_child() as ndxl: num_polygons = ndxl.read_u32() for _ in range(num_polygons): @@ -240,23 +251,24 @@ def _read_segm(segm: Reader, materials_list: List[Material]) -> GeometrySegment: geometry_seg.polygons.append(polygon) elif "NDXT" in next_header: - with segm.read_child("NDXT") as ndxt: + with segm.read_child() as ndxt: num_tris = ndxt.read_u32() for _ in range(num_tris): geometry_seg.triangles.append(ndxt.read_u16(3)) elif "STRP" in next_header: - with segm.read_child("STRP") as strp: + with segm.read_child() as strp: pass if segm.read_u16 != 0: #trailing 0 bug https://schlechtwetterfront.github.io/ze_filetypes/msh.html#STRP segm.skip_bytes(-2) else: - with segm.read_child("NULL") as unknown: + with segm.read_child() as unknown: pass return geometry_seg + diff --git a/addons/io_scene_swbf_msh/msh_to_blend.py b/addons/io_scene_swbf_msh/msh_to_blend.py index a5c3495..ac3e933 100644 --- a/addons/io_scene_swbf_msh/msh_to_blend.py +++ b/addons/io_scene_swbf_msh/msh_to_blend.py @@ -12,21 +12,18 @@ from .msh_model import * from .msh_model_utilities import * from .msh_utilities import * from .msh_model_gather import * +from .crc import * -def extract_models(models, materials_map): +def extract_models(scene: Scene, materials_map): model_map = {} - for model in sort_by_parent(models): + for model in sort_by_parent(scene.models): - if model.model_type != ModelType.STATIC: - new_obj = bpy.data.objects.new(model.name, None) - new_obj.empty_display_size = 1 - new_obj.empty_display_type = 'PLAIN_AXES' - - else: + if model.model_type == ModelType.STATIC: + new_mesh = bpy.data.meshes.new(model.name) verts = [] faces = [] @@ -67,10 +64,10 @@ def extract_models(models, materials_map): new_obj = bpy.data.objects.new(new_mesh.name, new_mesh) + ''' Assign Materials - will do per segment later... ''' - if mat_name: material = materials_map[mat_name] @@ -78,6 +75,12 @@ def extract_models(models, materials_map): new_obj.data.materials[0] = material else: new_obj.data.materials.append(material) + + else: + + new_obj = bpy.data.objects.new(model.name, None) + new_obj.empty_display_size = 1 + new_obj.empty_display_type = 'PLAIN_AXES' @@ -104,7 +107,7 @@ def extract_materials(scene: Scene) -> Dict[str,bpy.types.Material]: new_mat.use_nodes = True bsdf = new_mat.node_tree.nodes["Principled BSDF"] texImage = new_mat.node_tree.nodes.new('ShaderNodeTexImage') - texImage.image = bpy.data.images.load("/Users/will/Desktop/grad.png") + texImage.image = bpy.data.images.load("/Users/will/Desktop/grad.jpg") new_mat.node_tree.links.new(bsdf.inputs['Base Color'], texImage.outputs['Color']) extracted_materials[material_name] = new_mat @@ -114,9 +117,9 @@ def extract_materials(scene: Scene) -> Dict[str,bpy.types.Material]: def extract_scene(scene: Scene): - - matmap = extract_materials(scene) - extract_models(scene.models, matmap) + return None + #matmap = extract_materials(scene) + #extract_models(scene, matmap)