소스 검색

Max2Babylon - fixup for unordered bone hierarchies and non-bone item in a skeleton hierarchy

Simon Ferquel 10 년 전
부모
커밋
64c5afd936
2개의 변경된 파일101개의 추가작업 그리고 63개의 파일을 삭제
  1. 81 42
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Mesh.cs
  2. 20 21
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Skeleton.cs

+ 81 - 42
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Mesh.cs

@@ -9,6 +9,58 @@ namespace Max2Babylon
 {
     partial class BabylonExporter
     {
+        Dictionary<IIGameSkin, List<int>> skinSortedBones = new Dictionary<IIGameSkin, List<int>>();
+        List<int> SortBones(IIGameSkin skin)
+        {
+            List<int> boneIds = new List<int>();
+            Dictionary<int, IIGameNode> boneIndex = new Dictionary<int, IIGameNode>();
+            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);
+                    boneIndex[bone.NodeID] = bone;
+                }
+            }
+            while (true)
+            {
+                bool foundMisMatch = false;
+                for (int i = 0; i < boneIds.Count; ++i)
+                {
+                    var id = boneIds[i];
+                    if(id == -2)
+                    {
+                        continue;
+                    }
+                    var parent = boneIndex[id].NodeParent;
+                    if(parent != null)
+                    {
+                        var parentId = parent.NodeID;
+                        if (boneIds.IndexOf(parentId) > i)
+                        {
+                            boneIds.RemoveAt(i);
+                            boneIds.Insert(boneIds.IndexOf(parentId) + 1, id);
+                            foundMisMatch = true;
+                            break;
+                        }
+                    }
+                }
+                if(!foundMisMatch)
+                {
+                    break;
+                }
+            }
+            return boneIds;
+
+        }
+
         private int bonesCount;
         private void ExportMesh(IIGameScene scene, IIGameNode meshNode, BabylonScene babylonScene)
         {
@@ -62,25 +114,12 @@ namespace Max2Babylon
                 //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);
-                    }
-                }
+                boneIds = SortBones(skin);
+                skinSortedBones[skin] = boneIds;
             }
 
             // Position / rotation / scaling
@@ -161,13 +200,13 @@ namespace Max2Babylon
                     IntPtr indexer = new IntPtr(i);
                     var channelNum = mappingChannels[indexer];
                     if (channelNum == 1)
-                {
+                    {
                         hasUV = true;
-                }
+                    }
                     else if (channelNum == 2)
-                {
+                    {
                         hasUV2 = true;
-                }
+                    }
                 }
                 var hasColor = unskinnedMesh.NumberOfColorVerts > 0;
                 var hasAlpha = unskinnedMesh.GetNumberOfMapVerts(-2) > 0;
@@ -188,7 +227,7 @@ namespace Max2Babylon
                 var subMeshes = new List<BabylonSubMesh>();
                 var indexStart = 0;
 
-                
+
                 for (int i = 0; i < multiMatsCount; ++i)
                 {
                     int materialId = meshNode.NodeMaterial.GetMaterialID(i);
@@ -202,7 +241,7 @@ namespace Max2Babylon
 
                     if (multiMatsCount == 1)
                     {
-                        for(int j = 0; j < unskinnedMesh.NumberOfFaces; ++j)
+                        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, boneIds);
@@ -220,11 +259,11 @@ namespace Max2Babylon
                             ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face, boneIds);
                         }
                     }
-                    
 
 
 
-                   
+
+
                     if (indexCount != 0)
                     {
 
@@ -344,7 +383,7 @@ namespace Max2Babylon
             // Animations
             var animations = new List<BabylonAnimation>();
             GenerateCoordinatesAnimations(meshNode, animations);
-            
+
 
             if (!ExportFloatController(meshNode.MaxNode.VisController, "visibility", animations))
             {
@@ -409,42 +448,42 @@ namespace Max2Babylon
         }
 
         public static void GenerateCoordinatesAnimations(IIGameNode meshNode, List<BabylonAnimation> animations)
-            {
+        {
             //if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations))
             //{
-                ExportVector3Animation("position", animations, key =>
-                {
+            ExportVector3Animation("position", animations, key =>
+            {
                 var worldMatrix = meshNode.GetObjectTM(key);
                 var trans = worldMatrix.Translation;
                 return new float[] { trans.X, trans.Y, trans.Z };
-                });
+            });
             //}
 
 
             //if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
             //{
-                ExportQuaternionAnimation("rotationQuaternion", animations, key =>
-                {
-                    var worldMatrix = meshNode.GetObjectTM(key);
+            ExportQuaternionAnimation("rotationQuaternion", animations, key =>
+            {
+                var worldMatrix = meshNode.GetObjectTM(key);
 
 
 
-                    var rot = worldMatrix.Rotation;
-                    return new float[] { rot.X, rot.Y, rot.Z, -rot.W };
-                });
+                var rot = worldMatrix.Rotation;
+                return new float[] { rot.X, rot.Y, rot.Z, -rot.W };
+            });
             //}
 
 
             //if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
             //{
-                ExportVector3Animation("scaling", animations, key =>
-                {
-                    var worldMatrix = meshNode.GetObjectTM(key);
-                    var scale = worldMatrix.Scaling;
+            ExportVector3Animation("scaling", animations, key =>
+            {
+                var worldMatrix = meshNode.GetObjectTM(key);
+                var scale = worldMatrix.Scaling;
 
-                    return new float[] { scale.X, scale.Y, scale.Z };
-                });
-           // }
+                return new float[] { scale.X, scale.Y, scale.Z };
+            });
+            // }
         }
 
 

+ 20 - 21
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Skeleton.cs

@@ -110,44 +110,43 @@ namespace Max2Babylon
             mat3.NoScale();
             return Loader.Global.GMatrix.Create(mat3);
         }
-        private void ExportSkin(IIGameSkin skin, BabylonScene babylonScene)
+        private void ExportSkin( IIGameSkin skin, BabylonScene babylonScene)
         {
             var babylonSkeleton = new BabylonSkeleton { id = skins.IndexOf(skin) };
             babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;
 
             RaiseMessage(babylonSkeleton.name, 1);
-            //IGMatrix skinInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
-            //skin.GetInitSkinTM(skinInitMatrix);
+            IGMatrix skinInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
+            skin.GetInitSkinTM(skinInitMatrix);
             var skinIndex = skins.IndexOf(skin);
             var meshNode = skinnedNodes[skinIndex];
-            var skinInitMatrix = meshNode.GetObjectTM(0);
+            var meshInitMatrix = meshNode.GetObjectTM(0);
+            var boneIds = skinSortedBones[skin];
 
-            var bones = new List<BabylonBone>();
-            var gameBones = new List<IIGameNode>();
-            var boneIds = new List<int>();
-            var bindPoseInfos = new List<BonePoseInfo>();
-            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
+            var bones = new BabylonBone[boneIds.Count];
+            var gameBones = new IIGameNode[boneIds.Count];
+            var bindPoseInfos = new BonePoseInfo[boneIds.Count];
+            for (var unsortedIndex = 0; unsortedIndex < skin.TotalSkinBoneCount; unsortedIndex++)
             {
-                var gameBone = skin.GetIGameBone(index, false);
-               
+                var gameBone = skin.GetIGameBone(unsortedIndex, false);
+                int index = gameBone == null ? boneIds.IndexOf(-2) : boneIds.IndexOf(gameBone.NodeID);
                 if (gameBone == null)
                 {
-                    gameBones.Add(null);
-                    boneIds.Add(-2);
-                    bones.Add(new BabylonBone { index = index, name = "null-bone" });
 
-                    bindPoseInfos.Add(new BonePoseInfo {  });
+                    gameBones[index]=null;
+                    bones[index] = new BabylonBone { index = index, name = "null-bone" };
+
+                    bindPoseInfos[index] = new BonePoseInfo {  };
                 }
                 else
                 {
-                    gameBones.Add(gameBone);
-                    boneIds.Add(gameBone.NodeID);
-                    bones.Add(new BabylonBone { index = index, name = gameBone.Name });
+                    gameBones[index] = gameBone;
+                    bones[index] = 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[index] = new BonePoseInfo { AbsoluteTransform = boneInitMatrix };
                 }
             }
             // fix hierarchy an generate animation keys
@@ -171,7 +170,7 @@ namespace Max2Babylon
                     }
                     if (babBone.parentBoneIndex == -1)
                     {
-                        bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(skinInitMatrix.Inverse);
+                        bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(meshInitMatrix.Inverse);
                     }
                     else
                     {
@@ -229,7 +228,7 @@ namespace Max2Babylon
 
             //FixupHierarchy(Loader.Core.RootNode, skin.GetBone(0), bones);
 
-            babylonSkeleton.bones = bones.ToArray();
+            babylonSkeleton.bones = bones;
 
             babylonScene.SkeletonsList.Add(babylonSkeleton);
         }