BabylonExporter.Skeleton.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using System;
  2. using System.Collections.Generic;
  3. using Autodesk.Max;
  4. using BabylonExport.Entities;
  5. using SharpDX;
  6. namespace Max2Babylon
  7. {
  8. internal class BonePoseInfo
  9. {
  10. public IGMatrix AbsoluteTransform { get; set; }
  11. public IGMatrix LocalTransform { get; set; }
  12. }
  13. partial class BabylonExporter
  14. {
  15. readonly List<IIGameSkin> skins = new List<IIGameSkin>();
  16. readonly List<IIGameNode> skinnedNodes = new List<IIGameNode>();
  17. IGMatrix WithNoScale(IGMatrix mat)
  18. {
  19. var mat3 = mat.ExtractMatrix3();
  20. mat3.NoScale();
  21. return Loader.Global.GMatrix.Create(mat3);
  22. }
  23. private void ExportSkin( IIGameSkin skin, BabylonScene babylonScene)
  24. {
  25. var babylonSkeleton = new BabylonSkeleton { id = skins.IndexOf(skin) };
  26. babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;
  27. RaiseMessage(babylonSkeleton.name, 1);
  28. IGMatrix skinInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
  29. skin.GetInitSkinTM(skinInitMatrix);
  30. var skinIndex = skins.IndexOf(skin);
  31. var meshNode = skinnedNodes[skinIndex];
  32. var meshInitMatrix = meshNode.GetObjectTM(0);
  33. var boneIds = skinSortedBones[skin];
  34. var bones = new BabylonBone[boneIds.Count];
  35. var gameBones = new IIGameNode[boneIds.Count];
  36. var bindPoseInfos = new BonePoseInfo[boneIds.Count];
  37. for (var unsortedIndex = 0; unsortedIndex < skin.TotalSkinBoneCount; unsortedIndex++)
  38. {
  39. var gameBone = skin.GetIGameBone(unsortedIndex, false);
  40. int index = gameBone == null ? boneIds.IndexOf(-2) : boneIds.IndexOf(gameBone.NodeID);
  41. if (gameBone == null)
  42. {
  43. gameBones[index]=null;
  44. bones[index] = new BabylonBone { index = index, name = "null-bone" };
  45. bindPoseInfos[index] = new BonePoseInfo { };
  46. }
  47. else
  48. {
  49. gameBones[index] = gameBone;
  50. bones[index] = new BabylonBone { index = index, name = gameBone.Name };
  51. //IGMatrix boneInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
  52. var boneInitMatrix = gameBone.GetObjectTM(0);
  53. bindPoseInfos[index] = new BonePoseInfo { AbsoluteTransform = boneInitMatrix };
  54. }
  55. }
  56. // fix hierarchy an generate animation keys
  57. for (var index = 0; index < skin.TotalSkinBoneCount; index++)
  58. {
  59. var gameBone = gameBones[index];
  60. if (gameBone == null)
  61. {
  62. var babBone = bones[index];
  63. bindPoseInfos[index].LocalTransform = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
  64. babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();
  65. }
  66. else
  67. {
  68. var parent = gameBone.NodeParent;
  69. var babBone = bones[index];
  70. if (parent != null)
  71. {
  72. babBone.parentBoneIndex = boneIds.IndexOf(parent.NodeID);
  73. }
  74. if (babBone.parentBoneIndex == -1)
  75. {
  76. bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(meshInitMatrix.Inverse);
  77. }
  78. else
  79. {
  80. var parentBindPoseInfos = bindPoseInfos[babBone.parentBoneIndex];
  81. bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(parentBindPoseInfos.AbsoluteTransform.Inverse);
  82. }
  83. babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();
  84. var babylonAnimation = new BabylonAnimation
  85. {
  86. name = gameBone.Name + "Animation",
  87. property = "_matrix",
  88. dataType = BabylonAnimation.DataType.Matrix,
  89. loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
  90. framePerSecond = Loader.Global.FrameRate
  91. };
  92. var start = Loader.Core.AnimRange.Start;
  93. var end = Loader.Core.AnimRange.End;
  94. float[] previous = null;
  95. var keys = new List<BabylonAnimationKey>();
  96. for (var key = start; key <= end; key += Ticks)
  97. {
  98. var objectTM = gameBone.GetObjectTM(key);
  99. var parentNode = gameBone.NodeParent;
  100. IGMatrix mat;
  101. if (parentNode == null || babBone.parentBoneIndex == -1)
  102. {
  103. mat = objectTM.Multiply(meshNode.GetObjectTM(key).Inverse);
  104. }
  105. else
  106. {
  107. mat = objectTM.Multiply(parentNode.GetObjectTM(key).Inverse);
  108. }
  109. var current = mat.ToArray();
  110. if (key == start || key == end || !(previous.IsEqualTo(current)))
  111. {
  112. keys.Add(new BabylonAnimationKey
  113. {
  114. frame = key / Ticks,
  115. values = current
  116. });
  117. }
  118. previous = current;
  119. }
  120. babylonAnimation.keys = keys.ToArray();
  121. babBone.animation = babylonAnimation;
  122. }
  123. }
  124. babylonSkeleton.bones = bones;
  125. babylonScene.SkeletonsList.Add(babylonSkeleton);
  126. }
  127. }
  128. }