Browse Source

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.
pull/235/head
Adam Johnson 4 years ago
parent
commit
9a9bfa9ed6
Signed by: Hoikas
GPG Key ID: 0B6515D6FF6F271E
  1. 55
      korman/exporter/physics.py

55
korman/exporter/physics.py

@ -60,9 +60,7 @@ class PhysicsConverter:
indices += (v[0], v[2], v[3],) indices += (v[0], v[2], v[3],)
return indices return indices
def _convert_mesh_data(self, bo, physical, local_space, indices=True): def _convert_mesh_data(self, bo, physical, local_space, mat, indices=True):
mat = bo.matrix_world
mesh = bo.to_mesh(bpy.context.scene, True, "RENDER", calc_tessface=False) mesh = bo.to_mesh(bpy.context.scene, True, "RENDER", calc_tessface=False)
with TemporaryObject(mesh, bpy.data.meshes.remove): with TemporaryObject(mesh, bpy.data.meshes.remove):
if local_space: if local_space:
@ -211,29 +209,39 @@ class PhysicsConverter:
if tree_xformed: if tree_xformed:
bo_xformed = bo.plasma_object.has_transform_animation 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 # MOUL: only objects that have animation data are kPhysAnim
if ver != pvMoul or bo_xformed: if ver != pvMoul or bo_xformed:
_set_phys_prop(plSimulationInterface.kPhysAnim, simIface, physical) _set_phys_prop(plSimulationInterface.kPhysAnim, simIface, physical)
# PotS: objects inheriting parent animation only are not pinned
# MOUL: animated objects in subworlds are not pinned # Any physical that is parented by not kickable (dynamic) is passive -
if bo_xformed and (ver != pvMoul or subworld is None): # meaning we don't need to report back any changes from physics. Same for
_set_phys_prop(plSimulationInterface.kPinned, simIface, physical) # plFilterCoordInterface, which filters out some axes.
# MOUL: child objects are kPassive if (bo.parent is not None and not mod.dynamic) or bo.plasma_object.ci_type == plFilterCoordInterface:
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:
_set_phys_prop(plSimulationInterface.kPassive, simIface, physical) _set_phys_prop(plSimulationInterface.kPassive, simIface, physical)
# If the mass is zero, then we will fail to animate. Fix that. # If the mass is zero, then we will fail to animate. Fix that.
if physical.mass == 0.0: if physical.mass == 0.0:
physical.mass = 1.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: 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: else:
local_space = self._exporter().has_coordiface(bo) raise NotImplementedError("ODE physical transform")
self._bounds_converters[bounds](bo, physical, local_space) self._bounds_converters[bounds](bo, physical, local_space, mat)
else: else:
simIface = so.sim.object simIface = so.sim.object
physical = simIface.physical.object physical = simIface.physical.object
@ -245,14 +253,14 @@ class PhysicsConverter:
self._apply_props(simIface, physical, kwargs) 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""" """Exports box bounds based on the object"""
physical.boundsType = plSimDefs.kBoxBounds 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) 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""" """Exports convex hull bounds based on the object"""
physical.boundsType = plSimDefs.kHullBounds 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 # bake them to convex hulls. Specifically, Windows 32-bit w/PhysX 2.6. Everything else just
# needs to have us provide some friendlier data... # needs to have us provide some friendlier data...
with bmesh_from_object(bo) as mesh: with bmesh_from_object(bo) as mesh:
mat = bo.matrix_world
if local_space: if local_space:
physical.pos = hsVector3(*mat.to_translation()) physical.pos = hsVector3(*mat.to_translation())
physical.rot = utils.quaternion(mat.to_quaternion()) physical.rot = utils.quaternion(mat.to_quaternion())
@ -273,24 +280,24 @@ class PhysicsConverter:
verts = itertools.takewhile(lambda x: isinstance(x, BMVert), result["geom"]) verts = itertools.takewhile(lambda x: isinstance(x, BMVert), result["geom"])
physical.verts = [hsVector3(*i.co) for i in verts] 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""" """Exports sphere bounds based on the object"""
physical.boundsType = plSimDefs.kSphereBounds 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) 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""" """Exports an object's mesh as exact physical bounds"""
# Triangle meshes MAY optionally specify a proxy object to fetch the triangles from... # Triangle meshes MAY optionally specify a proxy object to fetch the triangles from...
mod = bo.plasma_modifiers.collision mod = bo.plasma_modifiers.collision
if mod.enabled and mod.proxy_object is not None: if mod.enabled and mod.proxy_object is not None:
physical.boundsType = plSimDefs.kProxyBounds 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: else:
physical.boundsType = plSimDefs.kExplicitBounds 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.verts = vertices
physical.indices = indices physical.indices = indices

Loading…
Cancel
Save