@@ -789,16 +789,58 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene)
789
789
// Set it up as a skeleton node if we haven't already.
790
790
if ( fbxBoneNode . GetSkeleton ( ) == null ) {
791
791
FbxSkeleton fbxSkeleton = FbxSkeleton . Create ( fbxScene , unityBoneTransform . name + "_Skel" ) ;
792
- var fbxSkeletonType = index . ContainsKey ( unityBoneTransform . parent )
792
+
793
+ var fbxSkeletonType = skinnedMesh . rootBone != unityBoneTransform //index.ContainsKey(unityBoneTransform.parent)
793
794
? FbxSkeleton . EType . eLimbNode : FbxSkeleton . EType . eRoot ;
794
795
fbxSkeleton . SetSkeletonType ( fbxSkeletonType ) ;
795
796
fbxSkeleton . Size . Set ( 1.0f * UnitScaleFactor ) ;
796
797
fbxBoneNode . SetNodeAttribute ( fbxSkeleton ) ;
797
798
}
798
799
}
799
800
801
+ List < Transform > boneList = new List < Transform > ( bones ) ;
802
+ Queue < Transform > q = new Queue < Transform > ( ) ;
803
+ q . Enqueue ( skinnedMesh . rootBone ) ;
804
+ while ( q . Count > 0 ) {
805
+ var v = q . Dequeue ( ) ;
806
+
807
+ if ( ! index . ContainsKey ( v ) && v . childCount > 0 ) {
808
+ FbxNode fbxBoneNode ;
809
+ if ( ! MapUnityObjectToFbxNode . TryGetValue ( v . gameObject , out fbxBoneNode ) ) {
810
+ if ( ExportSettings . mayaCompatibleNames ) {
811
+ v . name = ConvertToMayaCompatibleName ( v . name ) ;
812
+ }
813
+ fbxBoneNode = FbxNode . Create ( fbxScene , v . name ) ;
814
+ fbxBoneNode . SetTransformationInheritType ( FbxTransform . EInheritType . eInheritRSrs ) ;
815
+ MapUnityObjectToFbxNode . Add ( v . gameObject , fbxBoneNode ) ;
816
+ }
817
+
818
+ // Set it up as a skeleton node if we haven't already.
819
+ if ( fbxBoneNode . GetSkeleton ( ) == null ) {
820
+ FbxSkeleton fbxSkeleton = FbxSkeleton . Create ( fbxScene , v . name + "_Skel" ) ;
821
+
822
+ var fbxSkeletonType = skinnedMesh . rootBone != v //index.ContainsKey(unityBoneTransform.parent)
823
+ ? FbxSkeleton . EType . eLimbNode : FbxSkeleton . EType . eRoot ;
824
+ fbxSkeleton . SetSkeletonType ( fbxSkeletonType ) ;
825
+ fbxSkeleton . Size . Set ( 1.0f * UnitScaleFactor ) ;
826
+ fbxBoneNode . SetNodeAttribute ( fbxSkeleton ) ;
827
+ }
828
+
829
+ if ( v . parent != null && MapUnityObjectToFbxNode . ContainsKey ( v . parent . gameObject ) ) {
830
+ var fbxParent = MapUnityObjectToFbxNode [ v . parent . gameObject ] ;
831
+ fbxParent . AddChild ( fbxBoneNode ) ;
832
+ }
833
+
834
+ boneList . Add ( v ) ;
835
+ }
836
+
837
+ foreach ( Transform child in v ) {
838
+ q . Enqueue ( child ) ;
839
+ }
840
+ }
841
+
800
842
// Step 2: connect up the hierarchy.
801
- foreach ( var unityBone in bones ) {
843
+ foreach ( var unityBone in boneList ) {
802
844
if ( unityBone . parent != null && MapUnityObjectToFbxNode . ContainsKey ( unityBone . parent . gameObject ) ) {
803
845
var fbxBone = MapUnityObjectToFbxNode [ unityBone . gameObject ] ;
804
846
var fbxParent = MapUnityObjectToFbxNode [ unityBone . parent . gameObject ] ;
@@ -807,7 +849,38 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene)
807
849
}
808
850
809
851
// Step 3: set up the transforms.
810
- for ( int boneIndex = 0 , n = bones . Length ; boneIndex < n ; boneIndex ++ ) {
852
+ for ( int boneIndex = 0 , n = boneList . Count ; boneIndex < n ; boneIndex ++ ) {
853
+ var unityBone = boneList [ boneIndex ] ;
854
+ var fbxBone = MapUnityObjectToFbxNode [ unityBone . gameObject ] ;
855
+
856
+ Matrix4x4 pose ;
857
+ if ( boneIndex < bones . Length ) {
858
+ if ( fbxBone . GetSkeleton ( ) . GetSkeletonType ( ) == FbxSkeleton . EType . eRoot ) {
859
+ // bind pose is local -> root. We want root -> local, so invert.
860
+ var parentTransform = skinnedMesh . transform ;
861
+ var parentMatrix = Matrix4x4 . TRS ( parentTransform . localPosition , parentTransform . localRotation , parentTransform . localScale ) ;
862
+
863
+ pose = parentMatrix * bindPoses [ boneIndex ] . inverse ;
864
+ } else {
865
+ if ( index . ContainsKey ( unityBone . parent ) ) {
866
+ // Bind pose is local -> parent -> ... -> root.
867
+ // We want parent -> local.
868
+ // Invert our bind pose to get root -> local.
869
+ // The apply parent -> root to leave just parent -> local.
870
+ pose = bindPoses [ index [ unityBone . parent ] ] * bindPoses [ boneIndex ] . inverse ;
871
+ } else if ( unityBone . parent != null ) {
872
+ //var parentPose = Matrix4x4.TRS (unityBone.parent.localPosition, unityBone.parent.localRotation, unityBone.parent.localScale);
873
+ var parentPose = unityBone . parent . worldToLocalMatrix * skinnedMesh . transform . localToWorldMatrix ;
874
+ pose = parentPose * bindPoses [ boneIndex ] . inverse ;
875
+ } else {
876
+ pose = Matrix4x4 . identity ;
877
+ }
878
+ }
879
+ } else {
880
+ pose = Matrix4x4 . TRS ( unityBone . localPosition , unityBone . localRotation , unityBone . localScale ) ;
881
+ }
882
+
883
+ /*for (int boneIndex = 0, n = bones.Length; boneIndex < n; boneIndex++) {
811
884
var unityBone = bones[boneIndex];
812
885
var fbxBone = MapUnityObjectToFbxNode[unityBone.gameObject];
813
886
@@ -819,12 +892,28 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene)
819
892
820
893
pose = parentMatrix * bindPoses[boneIndex].inverse;
821
894
} else {
822
- // Bind pose is local -> parent -> ... -> root.
823
- // We want parent -> local.
824
- // Invert our bind pose to get root -> local.
825
- // The apply parent -> root to leave just parent -> local.
826
- pose = bindPoses [ index [ unityBone . parent ] ] * bindPoses [ boneIndex ] . inverse ;
827
- }
895
+ if (index.ContainsKey (unityBone.parent)) {
896
+ // Bind pose is local -> parent -> ... -> root.
897
+ // We want parent -> local.
898
+ // Invert our bind pose to get root -> local.
899
+ // The apply parent -> root to leave just parent -> local.
900
+ pose = bindPoses [index [unityBone.parent]] * bindPoses [boneIndex].inverse;
901
+ } else if (unityBone.parent != null) {
902
+ //var parentPose = Matrix4x4.TRS (unityBone.parent.localPosition, unityBone.parent.localRotation, unityBone.parent.localScale);
903
+ var parentPose = unityBone.parent.worldToLocalMatrix * skinnedMesh.transform.localToWorldMatrix;
904
+ //var p = unityBone.parent;
905
+ //while (p != null && !index.ContainsKey (p)) {
906
+ // p = p.parent;
907
+ //}
908
+ //if (p != null) {
909
+ // parentPose = bindPoses [index [p]];
910
+ //}
911
+
912
+ pose = parentPose * bindPoses [boneIndex].inverse;
913
+ } else {
914
+ pose = Matrix4x4.identity;
915
+ }
916
+ }*/
828
917
829
918
// FBX is transposed relative to Unity: transpose as we convert.
830
919
FbxMatrix matrix = new FbxMatrix ( ) ;
0 commit comments