From 3b999f550d75a32ce53ab8de81377cb915561f46 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Wed, 17 Feb 2021 15:09:35 -0500 Subject: [PATCH 1/3] Fix child font objects. Font objects were exported as a completely different SceneObject, causing the parenting relationship to be broken. This ensures that the drawable is properly attached to the correct SceneObject. --- korman/exporter/convert.py | 7 +++++-- korman/exporter/mesh.py | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/korman/exporter/convert.py b/korman/exporter/convert.py index 55cb30a..5f2555d 100644 --- a/korman/exporter/convert.py +++ b/korman/exporter/convert.py @@ -287,14 +287,17 @@ class Exporter: def _export_mesh_blobj(self, so, bo): self.animation.convert_object_animations(bo, so) if bo.data.materials: - self.mesh.export_object(bo) + self.mesh.export_object(bo, so) else: self.report.msg("No material(s) on the ObData, so no drawables", indent=1) def _export_font_blobj(self, so, bo): self.animation.convert_object_animations(bo, so) with utils.temporary_mesh_object(bo) as meshObj: - self._export_mesh_blobj(so, meshObj) + if bo.data.materials: + self.mesh.export_object(meshObj, so) + else: + self.report.msg("No material(s) on the ObData, so no drawables", indent=1) def _export_referenced_node_trees(self): self.report.progress_advance() diff --git a/korman/exporter/mesh.py b/korman/exporter/mesh.py index e629395..e8f1ac7 100644 --- a/korman/exporter/mesh.py +++ b/korman/exporter/mesh.py @@ -575,7 +575,7 @@ class MeshConverter(_MeshManager): # Sequence of tuples (material_index, material) return sorted(((i, material_source[i]) for i in valid_materials), key=lambda x: x[0]) - def export_object(self, bo): + def export_object(self, bo, so : plSceneObject): # If this object has modifiers, then it's a unique mesh, and we don't need to try caching it # Otherwise, let's *try* to share meshes as best we can... if bo.modifiers: @@ -587,7 +587,7 @@ class MeshConverter(_MeshManager): # Create the DrawInterface if drawables: - diface = self._mgr.find_create_object(plDrawInterface, bl=bo) + diface = self._mgr.find_create_object(plDrawInterface, bl=bo, so=so) for dspan_key, idx in drawables: diface.addDrawable(dspan_key, idx) From 9a9bfa9ed67d4cf704b8e88da0aa56b216375b06 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Wed, 17 Feb 2021 17:29:39 -0500 Subject: [PATCH 2/3] Fix child physicals appearing in the wrong location. A few observed problems: - In PotS, any physical parented to another object fell through the floor on link in. - In MOUL, physicals in a subworld were exported in the wrong coordinate system. They were exported in local-to-world space, but MOUL expects them in local-to-subworld space. - In PotS, any scaled physical parented to another object wiped out the visual (but not physical) scaling due to an improper flag setting. --- korman/exporter/physics.py | 55 +++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/korman/exporter/physics.py b/korman/exporter/physics.py index 4a4aa50..3806342 100644 --- a/korman/exporter/physics.py +++ b/korman/exporter/physics.py @@ -60,9 +60,7 @@ class PhysicsConverter: indices += (v[0], v[2], v[3],) return indices - def _convert_mesh_data(self, bo, physical, local_space, indices=True): - mat = bo.matrix_world - + def _convert_mesh_data(self, bo, physical, local_space, mat, indices=True): mesh = bo.to_mesh(bpy.context.scene, True, "RENDER", calc_tessface=False) with TemporaryObject(mesh, bpy.data.meshes.remove): if local_space: @@ -211,29 +209,39 @@ class PhysicsConverter: if tree_xformed: bo_xformed = bo.plasma_object.has_transform_animation + # Always pin these objects - otherwise they may start falling through the floor. + _set_phys_prop(plSimulationInterface.kPinned, simIface, physical) + # MOUL: only objects that have animation data are kPhysAnim if ver != pvMoul or bo_xformed: _set_phys_prop(plSimulationInterface.kPhysAnim, simIface, physical) - # PotS: objects inheriting parent animation only are not pinned - # MOUL: animated objects in subworlds are not pinned - if bo_xformed and (ver != pvMoul or subworld is None): - _set_phys_prop(plSimulationInterface.kPinned, simIface, physical) - # MOUL: child objects are kPassive - if ver == pvMoul and bo.parent is not None: - _set_phys_prop(plSimulationInterface.kPassive, simIface, physical) - # FilterCoordinateInterfaces are kPassive - if bo.plasma_object.ci_type == plFilterCoordInterface: + + # Any physical that is parented by not kickable (dynamic) is passive - + # meaning we don't need to report back any changes from physics. Same for + # plFilterCoordInterface, which filters out some axes. + if (bo.parent is not None and not mod.dynamic) or bo.plasma_object.ci_type == plFilterCoordInterface: _set_phys_prop(plSimulationInterface.kPassive, simIface, physical) # If the mass is zero, then we will fail to animate. Fix that. if physical.mass == 0.0: physical.mass = 1.0 + # Different Plasma versions have different ways they expect to get physical transforms. + # With Havok, massless objects are in absolute worldspace while massed (movable) objects + # are in object-local space. + # In PhysX, objects with a coordinate interface are in local to SUBWORLD space, otherwise + # they are in absolute worldspace. if ver <= pvPots: - local_space = physical.mass > 0.0 + local_space, mat = physical.mass > 0.0, bo.matrix_world + elif ver == pvMoul: + if self._exporter().has_coordiface(bo): + local_space = True + mat = subworld.matrix_world.inverted() * bo.matrix_world if subworld else bo.matrix_world + else: + local_space, mat = False, bo.matrix_world else: - local_space = self._exporter().has_coordiface(bo) - self._bounds_converters[bounds](bo, physical, local_space) + raise NotImplementedError("ODE physical transform") + self._bounds_converters[bounds](bo, physical, local_space, mat) else: simIface = so.sim.object physical = simIface.physical.object @@ -245,14 +253,14 @@ class PhysicsConverter: self._apply_props(simIface, physical, kwargs) - def _export_box(self, bo, physical, local_space): + def _export_box(self, bo, physical, local_space, mat): """Exports box bounds based on the object""" physical.boundsType = plSimDefs.kBoxBounds - vertices = self._convert_mesh_data(bo, physical, local_space, indices=False) + vertices = self._convert_mesh_data(bo, physical, local_space, mat, indices=False) physical.calcBoxBounds(vertices) - def _export_hull(self, bo, physical, local_space): + def _export_hull(self, bo, physical, local_space, mat): """Exports convex hull bounds based on the object""" physical.boundsType = plSimDefs.kHullBounds @@ -260,7 +268,6 @@ class PhysicsConverter: # bake them to convex hulls. Specifically, Windows 32-bit w/PhysX 2.6. Everything else just # needs to have us provide some friendlier data... with bmesh_from_object(bo) as mesh: - mat = bo.matrix_world if local_space: physical.pos = hsVector3(*mat.to_translation()) physical.rot = utils.quaternion(mat.to_quaternion()) @@ -273,24 +280,24 @@ class PhysicsConverter: verts = itertools.takewhile(lambda x: isinstance(x, BMVert), result["geom"]) physical.verts = [hsVector3(*i.co) for i in verts] - def _export_sphere(self, bo, physical, local_space): + def _export_sphere(self, bo, physical, local_space, mat): """Exports sphere bounds based on the object""" physical.boundsType = plSimDefs.kSphereBounds - vertices = self._convert_mesh_data(bo, physical, local_space, indices=False) + vertices = self._convert_mesh_data(bo, physical, local_space, mat, indices=False) physical.calcSphereBounds(vertices) - def _export_trimesh(self, bo, physical, local_space): + def _export_trimesh(self, bo, physical, local_space, mat): """Exports an object's mesh as exact physical bounds""" # Triangle meshes MAY optionally specify a proxy object to fetch the triangles from... mod = bo.plasma_modifiers.collision if mod.enabled and mod.proxy_object is not None: physical.boundsType = plSimDefs.kProxyBounds - vertices, indices = self._convert_mesh_data(mod.proxy_object, physical, local_space) + vertices, indices = self._convert_mesh_data(mod.proxy_object, physical, local_space, mat) else: physical.boundsType = plSimDefs.kExplicitBounds - vertices, indices = self._convert_mesh_data(bo, physical, local_space) + vertices, indices = self._convert_mesh_data(bo, physical, local_space, mat) physical.verts = vertices physical.indices = indices From 59d852d3306e1169e8e75a3b4e7f963bc9551411 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Wed, 17 Feb 2021 18:29:07 -0500 Subject: [PATCH 3/3] Fix kickables in subworlds. --- korman/exporter/physics.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/korman/exporter/physics.py b/korman/exporter/physics.py index 3806342..4692354 100644 --- a/korman/exporter/physics.py +++ b/korman/exporter/physics.py @@ -210,7 +210,9 @@ class PhysicsConverter: bo_xformed = bo.plasma_object.has_transform_animation # Always pin these objects - otherwise they may start falling through the floor. - _set_phys_prop(plSimulationInterface.kPinned, simIface, physical) + # Unless you've marked it kickable... + if not mod.dynamic: + _set_phys_prop(plSimulationInterface.kPinned, simIface, physical) # MOUL: only objects that have animation data are kPhysAnim if ver != pvMoul or bo_xformed: