Bläddra i källkod

Fix animation blending issue with glTF loader

Gary Hsu 7 år sedan
förälder
incheckning
66b901435e

+ 12 - 11
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -507,9 +507,6 @@ module BABYLON.GLTF2 {
             const babylonMesh = new Mesh(node.name || `node${node._index}`, this._babylonScene, node._parent._babylonMesh);
             node._babylonMesh = babylonMesh;
 
-            node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-            node._babylonAnimationTargets.push(babylonMesh);
-
             GLTFLoader._LoadTransform(node, babylonMesh);
 
             if (node.mesh != undefined) {
@@ -818,8 +815,8 @@ module BABYLON.GLTF2 {
             babylonBone = new Bone(node.name || `joint${node._index}`, skin._babylonSkeleton!, babylonParentBone, this._getNodeMatrix(node), null, null, boneIndex);
             babylonBones[node._index] = babylonBone;
 
-            node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-            node._babylonAnimationTargets.push(babylonBone);
+            node._babylonBones = node._babylonBones || [];
+            node._babylonBones.push(babylonBone);
 
             return babylonBone;
         }
@@ -939,7 +936,7 @@ module BABYLON.GLTF2 {
 
             // Ignore animations that have no animation targets.
             if ((channel.target.path === AnimationChannelTargetPath.WEIGHTS && !targetNode._numMorphTargets) ||
-                (channel.target.path !== AnimationChannelTargetPath.WEIGHTS && !targetNode._babylonAnimationTargets)) {
+                (channel.target.path !== AnimationChannelTargetPath.WEIGHTS && !targetNode._babylonMesh)) {
                 return Promise.resolve();
             }
 
@@ -1075,12 +1072,16 @@ module BABYLON.GLTF2 {
                     const babylonAnimation = new Animation(animationName, targetPath, 1, animationType);
                     babylonAnimation.setKeys(keys);
 
-                    if (targetNode._babylonAnimationTargets) {
-                        for (const babylonAnimationTarget of targetNode._babylonAnimationTargets) {
-                            const babylonAnimationClone = babylonAnimation.clone();
-                            babylonAnimationTarget.animations.push(babylonAnimationClone);
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimationClone, babylonAnimationTarget);
+                    if (targetNode._babylonBones) {
+                        const babylonAnimationTargets = [targetNode._babylonMesh!, ...targetNode._babylonBones];
+                        for (const babylonAnimationTarget of babylonAnimationTargets) {
+                            babylonAnimationTarget.animations.push(babylonAnimation);
                         }
+                        babylonAnimationGroup.addTargetedAnimation(babylonAnimation, babylonAnimationTargets);
+                    }
+                    else {
+                        targetNode._babylonMesh!.animations.push(babylonAnimation);
+                        babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonMesh);
                     }
                 }
             });

+ 1 - 1
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -77,7 +77,7 @@ module BABYLON.GLTF2 {
         _parent: _ILoaderNode;
         _babylonMesh?: Mesh;
         _primitiveBabylonMeshes?: Mesh[];
-        _babylonAnimationTargets?: Node[];
+        _babylonBones?: Bone[];
         _numMorphTargets?: number;
     }
 

+ 18 - 7
src/Animations/babylon.runtimeAnimation.ts

@@ -222,6 +222,17 @@
          * @param weight defines the weight to apply to this value (Defaults to 1.0)
          */
         public setValue(currentValue: any, weight = 1.0): void {
+            if (this._target instanceof Array) {
+                for (const target of this._target) {
+                    this._setValue(target, currentValue, weight);
+                }
+            }
+            else {
+                this._setValue(this._target, currentValue, weight);
+            }
+        }
+
+        private _setValue(target: any, currentValue: any, weight: number): void {
             // Set value
             var path: any;
             var destination: any;
@@ -229,7 +240,7 @@
             let targetPropertyPath = this._animation.targetPropertyPath
 
             if (targetPropertyPath.length > 1) {
-                var property = this._target[targetPropertyPath[0]];
+                var property = target[targetPropertyPath[0]];
 
                 for (var index = 1; index < targetPropertyPath.length - 1; index++) {
                     property = property[targetPropertyPath[index]];
@@ -239,14 +250,14 @@
                 destination = property;
             } else {
                 path = targetPropertyPath[0];
-                destination = this._target;
+                destination = target;
             }
 
             this._targetPath = path;
             this._activeTarget = destination;
             this._weight = weight;
 
-            if (!this._originalValue ) {
+            if (!this._originalValue) {
                 let originalValue: any;
 
                 if (destination.getRestPose && path === "_matrix") { // For bones
@@ -263,7 +274,7 @@
             }
 
             // Blending
-            const enableBlending = this._target && this._target.animationPropertiesOverride ? this._target.animationPropertiesOverride.enableBlending : this._animation.enableBlending;
+            const enableBlending = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.enableBlending : this._animation.enableBlending;
             if (enableBlending && this._blendingFactor <= 1.0) {
                 if (!this._originalBlendValue) {
                     let originalValue = destination[path];
@@ -302,7 +313,7 @@
                     }
                 }
 
-                const blendingSpeed = this._target && this._target.animationPropertiesOverride ? this._target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
+                const blendingSpeed = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
                 this._blendingFactor += blendingSpeed;
             } else {
                 this._currentValue = currentValue;
@@ -314,8 +325,8 @@
                 destination[path] = this._currentValue;
             }
 
-            if (this._target.markAsDirty) {
-                this._target.markAsDirty(this._animation.targetProperty);
+            if (target.markAsDirty) {
+                target.markAsDirty(this._animation.targetProperty);
             }
         }
 

+ 2 - 2
tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

@@ -260,11 +260,11 @@ describe('Babylon Scene Loader', function () {
 
                 const animationGroup = result.animationGroups[0];
                 expect(animationGroup.name, "animationGroup.name").to.equal("TwoTargetBlend");
-                expect(animationGroup.targetedAnimations, "animationGroup.targetedAnimations").to.have.lengthOf(19);
+                expect(animationGroup.targetedAnimations, "animationGroup.targetedAnimations").to.have.lengthOf(7);
                 const influenceAnimations = animationGroup.targetedAnimations.filter(_ => _.animation.targetProperty === "influence");
                 expect(influenceAnimations, "influenceAnimations").to.have.lengthOf(2);
                 const rotationAnimations = animationGroup.targetedAnimations.filter(_ => _.animation.targetProperty === "rotationQuaternion");
-                expect(rotationAnimations, "rotationAnimations").to.have.lengthOf(16);
+                expect(rotationAnimations, "rotationAnimations").to.have.lengthOf(4);
                 const positionAnimations = animationGroup.targetedAnimations.filter(_ => _.animation.targetProperty === "position");
                 expect(positionAnimations, "positionAnimations").to.have.lengthOf(1);
             });