From 049803f750d96d802533663a12e5b673919b79c0 Mon Sep 17 00:00:00 2001 From: William Herald Snyder Date: Sun, 1 Nov 2020 18:11:26 -0500 Subject: [PATCH] Reader class simplified --- addons/io_scene_swbf_msh/__init__.py | 3 +- addons/io_scene_swbf_msh/msh_model.py | 4 +- addons/io_scene_swbf_msh/msh_scene_read.py | 84 ++++++++++++++++++---- addons/io_scene_swbf_msh/msh_to_blend.py | 44 ++++++++---- 4 files changed, 104 insertions(+), 31 deletions(-) diff --git a/addons/io_scene_swbf_msh/__init__.py b/addons/io_scene_swbf_msh/__init__.py index e432118..cab7f18 100644 --- a/addons/io_scene_swbf_msh/__init__.py +++ b/addons/io_scene_swbf_msh/__init__.py @@ -62,6 +62,7 @@ from .msh_scene_read import read_scene from .msh_material_properties import * from .msh_to_blend import * + class ExportMSH(Operator, ExportHelper): """ Export the current scene as a SWBF .msh file. """ @@ -134,7 +135,7 @@ class ImportMSH(Operator, ImportHelper): def execute(self, context): with open(self.filepath, 'rb') as input_file: - extract_scene(read_scene(input_file)) + extract_scene(self.filepath, read_scene(input_file)) return {'FINISHED'} def menu_func_import(self, context): diff --git a/addons/io_scene_swbf_msh/msh_model.py b/addons/io_scene_swbf_msh/msh_model.py index 4f1e29b..c23c5c5 100644 --- a/addons/io_scene_swbf_msh/msh_model.py +++ b/addons/io_scene_swbf_msh/msh_model.py @@ -16,9 +16,9 @@ class ModelType(Enum): class CollisionPrimitiveShape(Enum): SPHERE = 0 - # ELLIPSOID = 1 + ELLIPSOID = 1 CYLINDER = 2 - # MESH = 3 + MESH = 3 BOX = 4 @dataclass diff --git a/addons/io_scene_swbf_msh/msh_scene_read.py b/addons/io_scene_swbf_msh/msh_scene_read.py index 36657f8..b774d5a 100644 --- a/addons/io_scene_swbf_msh/msh_scene_read.py +++ b/addons/io_scene_swbf_msh/msh_scene_read.py @@ -10,6 +10,8 @@ from .msh_utilities import * from .crc import * +envls = [] + def read_scene(input_file) -> Scene: scene = Scene() @@ -52,20 +54,27 @@ def read_scene(input_file) -> Scene: 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)) + 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)) + elif "ANM2" in next_header: + with hedr.read_child() as anm2: + _read_anm2(anm2, scene.models) else: - with hedr.read_child() as unknown: + with hedr.read_child() as null: pass + print("Models indexed by ENVLs: ") + for envl_index in set(envls): + print("\t" + scene.models[envl_index].name) + return scene @@ -164,12 +173,23 @@ def _read_modl(modl: Reader, materials_list: List[Material]) -> Model: elif "GEOM" in next_header: model.geometry = [] with modl.read_child() as geom: + while geom.could_have_child(): + next_header_geom = geom.peak_next_header() - next_header_modl = geom.peak_next_header() + if "SEGM" in next_header_geom: + with geom.read_child() as segm: + model.geometry.append(_read_segm(segm, materials_list)) - if "SEGM" in next_header_modl: - with geom.read_child() as segm: - model.geometry.append(_read_segm(segm, materials_list)) + elif "ENVL" in next_header_geom: + with geom.read_child() as envl: + global envls + num_indicies = envl.read_u32() + print("reading ENVL with " + str(num_indicies) + " indicies") + envls += [envl.read_u32() for _ in range(num_indicies)] + + else: + with geom.read_child() as null: + pass elif "SWCI" in next_header: prim = CollisionPrimitive() @@ -191,7 +211,7 @@ def _read_tran(tran: Reader) -> ModelTransform: xform = ModelTransform() - tran.skip_bytes(4 * 3) #ignore scale + tran.skip_bytes(12) #ignore scale rot = tran.read_f32(4) xform.rotation = Quaternion((rot[3], rot[0], rot[1], rot[2])) @@ -264,6 +284,10 @@ def _read_segm(segm: Reader, materials_list: List[Material]) -> GeometrySegment: if segm.read_u16 != 0: #trailing 0 bug https://schlechtwetterfront.github.io/ze_filetypes/msh.html#STRP segm.skip_bytes(-2) + elif "WGHT" in next_header: + with segm.read_child() as null: + pass + else: with segm.read_child() as unknown: pass @@ -272,3 +296,35 @@ def _read_segm(segm: Reader, materials_list: List[Material]) -> GeometrySegment: +def _read_anm2(anm2: Reader, models): + + hash_dict = {} + for model in models: + hash_dict[crc(model.name)] = model.name + + while anm2.could_have_child(): + + next_header = anm2.peak_next_header() + + if "CYCL" in next_header: + with anm2.read_child() as cycl: + pass + + elif "KFR3" in next_header: + with anm2.read_child() as kfr3: + + num_bones = kfr3.read_u32() + + for _ in range(num_bones): + + kfr3.read_u32() + + frametype = kfr3.read_u32() + + num_loc_frames = kfr3.read_u32() + num_rot_frames = kfr3.read_u32() + + kfr3.skip_bytes(16 * num_loc_frames + 20 * num_rot_frames) + + + diff --git a/addons/io_scene_swbf_msh/msh_to_blend.py b/addons/io_scene_swbf_msh/msh_to_blend.py index ac3e933..c2715ce 100644 --- a/addons/io_scene_swbf_msh/msh_to_blend.py +++ b/addons/io_scene_swbf_msh/msh_to_blend.py @@ -14,6 +14,8 @@ from .msh_utilities import * from .msh_model_gather import * from .crc import * +import os + def extract_models(scene: Scene, materials_map): @@ -21,9 +23,13 @@ def extract_models(scene: Scene, materials_map): model_map = {} for model in sort_by_parent(scene.models): + new_obj = None + + if model.name.startswith("p_") or "collision" in model.name: + continue + + if model.model_type == ModelType.STATIC or model.model_type == ModelType.SKIN: - if model.model_type == ModelType.STATIC: - new_mesh = bpy.data.meshes.new(model.name) verts = [] faces = [] @@ -42,10 +48,11 @@ def extract_models(scene: Scene, materials_map): offset += len(seg.positions) new_mesh.from_pydata(verts, [], faces) + new_mesh.update() new_mesh.validate() - + ''' edit_mesh = bmesh.new() edit_mesh.from_mesh(new_mesh) @@ -59,12 +66,12 @@ def extract_models(scene: Scene, materials_map): loop[uvlayer].uv = tuple([texcoord.x, texcoord.y]) edit_mesh.to_mesh(new_mesh) - edit_mesh.free() + edit_mesh.free() + ''' + - new_obj = bpy.data.objects.new(new_mesh.name, new_mesh) - ''' Assign Materials - will do per segment later... ''' @@ -97,7 +104,7 @@ def extract_models(scene: Scene, materials_map): -def extract_materials(scene: Scene) -> Dict[str,bpy.types.Material]: +def extract_materials(folder_path: str, scene: Scene) -> Dict[str,bpy.types.Material]: extracted_materials = {} @@ -106,9 +113,16 @@ def extract_materials(scene: Scene) -> Dict[str,bpy.types.Material]: new_mat = bpy.data.materials.new(name=material_name) 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.jpg") - new_mat.node_tree.links.new(bsdf.inputs['Base Color'], texImage.outputs['Color']) + + tex_path_def = os.path.join(folder_path, scene.materials[material_name].texture0) + tex_path_alt = os.path.join(folder_path, "PC", scene.materials[material_name].texture0) + + tex_path = tex_path_def if os.path.exists(tex_path_def) else tex_path_alt + + if os.path.exists(tex_path): + texImage = new_mat.node_tree.nodes.new('ShaderNodeTexImage') + texImage.image = bpy.data.images.load(tex_path) + new_mat.node_tree.links.new(bsdf.inputs['Base Color'], texImage.outputs['Color']) extracted_materials[material_name] = new_mat @@ -116,10 +130,12 @@ def extract_materials(scene: Scene) -> Dict[str,bpy.types.Material]: -def extract_scene(scene: Scene): - return None - #matmap = extract_materials(scene) - #extract_models(scene, matmap) +def extract_scene(filepath: str, scene: Scene): + + folder = os.path.join(os.path.dirname(filepath),"") + + matmap = extract_materials(folder,scene) + extract_models(scene, matmap)