From f220af7fde2d1892d2475a3adcfbaa4b2ee075b1 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Fri, 29 Nov 2024 19:09:40 +0100 Subject: [PATCH] Fix mesh orientation for gltf --- examples/gltf_scenes.py | 36 +++++++++++--------------- moderngl_window/loaders/scene/gltf2.py | 30 ++++++++++----------- moderngl_window/scene/node.py | 12 ++++----- 3 files changed, 36 insertions(+), 42 deletions(-) diff --git a/examples/gltf_scenes.py b/examples/gltf_scenes.py index 9d3f98b..ccd38b9 100644 --- a/examples/gltf_scenes.py +++ b/examples/gltf_scenes.py @@ -26,19 +26,19 @@ def __init__(self, **kwargs): # --- glTF-Sample-Models --- # self.scene = self.load_scene("2CylinderEngine/glTF-Binary/2CylinderEngine.glb") - # self.scene = self.load_scene('CesiumMilkTruck/glTF-Embedded/CesiumMilkTruck.gltf') + # self.scene = self.load_scene("CesiumMilkTruck/glTF-Embedded/CesiumMilkTruck.gltf") # self.scene = self.load_scene("CesiumMilkTruck/glTF-Binary/CesiumMilkTruck.glb") # self.scene = self.load_scene("CesiumMilkTruck/glTF/CesiumMilkTruck.gltf") - # self.scene = self.load_scene("Sponza/glTF/Sponza.gltf") + self.scene = self.load_scene("Sponza/glTF/Sponza.gltf") # self.scene = self.load_scene("Lantern/glTF-Binary/Lantern.glb") # self.scene = self.load_scene("Buggy/glTF-Binary/Buggy.glb") - self.scene = self.load_scene("VC/glTF-Binary/VC.glb") - # self.scene = self.load_scene('DamagedHelmet/glTF-Binary/DamagedHelmet.glb') + # self.scene = self.load_scene("VC/glTF-Binary/VC.glb") + # self.scene = self.load_scene("DamagedHelmet/glTF-Binary/DamagedHelmet.glb") # self.scene = self.load_scene("BoxInterleaved/glTF/BoxInterleaved.gltf") # self.scene = self.load_scene("OrientationTest/glTF/OrientationTest.gltf") # self.scene = self.load_scene("AntiqueCamera/glTF/AntiqueCamera.gltf") # self.scene = self.load_scene("BoomBox/glTF/BoomBox.gltf") - # self.scene = self.load_scene('Box/glTF/Box.gltf') + # self.scene = self.load_scene("Box/glTF/Box.gltf") # self.scene = self.load_scene("BoxTextured/glTF/BoxTextured.gltf") # self.scene = self.load_scene( # "BoxTexturedNonPowerOfTwo/glTF/BoxTexturedNonPowerOfTwo.gltf" @@ -50,20 +50,14 @@ def __init__(self, **kwargs): # self.scene = self.load_scene("Fox/glTF/Fox.gltf") # self.scene = self.load_scene("GearboxAssy/glTF/GearboxAssy.gltf") # self.scene = self.load_scene("ReciprocatingSaw/glTF/ReciprocatingSaw.gltf") - # self.scene = self.load_scene('RiggedFigure/glTF/RiggedFigure.gltf') + # self.scene = self.load_scene("RiggedFigure/glTF/RiggedFigure.gltf") # self.scene = self.load_scene("RiggedSimple/glTF/RiggedSimple.gltf") # self.scene = self.load_scene("SciFiHelmet/glTF/SciFiHelmet.gltf") # self.scene = self.load_scene("SimpleMeshes/glTF/SimpleMeshes.gltf") - # self.scene = self.load_scene( - # "SimpleSparseAccessor/glTF/SimpleSparseAccessor.gltf" - # ) + # self.scene = self.load_scene("SimpleSparseAccessor/glTF/SimpleSparseAccessor.gltf") # self.scene = self.load_scene("Suzanne/glTF/Suzanne.gltf") - # self.scene = self.load_scene( - # "TextureCoordinateTest/glTF/TextureCoordinateTest.gltf" - # ) - # self.scene = self.load_scene( - # "TextureSettingsTest/glTF/TextureSettingsTest.gltf" - # ) + # self.scene = self.load_scene("TextureCoordinateTest/glTF/TextureCoordinateTest.gltf") + # self.scene = self.load_scene("TextureSettingsTest/glTF/TextureSettingsTest.gltf") # self.scene = self.load_scene("VertexColorTest/glTF/VertexColorTest.gltf") # self.scene = self.load_scene("WaterBottle/glTF/WaterBottle.gltf") @@ -96,12 +90,12 @@ def on_render(self, time: float, frame_time: float): ) # Draw bounding boxes - self.scene.draw_bbox( - projection_matrix=self.camera.projection.matrix, - camera_matrix=camera_matrix, - children=True, - color=(0.75, 0.75, 0.75), - ) + # self.scene.draw_bbox( + # projection_matrix=self.camera.projection.matrix, + # camera_matrix=camera_matrix, + # children=True, + # color=(0.75, 0.75, 0.75), + # ) # self.scene.draw_wireframe( # projection_matrix=self.camera.projection.matrix, diff --git a/moderngl_window/loaders/scene/gltf2.py b/moderngl_window/loaders/scene/gltf2.py index 6983a57..7e0d70c 100644 --- a/moderngl_window/loaders/scene/gltf2.py +++ b/moderngl_window/loaders/scene/gltf2.py @@ -266,12 +266,9 @@ def load_nodes(self) -> None: def load_node(self, meta: GLTFNode, parent: Optional[Node] = None) -> Node: """Load a single node""" # Create the node - node = Node(name=meta.name) + node = Node(name=meta.name, matrix=meta.matrix) self.scene.nodes.append(node) - if meta.matrix is not None: - node.matrix = glm.mat4(meta.matrix) - if meta.mesh is not None: # Since we split up meshes with multiple primitives, this can be a list # If only one mesh we set it on the node as normal @@ -736,21 +733,21 @@ class GLTFNode: def __init__(self, data: dict[str, Any]) -> None: self.name = data.get("name") self.children = data.get("children") - self.matrix = data.get("matrix") self.mesh = data.get("mesh") self.camera = data.get("camera") + _matrix = data.get("matrix") + self.matrix = glm.mat4(*_matrix) if _matrix is not None else glm.mat4() + self.translation = data.get("translation") self.rotation = data.get("rotation") self.scale = data.get("scale") - if self.matrix is not None: - self.matrix = glm.mat4(*self.matrix) - else: - self.matrix = glm.mat4() - - if self.translation is not None: - self.matrix = self.matrix * glm.translate(glm.vec3(*self.translation)) + trans_mat = ( + glm.translate(glm.vec3(*self.translation)) + if self.translation is not None + else glm.mat4() + ) if self.rotation is not None: quat = glm.quat( @@ -759,10 +756,13 @@ def __init__(self, data: dict[str, Any]) -> None: z=self.rotation[2], w=self.rotation[3], ) - self.matrix = self.matrix * glm.mat4_cast(quat) + rot_mat = glm.mat4_cast(quat) + else: + rot_mat = glm.mat4() + + scale_mat = glm.scale(self.scale) if self.scale is not None else glm.mat4() - if self.scale is not None: - self.matrix = self.matrix * glm.scale(self.scale) + self.matrix = self.matrix * trans_mat * rot_mat * scale_mat @property def has_children(self) -> bool: diff --git a/moderngl_window/scene/node.py b/moderngl_window/scene/node.py index 2a5a34b..673ad8f 100644 --- a/moderngl_window/scene/node.py +++ b/moderngl_window/scene/node.py @@ -40,7 +40,7 @@ def __init__( # Local node matrix self._matrix = matrix # Global matrix - self._matrix_global: Optional[glm.mat4] = None + self._matrix_global = glm.mat4(1.0) self._children: list["Node"] = [] @@ -202,22 +202,22 @@ def calc_global_bbox( return bbox_min, bbox_max - def calc_model_mat(self, model_matrix: glm.mat4) -> None: + def calc_model_mat(self, parent_matrix: glm.mat4) -> None: """Calculate the model matrix related to all parents. Args: - model_matrix (numpy.ndarray): model matrix + parent_matrix: Matrix for parent node """ if self._matrix is not None: - self._matrix_global = self._matrix * model_matrix + self._matrix_global = parent_matrix * self._matrix for child in self._children: child.calc_model_mat(self._matrix_global) else: - self._matrix_global = model_matrix + self._matrix_global = parent_matrix for child in self._children: - child.calc_model_mat(model_matrix) + child.calc_model_mat(parent_matrix) def __repr__(self) -> str: return "".format(self.name)