Skip to content

Commit 3d277bf

Browse files
committed
reuse bone transform export
use same code path to export bone transforms, whether or not we are exporting animation only
1 parent fd4ab51 commit 3d277bf

File tree

1 file changed

+61
-108
lines changed

1 file changed

+61
-108
lines changed

Assets/FbxExporters/Editor/FbxExporter.cs

Lines changed: 61 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,28 @@ private bool IsBone (Transform t, Dictionary<Transform, int> bones)
915915
return false;
916916
}
917917

918+
/// <summary>
919+
/// Gets the bind pose for the Unity bone.
920+
/// </summary>
921+
/// <returns>The bind pose.</returns>
922+
/// <param name="unityBone">Unity bone.</param>
923+
/// <param name="bindPoses">Bind poses.</param>
924+
/// <param name="boneDict">Dictionary of bone to index.</param>
925+
/// <param name="skinnedMesh">Skinned mesh.</param>
926+
private Matrix4x4 GetBindPose(
927+
Transform unityBone, Matrix4x4[] bindPoses,
928+
Dictionary<Transform, int> boneDict, SkinnedMeshRenderer skinnedMesh
929+
){
930+
Matrix4x4 bindPose;
931+
int index;
932+
if (boneDict.TryGetValue (unityBone, out index)) {
933+
bindPose = bindPoses [index];
934+
} else {
935+
bindPose = unityBone.worldToLocalMatrix * skinnedMesh.transform.localToWorldMatrix;
936+
}
937+
return bindPose;
938+
}
939+
918940
/// <summary>
919941
/// Export bones of skinned mesh, if this is a skinned mesh with
920942
/// bones and bind poses.
@@ -971,17 +993,6 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene,
971993
Debug.LogErrorFormat("Node {0} should already be created", t.name);
972994
}
973995

974-
// Set it up as a skeleton node if we haven't already.
975-
if (fbxBoneNode.GetSkeleton () == null) {
976-
FbxSkeleton fbxSkeleton = FbxSkeleton.Create (fbxScene, t.name + SkeletonPrefix);
977-
978-
var fbxSkeletonType = skinnedMesh.rootBone != t
979-
? FbxSkeleton.EType.eLimbNode : FbxSkeleton.EType.eRoot;
980-
fbxSkeleton.SetSkeletonType (fbxSkeletonType);
981-
fbxSkeleton.Size.Set (1.0f * UnitScaleFactor);
982-
fbxBoneNode.SetNodeAttribute (fbxSkeleton);
983-
}
984-
985996
boneSet.Add (t);
986997
}
987998

@@ -992,69 +1003,13 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene,
9921003
}
9931004

9941005
var boneList = boneSet.ToArray();
995-
9961006
skinnedMeshToBonesMap.Add (skinnedMesh, boneList);
9971007

998-
// Step 2: Get bindposes
999-
var boneToBindPose = new Dictionary<Transform, Matrix4x4>();
1000-
for (int boneIndex = 0, n = boneList.Length; boneIndex < n; boneIndex++) {
1001-
var unityBone = boneList [boneIndex];
1002-
1003-
Matrix4x4 pose;
1004-
if (index.ContainsKey (unityBone)) {
1005-
int i = index [unityBone];
1006-
pose = bindPoses [i];
1007-
} else {
1008-
pose = unityBone.worldToLocalMatrix * skinnedMesh.transform.localToWorldMatrix;
1009-
}
1010-
boneToBindPose.Add (unityBone, pose);
1008+
var boneInfo = new SkinnedMeshBoneInfo (skinnedMesh, index);
1009+
foreach (var bone in boneList) {
1010+
var fbxBone = MapUnityObjectToFbxNode [bone.gameObject];
1011+
ExportBoneTransform (fbxBone, fbxScene, bone, boneInfo);
10111012
}
1012-
1013-
// Step 3: set up the transforms.
1014-
for (int boneIndex = 0, n = boneList.Length; boneIndex < n; boneIndex++) {
1015-
var unityBone = boneList [boneIndex];
1016-
var fbxBone = MapUnityObjectToFbxNode [unityBone.gameObject];
1017-
1018-
Matrix4x4 pose;
1019-
1020-
var bindPose = boneToBindPose [unityBone];
1021-
1022-
if (fbxBone.GetSkeleton ().GetSkeletonType () == FbxSkeleton.EType.eRoot) {
1023-
// bind pose is local -> root. We want root -> local, so invert.
1024-
pose = (unityBone.parent.worldToLocalMatrix * skinnedMesh.transform.localToWorldMatrix * bindPose.inverse);
1025-
} else {
1026-
// Bind pose is local -> parent -> ... -> root.
1027-
// We want parent -> local.
1028-
// Invert our bind pose to get root -> local.
1029-
// The apply parent -> root to leave just parent -> local.
1030-
pose = boneToBindPose [unityBone.parent] * bindPose.inverse;
1031-
}
1032-
1033-
// FBX is transposed relative to Unity: transpose as we convert.
1034-
FbxMatrix matrix = new FbxMatrix ();
1035-
matrix.SetColumn (0, new FbxVector4 (pose.GetRow (0).x, pose.GetRow (0).y, pose.GetRow (0).z, pose.GetRow (0).w));
1036-
matrix.SetColumn (1, new FbxVector4 (pose.GetRow (1).x, pose.GetRow (1).y, pose.GetRow (1).z, pose.GetRow (1).w));
1037-
matrix.SetColumn (2, new FbxVector4 (pose.GetRow (2).x, pose.GetRow (2).y, pose.GetRow (2).z, pose.GetRow (2).w));
1038-
matrix.SetColumn (3, new FbxVector4 (pose.GetRow (3).x, pose.GetRow (3).y, pose.GetRow (3).z, pose.GetRow (3).w));
1039-
1040-
// FBX wants translation, rotation (in euler angles) and scale.
1041-
// We assume there's no real shear, just rounding error.
1042-
FbxVector4 translation, rotation, shear, scale;
1043-
double sign;
1044-
matrix.GetElements (out translation, out rotation, out shear, out scale, out sign);
1045-
1046-
// Export bones with zero rotation, using a pivot instead to set the rotation
1047-
// so that the bones are easier to animate and the rotation shows up as the "joint orientation" in Maya.
1048-
fbxBone.LclTranslation.Set (new FbxDouble3(-translation.X*UnitScaleFactor, translation.Y*UnitScaleFactor, translation.Z*UnitScaleFactor));
1049-
fbxBone.LclRotation.Set (new FbxDouble3(0,0,0));
1050-
fbxBone.LclScaling.Set (new FbxDouble3 (scale.X, scale.Y, scale.Z));
1051-
1052-
// TODO (UNI-34294): add detailed comment about why we export rotation as pre-rotation
1053-
fbxBone.SetRotationActive (true);
1054-
fbxBone.SetPivotState (FbxNode.EPivotSet.eSourcePivot, FbxNode.EPivotState.ePivotReference);
1055-
fbxBone.SetPreRotation (FbxNode.EPivotSet.eSourcePivot, new FbxVector4 (rotation.X, -rotation.Y, -rotation.Z));
1056-
}
1057-
10581013
return true;
10591014
}
10601015

@@ -2223,12 +2178,13 @@ protected int ExportAnimationOnly(
22232178
// remove the exported bones from the export set
22242179
exportData.goExportSet.ExceptWith (bones);
22252180

2181+
var boneInfo = new SkinnedMeshBoneInfo (skinnedMesh, boneDict);
22262182
foreach (var bone in bones) {
22272183
FbxNode node;
22282184
if (!ExportGameObjectAndParents (
22292185
bone.gameObject, unityGO, fbxScene, out node, newCenter,
22302186
exportType, ref numObjectsExported, objectCount,
2231-
new SkinnedMeshBoneInfo(skinnedMesh, boneDict)
2187+
boneInfo
22322188
)) {
22332189
// export cancelled
22342190
return -1;
@@ -2267,10 +2223,12 @@ protected int ExportAnimationOnly(
22672223
class SkinnedMeshBoneInfo {
22682224
public SkinnedMeshRenderer skinnedMesh;
22692225
public Dictionary<Transform, int> boneDict;
2226+
public Dictionary<Transform, Matrix4x4> boneToBindPose;
22702227

22712228
public SkinnedMeshBoneInfo(SkinnedMeshRenderer skinnedMesh, Dictionary<Transform, int> boneDict){
22722229
this.skinnedMesh = skinnedMesh;
22732230
this.boneDict = boneDict;
2231+
this.boneToBindPose = new Dictionary<Transform, Matrix4x4>();
22742232
}
22752233
}
22762234

@@ -2323,48 +2281,48 @@ private bool ExportGameObjectAndParents(
23232281
ExportTransform (unityGo.transform, fbxNode, newCenter, exportType);
23242282
}
23252283

2326-
if (unityGo.transform.parent != null || unityGo.transform.parent != rootObject.transform.parent) {
2327-
SkinnedMeshBoneInfo parentBoneInfo = null;
2328-
if (boneInfo != null && boneInfo.skinnedMesh.rootBone != null && unityGo.transform != boneInfo.skinnedMesh.rootBone) {
2329-
parentBoneInfo = boneInfo;
2330-
}
2331-
2332-
FbxNode fbxNodeParent;
2333-
if (!ExportGameObjectAndParents (
2334-
unityGo.transform.parent.gameObject,
2335-
rootObject,
2336-
fbxScene,
2337-
out fbxNodeParent,
2338-
newCenter,
2339-
TransformExportType.Local,
2340-
ref exportProgress,
2341-
objectCount,
2342-
parentBoneInfo
2343-
)) {
2344-
// export cancelled
2345-
return false;
2346-
}
2347-
fbxNodeParent.AddChild (fbxNode);
2348-
}
2349-
23502284
if (unityGo == rootObject || unityGo.transform.parent == null) {
23512285
fbxScene.GetRootNode ().AddChild (fbxNode);
2286+
return true;
23522287
}
23532288

2289+
SkinnedMeshBoneInfo parentBoneInfo = null;
2290+
if (boneInfo != null && boneInfo.skinnedMesh.rootBone != null && unityGo.transform != boneInfo.skinnedMesh.rootBone) {
2291+
parentBoneInfo = boneInfo;
2292+
}
2293+
2294+
FbxNode fbxNodeParent;
2295+
if (!ExportGameObjectAndParents (
2296+
unityGo.transform.parent.gameObject,
2297+
rootObject,
2298+
fbxScene,
2299+
out fbxNodeParent,
2300+
newCenter,
2301+
TransformExportType.Local,
2302+
ref exportProgress,
2303+
objectCount,
2304+
parentBoneInfo
2305+
)) {
2306+
// export cancelled
2307+
return false;
2308+
}
2309+
fbxNodeParent.AddChild (fbxNode);
2310+
23542311
return true;
23552312
}
23562313

23572314
private bool ExportBoneTransform(
23582315
FbxNode fbxNode, FbxScene fbxScene, Transform unityBone, SkinnedMeshBoneInfo boneInfo
23592316
){
2360-
if (boneInfo != null || boneInfo.skinnedMesh == null || boneInfo.boneDict == null || unityBone == null) {
2317+
if (boneInfo == null || boneInfo.skinnedMesh == null || boneInfo.boneDict == null || unityBone == null) {
23612318
return false;
23622319
}
23632320

23642321
var skinnedMesh = boneInfo.skinnedMesh;
23652322
var boneDict = boneInfo.boneDict;
23662323
var rootBone = skinnedMesh.rootBone;
23672324

2325+
// setup the skeleton
23682326
var fbxSkeleton = fbxNode.GetSkeleton ();
23692327
if (fbxSkeleton == null) {
23702328
fbxSkeleton = FbxSkeleton.Create (fbxScene, unityBone.name + SkeletonPrefix);
@@ -2380,26 +2338,21 @@ private bool ExportBoneTransform(
23802338

23812339
// get bind pose
23822340
Matrix4x4 bindPose;
2383-
int index;
2384-
if (boneDict.TryGetValue (unityBone, out index)) {
2385-
bindPose = bindPoses [index];
2386-
} else {
2387-
bindPose = unityBone.worldToLocalMatrix * skinnedMesh.transform.localToWorldMatrix;
2341+
if (!boneInfo.boneToBindPose.TryGetValue (unityBone, out bindPose)) {
2342+
bindPose = GetBindPose (unityBone, bindPoses, boneDict, skinnedMesh);
2343+
boneInfo.boneToBindPose.Add (unityBone, bindPose);
23882344
}
23892345

23902346
Matrix4x4 pose;
23912347
if (unityBone == rootBone) {
23922348
pose = (unityBone.parent.worldToLocalMatrix * skinnedMesh.transform.localToWorldMatrix * bindPose.inverse);
23932349
} else {
23942350
// get parent's bind pose
2395-
int pIndex;
23962351
Matrix4x4 parentBindPose;
2397-
if (boneDict.TryGetValue (unityBone.parent, out pIndex)) {
2398-
parentBindPose = bindPoses [pIndex];
2399-
} else {
2400-
parentBindPose = unityBone.parent.worldToLocalMatrix * skinnedMesh.transform.localToWorldMatrix;
2352+
if (!boneInfo.boneToBindPose.TryGetValue (unityBone.parent, out parentBindPose)) {
2353+
parentBindPose = GetBindPose (unityBone.parent, bindPoses, boneDict, skinnedMesh);
2354+
boneInfo.boneToBindPose.Add (unityBone.parent, parentBindPose);
24012355
}
2402-
24032356
pose = parentBindPose * bindPose.inverse;
24042357
}
24052358

0 commit comments

Comments
 (0)