@@ -786,44 +786,48 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene)
786
786
}
787
787
788
788
// 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 ) ;
801
807
}
802
- fbxBoneNode = FbxNode . Create ( fbxScene , v . name ) ;
803
- fbxBoneNode . SetTransformationInheritType ( FbxTransform . EInheritType . eInheritRSrs ) ;
804
- MapUnityObjectToFbxNode . Add ( v . gameObject , fbxBoneNode ) ;
805
- }
806
808
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" ) ;
810
812
811
- var fbxSkeletonType = skinnedMesh . rootBone != v //index.ContainsKey(unityBoneTransform.parent)
813
+ var fbxSkeletonType = skinnedMesh . rootBone != t
812
814
? 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
+ }
817
819
818
- boneList . Add ( v ) ;
820
+ boneSet . Add ( t ) ;
821
+ }
819
822
820
- foreach ( Transform child in v ) {
821
- q . Enqueue ( child ) ;
823
+ foreach ( Transform child in t ) {
824
+ s . Push ( child ) ;
822
825
}
823
826
}
824
827
}
825
828
826
829
// Step 2: connect up the hierarchy.
830
+ var boneList = boneSet . ToArray ( ) ;
827
831
foreach ( var unityBone in boneList ) {
828
832
if ( unityBone . parent != null && MapUnityObjectToFbxNode . ContainsKey ( unityBone . parent . gameObject ) ) {
829
833
var fbxBone = MapUnityObjectToFbxNode [ unityBone . gameObject ] ;
@@ -832,8 +836,45 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene)
832
836
}
833
837
}
834
838
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
+
835
854
// 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++) {
837
878
var unityBone = boneList [boneIndex];
838
879
var fbxBone = MapUnityObjectToFbxNode [unityBone.gameObject];
839
880
@@ -864,41 +905,6 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene)
864
905
}
865
906
} else {
866
907
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
- }
902
908
}*/
903
909
904
910
// FBX is transposed relative to Unity: transpose as we convert.
0 commit comments