Browse Source

First pass at adding support for configurable bone influences

repsac 10 years ago
parent
commit
46f47e581a

+ 72 - 22
utils/exporters/blender/addons/io_three/__init__.py

@@ -232,7 +232,8 @@ def save_settings_export(properties):
 
         constants.MORPH_TARGETS: properties.option_animation_morph,
         constants.ANIMATION: properties.option_animation_skeletal,
-        constants.FRAME_STEP: properties.option_frame_step
+        constants.FRAME_STEP: properties.option_frame_step,
+        constants.INFLUENCES_PER_VERTEX: properties.option_influences
     }
 
     fname = get_settings_fullpath()
@@ -253,16 +254,28 @@ def restore_settings_export(properties):
 
     ## Geometry {
     properties.option_vertices = settings.get(
-        constants.VERTICES, constants.EXPORT_OPTIONS[constants.VERTICES])
+        constants.VERTICES, 
+        constants.EXPORT_OPTIONS[constants.VERTICES])
+
     properties.option_faces = settings.get(
-        constants.FACES, constants.EXPORT_OPTIONS[constants.FACES])
+        constants.FACES, 
+        constants.EXPORT_OPTIONS[constants.FACES])
     properties.option_normals = settings.get(
-        constants.NORMALS, constants.EXPORT_OPTIONS[constants.NORMALS])
+        constants.NORMALS, 
+        constants.EXPORT_OPTIONS[constants.NORMALS])
 
     properties.option_skinning = settings.get(
-        constants.SKINNING, constants.EXPORT_OPTIONS[constants.SKINNING])
+        constants.SKINNING, 
+        constants.EXPORT_OPTIONS[constants.SKINNING])
+
     properties.option_bones = settings.get(
-        constants.BONES, constants.EXPORT_OPTIONS[constants.BONES])
+        constants.BONES, 
+        constants.EXPORT_OPTIONS[constants.BONES])
+
+    properties.option_influences = settings.get(
+        constants.INFLUENCES_PER_VERTEX,
+        constants.EXPORT_OPTIONS[constants.INFLUENCES_PER_VERTEX])
+
     properties.option_geometry_type = settings.get(
         constants.GEOMETRY_TYPE,
         constants.EXPORT_OPTIONS[constants.GEOMETRY_TYPE])
@@ -270,36 +283,55 @@ def restore_settings_export(properties):
 
     ## Materials {
     properties.option_materials = settings.get(
-        constants.MATERIALS, constants.EXPORT_OPTIONS[constants.MATERIALS])
+        constants.MATERIALS, 
+        constants.EXPORT_OPTIONS[constants.MATERIALS])
+
     properties.option_uv_coords = settings.get(
-        constants.UVS, constants.EXPORT_OPTIONS[constants.UVS])
+        constants.UVS, 
+        constants.EXPORT_OPTIONS[constants.UVS])
+
     properties.option_face_materials = settings.get(
         constants.FACE_MATERIALS, 
         constants.EXPORT_OPTIONS[constants.FACE_MATERIALS])
+
     properties.option_maps = settings.get(
-        constants.MAPS, constants.EXPORT_OPTIONS[constants.MAPS])
+        constants.MAPS, 
+        constants.EXPORT_OPTIONS[constants.MAPS])
+
     properties.option_colors = settings.get(
-        constants.COLORS, constants.EXPORT_OPTIONS[constants.COLORS])
+        constants.COLORS, 
+        constants.EXPORT_OPTIONS[constants.COLORS])
+
     properties.option_mix_colors = settings.get(
-        constants.MIX_COLORS, constants.EXPORT_OPTIONS[constants.MIX_COLORS])
+        constants.MIX_COLORS, 
+        constants.EXPORT_OPTIONS[constants.MIX_COLORS])
     ## }
 
     ## Settings {
     properties.option_scale = settings.get(
-        constants.SCALE, constants.EXPORT_OPTIONS[constants.SCALE])
+        constants.SCALE, 
+        constants.EXPORT_OPTIONS[constants.SCALE])
+
     properties.option_round_off = settings.get(
         constants.ENABLE_PRECISION, 
         constants.EXPORT_OPTIONS[constants.ENABLE_PRECISION])
+
     properties.option_round_value = settings.get(
         constants.PRECISION, 
         constants.EXPORT_OPTIONS[constants.PRECISION])
+
     properties.option_logging = settings.get(
-        constants.LOGGING, constants.EXPORT_OPTIONS[constants.LOGGING])
+        constants.LOGGING, 
+        constants.EXPORT_OPTIONS[constants.LOGGING])
+
     properties.option_compression = settings.get(
-        constants.COMPRESSION, constants.NONE)
+        constants.COMPRESSION, 
+        constants.NONE)
+
     properties.option_copy_textures = settings.get(
         constants.COPY_TEXTURES, 
         constants.EXPORT_OPTIONS[constants.COPY_TEXTURES])
+
     properties.option_embed_animation = settings.get(
         constants.EMBED_ANIMATION, 
         constants.EXPORT_OPTIONS[constants.EMBED_ANIMATION])
@@ -307,26 +339,34 @@ def restore_settings_export(properties):
 
     ## Scene {
     properties.option_export_scene = settings.get(
-        constants.SCENE, constants.EXPORT_OPTIONS[constants.SCENE])
+        constants.SCENE, 
+        constants.EXPORT_OPTIONS[constants.SCENE])
+
     properties.option_embed_geometry = settings.get(
         constants.EMBED_GEOMETRY, 
         constants.EXPORT_OPTIONS[constants.EMBED_GEOMETRY])
+
     properties.option_lights = settings.get(
-        constants.LIGHTS, constants.EXPORT_OPTIONS[constants.LIGHTS])
+        constants.LIGHTS, 
+        constants.EXPORT_OPTIONS[constants.LIGHTS])
+
     properties.option_cameras = settings.get(
-        constants.CAMERAS, constants.EXPORT_OPTIONS[constants.CAMERAS])
+        constants.CAMERAS, 
+        constants.EXPORT_OPTIONS[constants.CAMERAS])
     ## }
 
     ## Animation {
     properties.option_animation_morph = settings.get(
-        constants.MORPH_TARGETS, constants.EXPORT_OPTIONS[constants.MORPH_TARGETS])
+        constants.MORPH_TARGETS, 
+        constants.EXPORT_OPTIONS[constants.MORPH_TARGETS])
+
     properties.option_animation_skeletal = settings.get(
-        constants.ANIMATION, constants.EXPORT_OPTIONS[constants.ANIMATION])
-    #properties.option_frame_index_as_time = settings.get(
-    #    'option_frame_index_as_time', False)
+        constants.ANIMATION, 
+        constants.EXPORT_OPTIONS[constants.ANIMATION])
 
     properties.option_frame_step = settings.get(
-        constants.FRAME_STEP, constants.EXPORT_OPTIONS[constants.FRAME_STEP])
+        constants.FRAME_STEP, 
+        constants.EXPORT_OPTIONS[constants.FRAME_STEP])
     ## }
 
 def compression_types():
@@ -498,6 +538,13 @@ class ExportThree(bpy.types.Operator, ExportHelper):
         items=compression_types(), 
         default=constants.NONE)
 
+    option_influences = IntProperty(
+        name='Influences',
+        description='Maximum number of bone influences',
+        min=1,
+        max=4,
+        default=2)
+
     def invoke(self, context, event):
         restore_settings_export(self.properties)
         return ExportHelper.invoke(self, context, event)
@@ -544,6 +591,9 @@ class ExportThree(bpy.types.Operator, ExportHelper):
 
         row = layout.row()
         row.prop(self.properties, 'option_geometry_type')
+
+        row = layout.row()
+        row.prop(self.properties, 'option_influences')
         ## }
 
         layout.separator()

+ 4 - 1
utils/exporters/blender/addons/io_three/constants.py

@@ -83,6 +83,8 @@ MSGPACK = 'msgpack'
 
 PACK = 'pack'
 
+INFLUENCES_PER_VERTEX = 'influencesPerVertex'
+
 EXPORT_OPTIONS = {
     FACES: True,
     VERTICES: True,
@@ -109,7 +111,8 @@ EXPORT_OPTIONS = {
     PRECISION: DEFAULT_PRECISION,
     EMBED_GEOMETRY: True,
     EMBED_ANIMATION: True,
-    GEOMETRY_TYPE: GEOMETRY
+    GEOMETRY_TYPE: GEOMETRY,
+    INFLUENCES_PER_VERTEX: 2
 }
 
 

+ 10 - 8
utils/exporters/blender/addons/io_three/exporter/api/mesh.py

@@ -60,7 +60,8 @@ def bones(mesh):
         z_axis = -bone_world_pos.y
 
         if bone.use_deform:
-            logger.debug('Adding bone %s at: %s, %s', bone.name, bone_index, bone_index_rel)
+            logger.debug('Adding bone %s at: %s, %s', 
+                bone.name, bone_index, bone_index_rel)
             bone_map[bone_count] = bone_index_rel
             bone_index_rel += 1
             bones.append({
@@ -70,7 +71,8 @@ def bones(mesh):
                 constants.ROTQ: (0,0,0,1)
             })
         else:
-            logger.debug('Ignoring bone %s at: %s, %s', bone.name, bone_index, bone_index_rel)
+            logger.debug('Ignoring bone %s at: %s, %s', 
+                bone.name, bone_index, bone_index_rel)
 
         bone_count += 1
 
@@ -377,15 +379,15 @@ def normals(mesh, options):
 
 
 @_mesh
-def skin_weights(mesh, bone_map):
+def skin_weights(mesh, bone_map, influences):
     logger.debug('mesh.skin_weights(%s)', mesh)
-    return _skinning_data(mesh, bone_map, 1)
+    return _skinning_data(mesh, bone_map, influences, 1)
 
 
 @_mesh
-def skin_indices(mesh, bone_map):
+def skin_indices(mesh, bone_map, influences):
     logger.debug('mesh.skin_indices(%s)', mesh)
-    return _skinning_data(mesh, bone_map, 0)
+    return _skinning_data(mesh, bone_map, influences, 0)
 
 
 @_mesh
@@ -630,7 +632,7 @@ def _armature(mesh):
     return armature
 
 
-def _skinning_data(mesh, bone_map, array_index):
+def _skinning_data(mesh, bone_map, influences, array_index):
     armature = _armature(mesh)
     if not armature: return
 
@@ -645,7 +647,7 @@ def _skinning_data(mesh, bone_map, array_index):
 
         bone_array.sort(key=operator.itemgetter(1), reverse=True)
 
-        for index in range(2):
+        for index in range(influences):
             if index >= len(bone_array):
                 manifest.append(0)
                 continue

+ 16 - 4
utils/exporters/blender/addons/io_three/exporter/geometry.py

@@ -179,7 +179,8 @@ class Geometry(base_classes.BaseNode):
         components = [constants.VERTICES, constants.FACES, 
             constants.UVS, constants.COLORS, constants.NORMALS,
             constants.BONES, constants.SKIN_WEIGHTS, 
-            constants.SKIN_INDICES, constants.NAME]
+            constants.SKIN_INDICES, constants.NAME,
+            constants.INFLUENCES_PER_VERTEX]
 
         data = {}
         anim_components = [constants.MORPH_TARGETS, constants.ANIMATION]
@@ -229,7 +230,8 @@ class Geometry(base_classes.BaseNode):
     def __geometry_metadata(self, metadata): 
         skip = (constants.TYPE, constants.FACES, constants.UUID,
             constants.ANIMATION, constants.SKIN_INDICES,
-            constants.BONE_MAP, constants.SKIN_WEIGHTS, constants.NAME)
+            constants.BONE_MAP, constants.SKIN_WEIGHTS, 
+            constants.NAME, constants.INFLUENCES_PER_VERTEX)
         vectors = (constants.VERTICES, constants.NORMALS)
 
         for key in self.keys():
@@ -337,6 +339,10 @@ class Geometry(base_classes.BaseNode):
             self[constants.ANIMATION] = api.mesh.animation(
                 self.node, self.options)
 
+        #@TODO: wondering if bone maps should be stored with
+        #       the object itself or only handled via a local
+        #       variable as it doesn't seem this data has 
+        #       other users outside of the immediate logic
         if self.options.get(constants.BONES):
             logger.info('Parsing %s', constants.BONES)
             bone_data = api.mesh.bones(self.node)
@@ -345,9 +351,15 @@ class Geometry(base_classes.BaseNode):
 
         if self.options.get(constants.SKINNING):
             logger.info('Parsing %s', constants.SKINNING)
+            influences = self.options.get(
+                constants.INFLUENCES_PER_VERTEX, 2)
             bone_map = self.get(constants.BONE_MAP) or {}
-            self[constants.SKIN_INDICES] = api.mesh.skin_indices(self.node, bone_map)
-            self[constants.SKIN_WEIGHTS] = api.mesh.skin_weights(self.node, bone_map)
+
+            self[constants.INFLUENCES_PER_VERTEX] = influences
+            self[constants.SKIN_INDICES] = api.mesh.skin_indices(
+                self.node, bone_map, influences)
+            self[constants.SKIN_WEIGHTS] = api.mesh.skin_weights(
+                self.node, bone_map, influences)
 
         if self.options.get(constants.MORPH_TARGETS):
             logger.info('Parsing %s', constants.MORPH_TARGETS)

BIN
utils/exporters/blender/modules/msgpack/__pycache__/__init__.cpython-34.pyc


BIN
utils/exporters/blender/modules/msgpack/__pycache__/_version.cpython-34.pyc


BIN
utils/exporters/blender/modules/msgpack/__pycache__/exceptions.cpython-34.pyc


BIN
utils/exporters/blender/modules/msgpack/__pycache__/fallback.cpython-34.pyc


+ 9 - 0
utils/exporters/blender/tests/scripts/test_geometry_influences.bash

@@ -0,0 +1,9 @@
+#!/bin/bash
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+source "$DIR/setup_test_env.bash"
+
+blender --background $BLEND/anim.blend --python $PYSCRIPT -- \
+    $JSON --vertices --faces --animation --bones --skinning \
+    --embedAnimation --influencesPerVertex 4
+makereview $@ --tag $(tagname)