Selaa lähdekoodia

[Max2Babylon] - export crash when a skin modifier is not really a bone

Simon Ferquel 10 vuotta sitten
vanhempi
commit
ce76dbc62c

+ 28 - 11
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Mesh.cs

@@ -56,14 +56,31 @@ namespace Max2Babylon
             var skin = gameMesh.IGameSkin;
             var unskinnedMesh = gameMesh;
             IGMatrix skinInitPoseMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
+            List<int> boneIds = null;
             if (isSkinned)
             {
                 //unskinnedMesh = skin.InitialPose;
                 bonesCount = skin.TotalSkinBoneCount;
                 skins.Add(skin);
+                
                 skinnedNodes.Add(meshNode);
                 babylonMesh.skeletonId = skins.IndexOf(skin);
                 skin.GetInitSkinTM(skinInitPoseMatrix);
+                boneIds = new List<int>();
+                for (var index = 0; index < skin.TotalSkinBoneCount; index++)
+                {
+                    var bone = skin.GetIGameBone(index, false);
+                    if(bone == null)
+                    {
+                        // non bone in skeletton
+                        boneIds.Add(-2);
+
+                    }
+                    else
+                    {
+                        boneIds.Add(bone.NodeID);
+                    }
+                }
             }
 
             // Position / rotation / scaling
@@ -188,7 +205,7 @@ namespace Max2Babylon
                         for(int j = 0; j < unskinnedMesh.NumberOfFaces; ++j)
                         {
                             var face = unskinnedMesh.GetFace(j);
-                            ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face);
+                            ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face, boneIds);
                         }
                     }
                     else
@@ -200,7 +217,7 @@ namespace Max2Babylon
                             var face = materialFaces[faceIndexer];
 
                             Marshal.FreeHGlobal(faceIndexer);
-                            ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face);
+                            ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face, boneIds);
                         }
                     }
                     
@@ -347,11 +364,11 @@ namespace Max2Babylon
             babylonScene.MeshesList.Add(babylonMesh);
         }
 
-        private void ExtractFace(IIGameSkin skin, IIGameMesh unskinnedMesh, List<GlobalVertex> vertices, List<int> indices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, List<GlobalVertex>[] verticesAlreadyExported, ref int indexCount, ref int minVertexIndex, ref int maxVertexIndex, IFaceEx face)
+        private void ExtractFace(IIGameSkin skin, IIGameMesh unskinnedMesh, List<GlobalVertex> vertices, List<int> indices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, List<GlobalVertex>[] verticesAlreadyExported, ref int indexCount, ref int minVertexIndex, ref int maxVertexIndex, IFaceEx face, List<int> boneIds)
         {
-            var a = CreateGlobalVertex(unskinnedMesh, face, 0, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
-            var b = CreateGlobalVertex(unskinnedMesh, face, 2, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
-            var c = CreateGlobalVertex(unskinnedMesh, face, 1, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
+            var a = CreateGlobalVertex(unskinnedMesh, face, 0, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin, boneIds);
+            var b = CreateGlobalVertex(unskinnedMesh, face, 2, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin, boneIds);
+            var c = CreateGlobalVertex(unskinnedMesh, face, 1, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin, boneIds);
             indices.Add(a);
             indices.Add(b);
             indices.Add(c);
@@ -431,7 +448,7 @@ namespace Max2Babylon
         }
 
 
-        int CreateGlobalVertex(IIGameMesh mesh, IFaceEx face, int facePart, List<GlobalVertex> vertices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, List<GlobalVertex>[] verticesAlreadyExported, IIGameSkin skin)
+        int CreateGlobalVertex(IIGameMesh mesh, IFaceEx face, int facePart, List<GlobalVertex> vertices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, List<GlobalVertex>[] verticesAlreadyExported, IIGameSkin skin, List<int> boneIds)
         {
             var vertexIndex = (int)face.Vert[facePart];
 
@@ -498,25 +515,25 @@ namespace Max2Babylon
 
                 if (nbBones > 0)
                 {
-                    bone0 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 0), false);
+                    bone0 = boneIds.IndexOf(skin.GetIGameBone(vertexIndex, 0).NodeID);
                     weight0 = skin.GetWeight(vertexIndex, 0);
                 }
 
                 if (nbBones > 1)
                 {
-                    bone1 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 1), false);
+                    bone1 = boneIds.IndexOf(skin.GetIGameBone(vertexIndex, 1).NodeID);
                     weight1 = skin.GetWeight(vertexIndex, 1);
                 }
 
                 if (nbBones > 2)
                 {
-                    bone2 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 2), false);
+                    bone2 = boneIds.IndexOf(skin.GetIGameBone(vertexIndex, 2).NodeID);
                     weight2 = skin.GetWeight(vertexIndex, 2);
                 }
 
                 if (nbBones > 3)
                 {
-                    bone3 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 3), false);
+                    bone3 = boneIds.IndexOf(skin.GetIGameBone(vertexIndex, 3).NodeID);
                 }
 
                 if (nbBones == 0)

+ 74 - 53
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Skeleton.cs

@@ -129,81 +129,102 @@ namespace Max2Babylon
             for (var index = 0; index < skin.TotalSkinBoneCount; index++)
             {
                 var gameBone = skin.GetIGameBone(index, false);
+               
+                if (gameBone == null)
+                {
+                    gameBones.Add(null);
+                    boneIds.Add(-2);
+                    bones.Add(new BabylonBone { index = index, name = "null-bone" });
 
-                gameBones.Add(gameBone);
-                boneIds.Add(gameBone.NodeID);
-                bones.Add(new BabylonBone { index = index, name = gameBone.Name });
-                //IGMatrix boneInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
-
-                //skin.GetInitBoneTM(gameBone, boneInitMatrix);
-                var boneInitMatrix = gameBone.GetObjectTM(0);
-                bindPoseInfos.Add(new BonePoseInfo { AbsoluteTransform = boneInitMatrix });
+                    bindPoseInfos.Add(new BonePoseInfo {  });
+                }
+                else
+                {
+                    gameBones.Add(gameBone);
+                    boneIds.Add(gameBone.NodeID);
+                    bones.Add(new BabylonBone { index = index, name = gameBone.Name });
+                    //IGMatrix boneInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
+
+                    //skin.GetInitBoneTM(gameBone, boneInitMatrix);
+                    var boneInitMatrix = gameBone.GetObjectTM(0);
+                    bindPoseInfos.Add(new BonePoseInfo { AbsoluteTransform = boneInitMatrix });
+                }
             }
             // fix hierarchy an generate animation keys
             for (var index = 0; index < skin.TotalSkinBoneCount; index++)
             {
                 var gameBone = gameBones[index];
-                var parent = gameBone.NodeParent;
-                var babBone = bones[index];
-                if (parent != null)
-                {
-                    babBone.parentBoneIndex = boneIds.IndexOf(parent.NodeID);
-                }
-                if (babBone.parentBoneIndex == -1)
+                if (gameBone == null)
                 {
-                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(skinInitMatrix.Inverse);
+
+                    var babBone = bones[index];
+                    bindPoseInfos[index].LocalTransform = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
+                    babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();
                 }
                 else
                 {
-                    var parentBindPoseInfos = bindPoseInfos[babBone.parentBoneIndex];
-                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(parentBindPoseInfos.AbsoluteTransform.Inverse);
-                }
-                babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();
-
-                var babylonAnimation = new BabylonAnimation
-                {
-                    name = gameBone.Name + "Animation",
-                    property = "_matrix",
-                    dataType = BabylonAnimation.DataType.Matrix,
-                    loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
-                    framePerSecond = Loader.Global.FrameRate
-                };
-
-                var start = Loader.Core.AnimRange.Start;
-                var end = Loader.Core.AnimRange.End;
-
-                float[] previous = null;
-                var keys = new List<BabylonAnimationKey>();
-                for (var key = start; key <= end; key += Ticks)
-                {
-                    var objectTM = gameBone.GetObjectTM(key);
-                    var parentNode = gameBone.NodeParent;
-                    IGMatrix mat;
-                    if (parentNode == null || babBone.parentBoneIndex == -1)
+                    var parent = gameBone.NodeParent;
+                    var babBone = bones[index];
+                    if (parent != null)
+                    {
+                        babBone.parentBoneIndex = boneIds.IndexOf(parent.NodeID);
+                    }
+                    if (babBone.parentBoneIndex == -1)
                     {
-                        mat = objectTM.Multiply(meshNode.GetObjectTM(key).Inverse);
+                        bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(skinInitMatrix.Inverse);
                     }
                     else
                     {
-                        mat = objectTM.Multiply(parentNode.GetObjectTM(key).Inverse);
+                        var parentBindPoseInfos = bindPoseInfos[babBone.parentBoneIndex];
+                        bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(parentBindPoseInfos.AbsoluteTransform.Inverse);
                     }
+                    babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();
 
-                    var current = mat.ToArray();
-                    if (key == start || key == end || !(previous.IsEqualTo(current)))
+                    var babylonAnimation = new BabylonAnimation
                     {
-                        keys.Add(new BabylonAnimationKey
+                        name = gameBone.Name + "Animation",
+                        property = "_matrix",
+                        dataType = BabylonAnimation.DataType.Matrix,
+                        loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
+                        framePerSecond = Loader.Global.FrameRate
+                    };
+
+                    var start = Loader.Core.AnimRange.Start;
+                    var end = Loader.Core.AnimRange.End;
+
+                    float[] previous = null;
+                    var keys = new List<BabylonAnimationKey>();
+                    for (var key = start; key <= end; key += Ticks)
+                    {
+                        var objectTM = gameBone.GetObjectTM(key);
+                        var parentNode = gameBone.NodeParent;
+                        IGMatrix mat;
+                        if (parentNode == null || babBone.parentBoneIndex == -1)
+                        {
+                            mat = objectTM.Multiply(meshNode.GetObjectTM(key).Inverse);
+                        }
+                        else
                         {
-                            frame = key / Ticks,
-                            values = current
-                        });
+                            mat = objectTM.Multiply(parentNode.GetObjectTM(key).Inverse);
+                        }
+
+                        var current = mat.ToArray();
+                        if (key == start || key == end || !(previous.IsEqualTo(current)))
+                        {
+                            keys.Add(new BabylonAnimationKey
+                            {
+                                frame = key / Ticks,
+                                values = current
+                            });
+                        }
+
+                        previous = current;
                     }
 
-                    previous = current;
+                    babylonAnimation.keys = keys.ToArray();
+                    babBone.animation = babylonAnimation;
                 }
 
-                babylonAnimation.keys = keys.ToArray();
-                babBone.animation = babylonAnimation;
-
             }
 
             //FixupHierarchy(Loader.Core.RootNode, skin.GetBone(0), bones);