Browse Source

Optimize convex hull export.

Avoiding the context switches appears to be a huge boon for performance.
With 100 iterations on an arbitrary mesh, the improvement was 17s to
2.55s.
pull/176/head
Adam Johnson 5 years ago
parent
commit
ecaba2e6e0
Signed by: Hoikas
GPG Key ID: 0B6515D6FF6F271E
  1. 43
      korman/exporter/physics.py
  2. 13
      korman/helpers.py

43
korman/exporter/physics.py

@ -13,13 +13,15 @@
# You should have received a copy of the GNU General Public License
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
import bmesh
import bpy
import itertools
import mathutils
from PyHSPlasma import *
import weakref
from .explosions import ExportError, ExportAssertionError
from ..helpers import TemporaryObject
from ..helpers import bmesh_from_object, TemporaryObject
from . import utils
def _set_phys_prop(prop, sim, phys, value=True):
@ -58,18 +60,11 @@ class PhysicsConverter:
indices += (v[0], v[2], v[3],)
return indices
def _convert_mesh_data(self, bo, physical, local_space, indices=True, mesh_func=None):
try:
mesh = bo.to_mesh(bpy.context.scene, True, "RENDER", calc_tessface=False)
except:
raise ExportError("Unable to convert object [{}] '{}' to a mesh. Make sure you didn't try to use this object as a region!",
bo.type, bo.name)
def _convert_mesh_data(self, bo, physical, local_space, indices=True):
mat = bo.matrix_world
mesh = bo.to_mesh(bpy.context.scene, True, "RENDER", calc_tessface=False)
with TemporaryObject(mesh, bpy.data.meshes.remove):
if mesh_func is not None:
mesh_func(mesh)
if local_space:
mesh.update(calc_tessface=indices)
physical.pos = hsVector3(*mat.to_translation())
@ -264,21 +259,19 @@ class PhysicsConverter:
# Only certain builds of libHSPlasma are able to take artist generated triangle soups and
# bake them to convex hulls. Specifically, Windows 32-bit w/PhysX 2.6. Everything else just
# needs to have us provide some friendlier data...
def _bake_hull(mesh):
# The bmesh API for doing this is trash, so we will link this temporary mesh to an
# even more temporary object so we can use the traditional operator.
# Unless you want to write some code to do this by hand...??? (not me)
bo = bpy.data.objects.new("BMeshSucks", mesh)
bpy.context.scene.objects.link(bo)
with TemporaryObject(bo, bpy.data.objects.remove):
bpy.context.scene.objects.active = bo
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.select_all(action="SELECT")
bpy.ops.mesh.convex_hull(use_existing_faces=False)
bpy.ops.object.mode_set(mode="OBJECT")
physical.verts = self._convert_mesh_data(bo, physical, local_space, indices=False,
mesh_func=_bake_hull)
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())
bmesh.ops.scale(mesh, vec=mat.to_scale(), verts=mesh.verts)
else:
mesh.transform(mat)
result = bmesh.ops.convex_hull(mesh, input=mesh.verts, use_existing_faces=False)
BMVert = bmesh.types.BMVert
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):
"""Exports sphere bounds based on the object"""

13
korman/helpers.py

@ -13,9 +13,22 @@
# You should have received a copy of the GNU General Public License
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
import bmesh
import bpy
from contextlib import contextmanager
import math
@contextmanager
def bmesh_from_object(bl):
"""Converts a Blender Object to a BMesh with modifiers applied."""
mesh = bmesh.new()
try:
# Empirical evidence indicates that this applies Blender Modifiers
mesh.from_object(bl, bpy.context.scene)
yield mesh
finally:
mesh.free()
class GoodNeighbor:
"""Leave Things the Way You Found Them! (TM)"""

Loading…
Cancel
Save