Преглед изворни кода

Merge pull request #3269 from bghgary/skeleton-fix

Fix issue with applying skeleton root transforms for glTF loader
sebavan пре 7 година
родитељ
комит
c21d17ec86

+ 21 - 14
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -306,8 +306,9 @@ module BABYLON.GLTF2 {
             switch (this._parent.coordinateSystemMode) {
                 case GLTFLoaderCoordinateSystemMode.AUTO: {
                     if (!this._babylonScene.useRightHandedSystem) {
-                        this._rootNode.babylonMesh.rotation = new Vector3(0, Math.PI, 0);
-                        this._rootNode.babylonMesh.scaling = new Vector3(1, 1, -1);
+                        this._rootNode.rotation = [ 0, 1, 0, 0 ];
+                        this._rootNode.scale = [ 1, 1, -1 ];
+                        this._loadTransform(this._rootNode);
                     }
                     break;
                 }
@@ -386,7 +387,7 @@ module BABYLON.GLTF2 {
                 this._loadMesh("#/meshes/" + node.mesh, node, mesh);
             }
 
-            node.babylonMesh.parent = node.parent ? node.parent.babylonMesh : null;
+            node.babylonMesh.parent = node.parent.babylonMesh;
 
             node.babylonAnimationTargets = node.babylonAnimationTargets || [];
             node.babylonAnimationTargets.push(node.babylonMesh);
@@ -397,7 +398,15 @@ module BABYLON.GLTF2 {
                     throw new Error(context + ": Failed to find skin " + node.skin);
                 }
 
-                node.babylonMesh.skeleton = this._loadSkin("#/skins/" + node.skin, skin);
+                this._loadSkinAsync("#/skins/" + node.skin, skin, () => {
+                    node.babylonMesh.skeleton = skin.babylonSkeleton;
+                    node.babylonMesh._refreshBoundingInfo(true);
+                });
+
+                node.babylonMesh.parent = this._rootNode.babylonMesh;
+                node.babylonMesh.position = Vector3.Zero();
+                node.babylonMesh.rotationQuaternion = Quaternion.Identity();
+                node.babylonMesh.scaling = Vector3.One();
             }
 
             if (node.camera != null) {
@@ -807,9 +816,10 @@ module BABYLON.GLTF2 {
             node.babylonMesh.scaling = scaling;
         }
 
-        private _loadSkin(context: string, skin: IGLTFSkin): Skeleton {
+        private _loadSkinAsync(context: string, skin: IGLTFSkin, onSuccess: () => void): void {
             if (skin.babylonSkeleton) {
-                return skin.babylonSkeleton;
+                onSuccess();
+                return;
             }
 
             const skeletonId = "skeleton" + skin.index;
@@ -817,6 +827,7 @@ module BABYLON.GLTF2 {
 
             if (skin.inverseBindMatrices == null) {
                 this._loadBones(context, skin, null);
+                onSuccess();
             }
             else {
                 const accessor = GLTFLoader._GetProperty(this._gltf.accessors, skin.inverseBindMatrices);
@@ -826,18 +837,14 @@ module BABYLON.GLTF2 {
 
                 this._loadAccessorAsync("#/accessors/" + accessor.index, accessor, data => {
                     this._loadBones(context, skin, <Float32Array>data);
+                    onSuccess();
                 });
             }
-
-            return skin.babylonSkeleton;
         }
 
         private _createBone(node: IGLTFNode, skin: IGLTFSkin, parent: Nullable<Bone>, localMatrix: Matrix, baseMatrix: Matrix, index: number): Bone {
             const babylonBone = new Bone(node.name || "bone" + node.index, skin.babylonSkeleton, parent, localMatrix, null, baseMatrix, index);
 
-            node.babylonBones = node.babylonBones || {};
-            node.babylonBones[skin.index] = babylonBone;
-
             node.babylonAnimationTargets = node.babylonAnimationTargets || [];
             node.babylonAnimationTargets.push(babylonBone);
 
@@ -871,7 +878,7 @@ module BABYLON.GLTF2 {
             }
 
             let babylonParentBone: Nullable<Bone> = null;
-            if (node.index !== skin.skeleton && node.parent && node.parent !== this._rootNode) {
+            if (node.parent !== this._rootNode) {
                 babylonParentBone = this._loadBone(node.parent, skin, inverseBindMatrixData, babylonBones);
                 baseMatrix.multiplyToRef(babylonParentBone.getInvertedAbsoluteTransform(), baseMatrix);
             }
@@ -890,7 +897,7 @@ module BABYLON.GLTF2 {
                     node.translation ? Vector3.FromArray(node.translation) : Vector3.Zero());
         }
 
-        private _traverseNodes(context: string, indices: number[], action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode> = null): void {
+        private _traverseNodes(context: string, indices: number[], action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): void {
             for (const index of indices) {
                 const node = GLTFLoader._GetProperty(this._gltf.nodes, index);
                 if (!node) {
@@ -901,7 +908,7 @@ module BABYLON.GLTF2 {
             }
         }
 
-        public _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: Nullable<IGLTFNode>) => boolean, parentNode: Nullable<IGLTFNode> = null): void {
+        public _traverseNode(context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): void {
             if (GLTFLoaderExtension.TraverseNode(this, context, node, action, parentNode)) {
                 return;
             }

+ 2 - 2
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -6,7 +6,7 @@ module BABYLON.GLTF2 {
 
         public abstract get name(): string;
 
-        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean { return false; }
+        protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean { return false; }
 
         protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean { return false; }
 
@@ -39,7 +39,7 @@ module BABYLON.GLTF2 {
 
         public static _Extensions: GLTFLoaderExtension[] = [];
 
-        public static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: Nullable<IGLTFNode>): boolean {
+        public static TraverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean {
             return this._ApplyExtensions(extension => extension._traverseNode(loader, context, node, action, parentNode));
         }
 

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

@@ -232,9 +232,8 @@ module BABYLON.GLTF2 {
 
         // Runtime values
         index: number;
-        parent?: IGLTFNode;
+        parent: IGLTFNode;
         babylonMesh: Mesh;
-        babylonBones?: { [skin: number]: Bone };
         babylonAnimationTargets?: Node[];
     }
 

+ 58 - 9
src/Mesh/babylon.mesh.ts

@@ -665,15 +665,19 @@
 
         /**
          * This method recomputes and sets a new BoundingInfo to the mesh unless it is locked.
-         * This means the mesh underlying bounding box and sphere are recomputed.   
-         * Returns the Mesh.  
+         * This means the mesh underlying bounding box and sphere are recomputed.
+         * Returns the Mesh.
          */
         public refreshBoundingInfo(): Mesh {
+            return this._refreshBoundingInfo(false);
+        }
+
+        public _refreshBoundingInfo(applySkeleton: boolean): Mesh {
             if (this._boundingInfo && this._boundingInfo.isLocked) {
                 return this;
             }
-            var data = this.getVerticesData(VertexBuffer.PositionKind);
 
+            var data = this._getPositionData(applySkeleton);
             if (data) {
                 var extend = Tools.ExtractMinAndMax(data, 0, this.getTotalVertices());
                 this._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
@@ -689,6 +693,55 @@
             return this;
         }
 
+        private _getPositionData(applySkeleton: boolean): Nullable<FloatArray> {
+            var data = this.getVerticesData(VertexBuffer.PositionKind);
+
+            if (data && applySkeleton && this.skeleton) {
+                data = data.slice();
+
+                var matricesIndicesData = this.getVerticesData(VertexBuffer.MatricesIndicesKind);
+                var matricesWeightsData = this.getVerticesData(VertexBuffer.MatricesWeightsKind);
+                if (matricesWeightsData && matricesIndicesData) {
+                    var needExtras = this.numBoneInfluencers > 4;
+                    var matricesIndicesExtraData = needExtras ? this.getVerticesData(VertexBuffer.MatricesIndicesExtraKind) : null;
+                    var matricesWeightsExtraData = needExtras ? this.getVerticesData(VertexBuffer.MatricesWeightsExtraKind) : null;
+
+                    var skeletonMatrices = this.skeleton.getTransformMatrices(this);
+
+                    var tempVector = Tmp.Vector3[0];
+                    var finalMatrix = Tmp.Matrix[0];
+                    var tempMatrix = Tmp.Matrix[1];
+
+                    var matWeightIdx = 0;
+                    for (var index = 0; index < data.length; index += 3, matWeightIdx += 4) {
+                        finalMatrix.reset();
+
+                        var inf: number;
+                        var weight: number;
+                        for (inf = 0; inf < 4; inf++) {
+                            weight = matricesWeightsData[matWeightIdx + inf];
+                            if (weight <= 0) break;
+                            Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesData[matWeightIdx + inf] * 16, weight, tempMatrix);
+                            finalMatrix.addToSelf(tempMatrix);
+                        }
+                        if (needExtras) {
+                            for (inf = 0; inf < 4; inf++) {
+                                weight = matricesWeightsExtraData![matWeightIdx + inf];
+                                if (weight <= 0) break;
+                                Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesExtraData![matWeightIdx + inf] * 16, weight, tempMatrix);
+                                finalMatrix.addToSelf(tempMatrix);
+                            }
+                        }
+
+                        Vector3.TransformCoordinatesFromFloatsToRef(data[index], data[index + 1], data[index + 2], finalMatrix, tempVector);
+                        tempVector.toArray(data, index);
+                    }
+                }
+            }
+
+            return data;
+        }
+
         public _createGlobalSubMesh(force: boolean): Nullable<SubMesh> {
             var totalVertices = this.getTotalVertices();
             if (!totalVertices || !this.getIndices()) {
@@ -3115,10 +3168,6 @@
             var matricesIndicesExtraData = needExtras ? this.getVerticesData(VertexBuffer.MatricesIndicesExtraKind) : null;
             var matricesWeightsExtraData = needExtras ? this.getVerticesData(VertexBuffer.MatricesWeightsExtraKind) : null;
 
-            if (!matricesWeightsExtraData || !matricesIndicesExtraData) {
-                return this;
-            }
-
             var skeletonMatrices = skeleton.getTransformMatrices(this);
 
             var tempVector3 = Vector3.Zero();
@@ -3139,9 +3188,9 @@
                 }
                 if (needExtras) {
                     for (inf = 0; inf < 4; inf++) {
-                        weight = matricesWeightsExtraData[matWeightIdx + inf];
+                        weight = matricesWeightsExtraData![matWeightIdx + inf];
                         if (weight > 0) {
-                            Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesExtraData[matWeightIdx + inf] * 16, weight, tempMatrix);
+                            Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesExtraData![matWeightIdx + inf] * 16, weight, tempMatrix);
                             finalMatrix.addToSelf(tempMatrix);
 
                         } else break;