monkeyman192 / NMSDK

Custom Model importer for NMS
https://monkeyman192.github.io/NMSDK/
29 stars 9 forks source link

[BUG] Can't import scenes - material uniforms no longer at 0x218 #72

Closed kidheracles closed 3 years ago

kidheracles commented 3 years ago

Describe the bug All SCENE files no longer import successfully since 2.61

To Reproduce Execute tests/import_crystal.py with a current MbinCompiler.exe and unpacked 2.61 files

**Stack trace*** Traceback (most recent call last): File "\import_crystal.py", line 15, in File "C:\Program Files\Blender Foundation\Blender 2.83\2.83\scripts\modules\bpy\ops.py", line 201, in call ret = op_call(self.idname_py(), None, kw) RuntimeError: Error: Traceback (most recent call last): File "C:\Users\avanv\AppData\Roaming\Blender Foundation\Blender\2.83\scripts\addons\nmsdk\NMSDK.py", line 72, in execute importer.render_scene() File "C:\Users\avanv\AppData\Roaming\Blender Foundation\Blender\2.83\scripts\addons\nmsdk\ModelImporter\import_scene.py", line 336, in render_scene added_obj = self._add_mesh_to_scene(obj) File "C:\Users\avanv\AppData\Roaming\Blender Foundation\Blender\2.83\scripts\addons\nmsdk\ModelImporter\import_scene.py", line 854, in _add_mesh_to_scene material = create_material_node(mat_path, self.materials) File "C:\Users\avanv\AppData\Roaming\Blender Foundation\Blender\2.83\scripts\addons\nmsdk\NMS\material_node.py", line 58, in create_material_node rgb_input.outputs[0].default_value[0] = uniforms['gMaterialColourVec4'][0] # noqa KeyError: 'gMaterialColourVec4'

location: C:\Program Files\Blender Foundation\Blender 2.83\2.83\scripts\modules\bpy\ops.py:201

Error: Python script failed, check the message in the system console

Additional context Data map after read_material(): {'Name': 'Crystal_Large', 'Class': 'Models/Planets/Biomes/Common/Cry', 'CastShadow': True, 'Flags': [], 'Uniforms': {}, 'Samplers': {}}

That Class should be 'Opaque'

MbinCompiler representation for this material:

I will raise a pull request to jump over the new metamaterial element

bjj commented 3 years ago

Can confirm I applied linked 1dd0fab (resolving conflicts) against 676b9723 and I was able to load NMS Origins models.

diff --git a/ModelImporter/readers.py b/ModelImporter/readers.py
index fbc804c..8cddaa9 100644
--- a/ModelImporter/readers.py
+++ b/ModelImporter/readers.py
@@ -139,11 +139,15 @@ def read_material(fname):
         f.seek(0x60)
         # get name
         data['Name'] = read_string(f, 0x80)
+        # get metamaterial, introduced in 2.61
+        data['Metamaterial'] = read_string(f, 0x100)
         # get class
         data['Class'] = read_string(f, 0x20)
         # get whether it casts a shadow
-        f.seek(0xA4 + 0x60)
+        f.seek(0x4, 1)
         data['CastShadow'] = read_bool(f)
+        # save pointer for Flags Uniforms Samplers list headers
+        list_header_first = f.tell() + 0x1 + 0x80 + 0x80 + 0x2
         # get material flags
         data['Flags'] = list()
         f.seek(0x208)
@@ -153,7 +157,7 @@ def read_material(fname):
             data['Flags'].append(struct.unpack('<I', f.read(0x4))[0])
         # get uniforms
         data['Uniforms'] = dict()
-        f.seek(0x218)
+        f.seek(list_header_first + 0x10)
         list_offset, list_count = read_list_header(f)
         f.seek(list_offset, 1)
         for i in range(list_count):
@@ -163,7 +167,7 @@ def read_material(fname):
             f.seek(0x10, 1)
         # get samplers (texture paths)
         data['Samplers'] = dict()
-        f.seek(0x228)
+        f.seek(list_header_first + 0x20)
         list_offset, list_count = read_list_header(f)
         f.seek(list_offset, 1)
         for i in range(list_count):
monkeyman192 commented 3 years ago

Sorry, been real busy. I was planning on trying to sit down today and merge these PR's in and make some additional changes. Thanks for the confirmation also!

monkeyman192 commented 3 years ago

I think this can be closed as the PR fixing this has now been merged