Skip to content

Commit f1664d0

Browse files
committed
use a set so duplicate bones are not added
- currently assuming there is exactly one root bone - calculate bind poses before finding transform matrix - delete commented out code
1 parent e398ce2 commit f1664d0

File tree

1 file changed

+69
-63
lines changed

1 file changed

+69
-63
lines changed

Assets/FbxExporters/Editor/FbxExporter.cs

Lines changed: 69 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -786,44 +786,48 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene)
786786
}
787787

788788
// Step 1: create the bones.
789-
List<Transform> boneList = new List<Transform> ();
790-
Queue<Transform> q = new Queue<Transform> (bones);
791-
while (q.Count > 0) {
792-
var v = q.Dequeue ();
793-
794-
if (IsBone(v, index)) {
795-
// Create the bone node if we haven't already. Parent it to
796-
// its corresponding parent, or to the scene if there is none.
797-
FbxNode fbxBoneNode;
798-
if (!MapUnityObjectToFbxNode.TryGetValue (v.gameObject, out fbxBoneNode)) {
799-
if (ExportSettings.mayaCompatibleNames) {
800-
v.name = ConvertToMayaCompatibleName (v.name);
789+
HashSet<Transform> boneSet = new HashSet<Transform> ();
790+
var s = new Stack<Transform> ();
791+
s.Push(skinnedMesh.rootBone);
792+
while (s.Count > 0) {
793+
var t = s.Pop();
794+
795+
if (IsBone(t, index)) {
796+
if (!boneSet.Contains (t)) {
797+
// Create the bone node if we haven't already. Parent it to
798+
// its corresponding parent, or to the scene if there is none.
799+
FbxNode fbxBoneNode;
800+
if (!MapUnityObjectToFbxNode.TryGetValue (t.gameObject, out fbxBoneNode)) {
801+
if (ExportSettings.mayaCompatibleNames) {
802+
t.name = ConvertToMayaCompatibleName (t.name);
803+
}
804+
fbxBoneNode = FbxNode.Create (fbxScene, t.name);
805+
fbxBoneNode.SetTransformationInheritType (FbxTransform.EInheritType.eInheritRSrs);
806+
MapUnityObjectToFbxNode.Add (t.gameObject, fbxBoneNode);
801807
}
802-
fbxBoneNode = FbxNode.Create (fbxScene, v.name);
803-
fbxBoneNode.SetTransformationInheritType (FbxTransform.EInheritType.eInheritRSrs);
804-
MapUnityObjectToFbxNode.Add (v.gameObject, fbxBoneNode);
805-
}
806808

807-
// Set it up as a skeleton node if we haven't already.
808-
if (fbxBoneNode.GetSkeleton() == null) {
809-
FbxSkeleton fbxSkeleton = FbxSkeleton.Create (fbxScene, v.name + "_Skel");
809+
// Set it up as a skeleton node if we haven't already.
810+
if (fbxBoneNode.GetSkeleton () == null) {
811+
FbxSkeleton fbxSkeleton = FbxSkeleton.Create (fbxScene, t.name + "_Skel");
810812

811-
var fbxSkeletonType = skinnedMesh.rootBone != v//index.ContainsKey(unityBoneTransform.parent)
813+
var fbxSkeletonType = skinnedMesh.rootBone != t
812814
? FbxSkeleton.EType.eLimbNode : FbxSkeleton.EType.eRoot;
813-
fbxSkeleton.SetSkeletonType (fbxSkeletonType);
814-
fbxSkeleton.Size.Set (1.0f*UnitScaleFactor);
815-
fbxBoneNode.SetNodeAttribute (fbxSkeleton);
816-
}
815+
fbxSkeleton.SetSkeletonType (fbxSkeletonType);
816+
fbxSkeleton.Size.Set (1.0f * UnitScaleFactor);
817+
fbxBoneNode.SetNodeAttribute (fbxSkeleton);
818+
}
817819

818-
boneList.Add (v);
820+
boneSet.Add (t);
821+
}
819822

820-
foreach (Transform child in v) {
821-
q.Enqueue (child);
823+
foreach (Transform child in t) {
824+
s.Push (child);
822825
}
823826
}
824827
}
825828

826829
// Step 2: connect up the hierarchy.
830+
var boneList = boneSet.ToArray();
827831
foreach (var unityBone in boneList) {
828832
if (unityBone.parent != null && MapUnityObjectToFbxNode.ContainsKey(unityBone.parent.gameObject)) {
829833
var fbxBone = MapUnityObjectToFbxNode [unityBone.gameObject];
@@ -832,8 +836,45 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene)
832836
}
833837
}
834838

839+
// Get bindposes
840+
var boneToBindPose = new Dictionary<Transform, Matrix4x4>();
841+
for (int boneIndex = 0, n = boneList.Length; boneIndex < n; boneIndex++) {
842+
var unityBone = boneList [boneIndex];
843+
844+
Matrix4x4 pose;
845+
if (index.ContainsKey (unityBone)) {
846+
int i = index [unityBone];
847+
pose = bindPoses [i];
848+
} else {
849+
pose = unityBone.worldToLocalMatrix * skinnedMesh.transform.localToWorldMatrix;
850+
}
851+
boneToBindPose.Add (unityBone, pose);
852+
}
853+
835854
// Step 3: set up the transforms.
836-
for (int boneIndex = 0, n = boneList.Count; boneIndex < n; boneIndex++) {
855+
for (int boneIndex = 0, n = boneList.Length; boneIndex < n; boneIndex++) {
856+
var unityBone = boneList [boneIndex];
857+
var fbxBone = MapUnityObjectToFbxNode [unityBone.gameObject];
858+
859+
Matrix4x4 pose;
860+
861+
var bindPose = boneToBindPose [unityBone];
862+
863+
if (fbxBone.GetSkeleton ().GetSkeletonType () == FbxSkeleton.EType.eRoot) {
864+
// bind pose is local -> root. We want root -> local, so invert.
865+
var parentTransform = skinnedMesh.transform;
866+
var parentMatrix = Matrix4x4.TRS (parentTransform.localPosition, parentTransform.localRotation, parentTransform.localScale);
867+
868+
pose = parentMatrix * bindPose.inverse;
869+
} else {
870+
// Bind pose is local -> parent -> ... -> root.
871+
// We want parent -> local.
872+
// Invert our bind pose to get root -> local.
873+
// The apply parent -> root to leave just parent -> local.
874+
pose = boneToBindPose [unityBone.parent] * bindPose.inverse;
875+
}
876+
877+
/*for (int boneIndex = 0, n = boneList.Length; boneIndex < n; boneIndex++) {
837878
var unityBone = boneList [boneIndex];
838879
var fbxBone = MapUnityObjectToFbxNode [unityBone.gameObject];
839880
@@ -864,41 +905,6 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene)
864905
}
865906
} else {
866907
pose = Matrix4x4.TRS (unityBone.localPosition, unityBone.localRotation, unityBone.localScale);
867-
}
868-
869-
/*for (int boneIndex = 0, n = bones.Length; boneIndex < n; boneIndex++) {
870-
var unityBone = bones[boneIndex];
871-
var fbxBone = MapUnityObjectToFbxNode[unityBone.gameObject];
872-
873-
Matrix4x4 pose;
874-
if (fbxBone.GetSkeleton().GetSkeletonType() == FbxSkeleton.EType.eRoot) {
875-
// bind pose is local -> root. We want root -> local, so invert.
876-
var parentTransform = skinnedMesh.transform;
877-
var parentMatrix = Matrix4x4.TRS (parentTransform.localPosition, parentTransform.localRotation, parentTransform.localScale);
878-
879-
pose = parentMatrix * bindPoses[boneIndex].inverse;
880-
} else {
881-
if (index.ContainsKey (unityBone.parent)) {
882-
// Bind pose is local -> parent -> ... -> root.
883-
// We want parent -> local.
884-
// Invert our bind pose to get root -> local.
885-
// The apply parent -> root to leave just parent -> local.
886-
pose = bindPoses [index [unityBone.parent]] * bindPoses [boneIndex].inverse;
887-
} else if (unityBone.parent != null) {
888-
//var parentPose = Matrix4x4.TRS (unityBone.parent.localPosition, unityBone.parent.localRotation, unityBone.parent.localScale);
889-
var parentPose = unityBone.parent.worldToLocalMatrix * skinnedMesh.transform.localToWorldMatrix;
890-
//var p = unityBone.parent;
891-
//while (p != null && !index.ContainsKey (p)) {
892-
// p = p.parent;
893-
//}
894-
//if (p != null) {
895-
// parentPose = bindPoses [index [p]];
896-
//}
897-
898-
pose = parentPose * bindPoses [boneIndex].inverse;
899-
} else {
900-
pose = Matrix4x4.identity;
901-
}
902908
}*/
903909

904910
// FBX is transposed relative to Unity: transpose as we convert.

0 commit comments

Comments
 (0)