瀏覽代碼

Fix blender rest export of individual skinned meshes (#8781)

* Blender exporter: use the right bones for POSE and REST mode #6050

* re-enable REST export

* Revert: fixed skinned mesh export (362cb796d004953274e4986520402de79a68cac5); this actually breaks export of individual models

* add support for JSONLoader to BlendCharacter (copied from c32f31a5875d9698e52688d293024ee9f88ce0b8)

* renamed loadObject to load again in BlendCharacter
Daniel Nienhaus 9 年之前
父節點
當前提交
8eaef33862

+ 29 - 0
examples/js/BlendCharacter.js

@@ -55,6 +55,35 @@ THREE.BlendCharacter = function () {
 
 	};
 
+	this.loadJSON = function ( url, onLoad ) {
+
+		var scope = this;
+
+		var loader = new THREE.JSONLoader();
+		loader.load( url, function( geometry, materials ) {
+
+			var originalMaterial = materials[ 0 ];
+			originalMaterial.skinning = true;
+
+			THREE.SkinnedMesh.call( scope, geometry, originalMaterial );
+
+			var mixer = new THREE.AnimationMixer( scope );
+			scope.mixer = mixer;
+
+			// Create the animations
+			for ( var i = 0; i < geometry.animations.length; ++ i ) {
+
+				mixer.clipAction( geometry.animations[ i ] );
+
+			}
+
+			// Loading is complete, fire the callback
+			if ( onLoad !== undefined ) onLoad();
+
+		} );
+
+	};
+	
 	this.update = function( dt ) {
 
 		this.mixer.update( dt );

+ 3 - 2
utils/exporters/blender/addons/io_three/__init__.py

@@ -525,7 +525,8 @@ def animation_options():
     """
     anim = [
         (constants.OFF, constants.OFF.title(), constants.OFF),
-        (constants.POSE, constants.POSE.title(), constants.POSE)
+        (constants.POSE, constants.POSE.title(), constants.POSE),
+        (constants.REST, constants.REST.title(), constants.REST)
     ]
 
     return anim
@@ -726,7 +727,7 @@ class ExportThree(bpy.types.Operator, ExportHelper):
 
     option_animation_skeletal = EnumProperty(
         name="",
-        description="Export animation (skeletal) NOTE: Mesh must be in bind pose",
+        description="Export animation (skeletal)",
         items=animation_options(),
         default=constants.OFF)
 

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

@@ -623,29 +623,31 @@ def normals(mesh):
 
 
 @_mesh
-def skin_weights(mesh, bone_map, influences):
+def skin_weights(mesh, bone_map, influences, anim_type):
     """
 
     :param mesh:
     :param bone_map:
     :param influences:
+    :param anim_type
 
     """
     logger.debug("mesh.skin_weights(%s)", mesh)
-    return _skinning_data(mesh, bone_map, influences, 1)
+    return _skinning_data(mesh, bone_map, influences, anim_type, 1)
 
 
 @_mesh
-def skin_indices(mesh, bone_map, influences):
+def skin_indices(mesh, bone_map, influences, anim_type):
     """
 
     :param mesh:
     :param bone_map:
     :param influences:
+    :param anim_type
 
     """
     logger.debug("mesh.skin_indices(%s)", mesh)
-    return _skinning_data(mesh, bone_map, influences, 0)
+    return _skinning_data(mesh, bone_map, influences, anim_type,  0)
 
 
 @_mesh
@@ -762,8 +764,8 @@ def vertices(mesh):
     vertices_ = []
 
     for vertex in mesh.vertices:
-        vertices_.extend((vertex.co.x, vertex.co.z, -vertex.co.y))
-        
+        vertices_.extend((vertex.co.x, vertex.co.y, vertex.co.z))
+
     return vertices_
 
 
@@ -961,13 +963,14 @@ def _armature(mesh):
     return armature
 
 
-def _skinning_data(mesh, bone_map, influences, array_index):
+def _skinning_data(mesh, bone_map, influences, anim_type, array_index):
     """
 
     :param mesh:
     :param bone_map:
     :param influences:
     :param array_index:
+    :param anim_type
 
     """
     armature = _armature(mesh)
@@ -975,6 +978,13 @@ def _skinning_data(mesh, bone_map, influences, array_index):
     if not armature:
         return manifest
 
+    # armature bones here based on type
+    if anim_type == constants.OFF or anim_type == constants.REST:
+        armature_bones = armature.data.bones
+    else:
+        # POSE mode
+        armature_bones = armature.pose.bones
+
     obj = object_.objects_using_mesh(mesh)[0]
     logger.debug("Skinned object found %s", obj.name)
 
@@ -990,7 +1000,7 @@ def _skinning_data(mesh, bone_map, influences, array_index):
                 manifest.append(0)
                 continue
             name = obj.vertex_groups[bone_array[index][0]].name
-            for bone_index, bone in enumerate(armature.pose.bones):
+            for bone_index, bone in enumerate(armature_bones):
                 if bone.name != name:
                     continue
                 if array_index is 0:

+ 1 - 1
utils/exporters/blender/addons/io_three/exporter/api/object.py

@@ -378,7 +378,7 @@ def matrix(obj, options):
         parent_inverted = obj.parent.matrix_world.inverted(mathutils.Matrix())
         return parent_inverted * obj.matrix_world
     else:
-        return obj.matrix_world
+        return AXIS_CONVERSION * obj.matrix_world
 
 
 @_object

+ 3 - 2
utils/exporters/blender/addons/io_three/exporter/geometry.py

@@ -558,12 +558,13 @@ class Geometry(base_classes.BaseNode):
             logger.info("Parsing %s", constants.SKINNING)
             influences = self.options.get(
                 constants.INFLUENCES_PER_VERTEX, 2)
+            anim_type = self.options.get(constants.ANIMATION)
 
             self[constants.INFLUENCES_PER_VERTEX] = influences
             self[constants.SKIN_INDICES] = api.mesh.skin_indices(
-                self.node, bone_map, influences) or []
+                self.node, bone_map, influences, anim_type) or []
             self[constants.SKIN_WEIGHTS] = api.mesh.skin_weights(
-                self.node, bone_map, influences) or []
+                self.node, bone_map, influences, anim_type) or []
 
         if self.options.get(constants.BLEND_SHAPES):
             logger.info("Parsing %s", constants.BLEND_SHAPES)