Skip to content

Commit e6ab2c8

Browse files
committed
Merge branch 'master' into temp-merge-master-3.0
2 parents 578298e + 05fda21 commit e6ab2c8

File tree

7 files changed

+200
-189
lines changed

7 files changed

+200
-189
lines changed

appcollector.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
application_name: FBX Exporter
2+
application_type: Package
3+
language: C#
4+
development_stage: Production
5+
findings_access:
6+
7+
8+
organization: 5d8b8596cadf01000a30db1f
9+
10+
slack_channel: devs-fbx-exporter
11+
description: The Unity FBX Exporter package makes it easy to send geometry and animation from Unity 2018.3 or later to any application that supports FBX and back again with minimal effort.\n\nIn particular, this round-trip workflow enables you to export Unity scenes to FBX, import into Maya, Maya LT, or 3ds Max using an artist-friendly interface, export Unity-ready FBX geometry and animation, and safely merge your changes back into those Assets to continue your work.\n\nFor more information, see the FBX Exporter package documentation.
12+
risk_assessment:
13+
internet_facing: false
14+
personal_info: false
15+
payment_info: false
16+
authentication: No Authentication
17+
hosting: N/A
18+
revenue_impact: false
19+
pci: false

com.unity.formats.fbx/Editor/FbxExportSettings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ public bool HideSendToUnityMenuProperty
462462
}
463463

464464
[SerializeField]
465-
private bool BakeAnimation = true;
465+
private bool BakeAnimation = false;
466466
internal bool BakeAnimationProperty
467467
{
468468
get { return BakeAnimation; }
@@ -580,7 +580,7 @@ internal override void LoadDefaults()
580580
integrationSavePath = DefaultIntegrationSavePath;
581581
dccOptionPaths = null;
582582
dccOptionNames = null;
583-
BakeAnimationProperty = true;
583+
BakeAnimationProperty = false;
584584
ExportModelSettings = ScriptableObject.CreateInstance (typeof(ExportModelSettings)) as ExportModelSettings;
585585
exportModelSettingsSerialize = ExportModelSettings.info;
586586
ShowConvertToPrefabDialog = true;

com.unity.formats.fbx/Editor/FbxExporter.cs

Lines changed: 100 additions & 140 deletions
Large diffs are not rendered by default.

com.unity.formats.fbx/Editor/FbxPropertyChannelPair.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ public PropertyChannelMap(Dictionary<string,string> propertyMap, Dictionary<stri
6161
{ "Motion T", "Lcl Translation" },
6262
{ "m_TranslationOffset", "Translation" },
6363
{ "m_ScaleOffset", "Scaling" },
64-
{ "m_RotationOffset", "Rotation" }
64+
{ "m_RotationOffset", "Rotation" },
65+
{ "localEulerAnglesRaw", "Lcl Rotation" }
6566
};
6667

6768
/// <summary>

com.unity.formats.fbx/Editor/FbxRotationCurve.cs

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,11 @@ private Key [] ComputeKeys(UnityEngine.Quaternion restRotation, FbxNode node) {
5454
: new FbxVector4();
5555

5656
// Get the inverse of the prerotation
57-
var fbxPreRotationInverse = ModelExporter.EulerToQuaternion (fbxPreRotationEuler);
57+
var fbxPreRotationInverse = ModelExporter.EulerToQuaternionXYZ (fbxPreRotationEuler);
5858
fbxPreRotationInverse.Inverse();
5959

6060
// Find when we have keys set.
61-
var keyTimes =
62-
(UnityEditor.Formats.Fbx.Exporter.ModelExporter.ExportSettings.BakeAnimationProperty)
63-
? ModelExporter.GetSampleTimes(GetCurves(), SampleRate)
64-
: ModelExporter.GetKeyTimes(GetCurves());
61+
var keyTimes = ModelExporter.GetSampleTimes(GetCurves(), SampleRate);
6562

6663
// Convert to the Key type.
6764
var keys = new Key[keyTimes.Count];
@@ -76,10 +73,12 @@ private Key [] ComputeKeys(UnityEngine.Quaternion restRotation, FbxNode node) {
7673
// then animation.
7774
var fbxFinalQuat = fbxPreRotationInverse * fbxFinalAnimation;
7875

76+
var finalUnityQuat = new Quaternion((float)fbxFinalQuat.X, (float)fbxFinalQuat.Y, (float)fbxFinalQuat.Z, (float)fbxFinalQuat.W);
77+
7978
// Store the key so we can sort them later.
8079
Key key = new Key();
8180
key.time = FbxTime.FromSecondDouble(seconds);
82-
key.euler = ModelExporter.QuaternionToEuler (fbxFinalQuat);
81+
key.euler = ModelExporter.ConvertToFbxVector4(finalUnityQuat.eulerAngles);
8382
keys[i++] = key;
8483
}
8584

@@ -118,12 +117,6 @@ public void Animate(Transform unityTransform, FbxNode fbxNode, FbxAnimLayer fbxA
118117
}
119118
}
120119

121-
// Uni-35616 unroll curves to preserve continuous rotations
122-
var fbxCurveNode = fbxNode.LclRotation.GetCurveNode(fbxAnimLayer, false /*should already exist*/);
123-
124-
FbxAnimCurveFilterUnroll fbxAnimUnrollFilter = new FbxAnimCurveFilterUnroll();
125-
fbxAnimUnrollFilter.Apply(fbxCurveNode);
126-
127120
if (Verbose) {
128121
Debug.Log("Exported rotation animation for " + fbxNode.GetName());
129122
}
@@ -170,16 +163,15 @@ protected override FbxQuaternion GetConvertedQuaternionRotation (float seconds,
170163
// The final animation, including the effect of pre-rotation.
171164
// If we have no curve, assume the node has the correct rotation right now.
172165
// We need to evaluate since we might only have keys in one of the axes.
173-
var unityFinalAnimation = Quaternion.Euler (
166+
var unityFinalAnimation = new Vector3 (
174167
(x == null) ? eulerRest [0] : x.Evaluate (seconds),
175168
(y == null) ? eulerRest [1] : y.Evaluate (seconds),
176169
(z == null) ? eulerRest [2] : z.Evaluate (seconds)
177170
);
178171

179172
// convert the final animation to righthanded coords
180-
var finalEuler = ModelExporter.ConvertQuaternionToXYZEuler(unityFinalAnimation);
181173

182-
return ModelExporter.EulerToQuaternion (new FbxVector4(finalEuler));
174+
return ModelExporter.EulerToQuaternionZXY (unityFinalAnimation);
183175
}
184176
}
185177

@@ -236,10 +228,7 @@ protected override FbxQuaternion GetConvertedQuaternionRotation (float seconds,
236228
(z == null) ? restRotation[2] : z.Evaluate(seconds),
237229
(w == null) ? restRotation[3] : w.Evaluate(seconds));
238230

239-
// convert the final animation to righthanded coords
240-
var finalEuler = ModelExporter.ConvertQuaternionToXYZEuler(fbxFinalAnimation);
241-
242-
return ModelExporter.EulerToQuaternion (finalEuler);
231+
return fbxFinalAnimation;
243232
}
244233
}
245234

com.unity.formats.fbx/Tests/FbxTests/FbxAnimationTest.cs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ public int Main (KeyData keyData, string testName, string path)
416416
bool hasQuatBinding =
417417
MapEulerToQuaternionPropertyName.TryGetValue (propertyBinding, out propertyBinding);
418418

419+
bool isRotation = AnimationTestDataClass.m_rotationEulerNames.Contains(curveBinding.propertyName) ||
420+
AnimationTestDataClass.m_rotationQuaternionNames.Contains(curveBinding.propertyName);
421+
419422
if (id==-1)
420423
id = keyData.GetIndexOf (propertyBinding);
421424

@@ -439,13 +442,13 @@ public int Main (KeyData keyData, string testName, string path)
439442
else
440443
{
441444
// compare by sampled keyvalues against original keydata
442-
KeyValuesTest (keyData.keyTimes, keyData.GetAltKeyValues (id), animCurveImported, curveBinding.propertyName);
445+
KeyValuesTest (keyData.keyTimes, keyData.GetAltKeyValues (id), animCurveImported, curveBinding.propertyName, isRotation);
443446
}
444447
}
445448
else
446449
{
447450
// compare by sampled keyvalues against original animCurve
448-
KeyValuesTest (animCurvesOriginal[id], animCurveImported, curveBinding.propertyName);
451+
KeyValuesTest (animCurvesOriginal[id], animCurveImported, curveBinding.propertyName, isRotation);
449452
}
450453
result++;
451454
}
@@ -497,14 +500,20 @@ public static void ClipTest(AnimationClip animClipOriginal, AnimationClip animCl
497500
continue;
498501
}
499502

503+
bool isRotation = AnimationTestDataClass.m_rotationEulerNames.Contains(curveBinding.propertyName) ||
504+
AnimationTestDataClass.m_rotationQuaternionNames.Contains(curveBinding.propertyName);
505+
500506
AnimationCurve animCurveOrig = AnimationUtility.GetEditorCurve (animClipOriginal, curveBinding);
501507
Assert.That (animCurveOrig, Is.Not.Null);
502508

503509
AnimationCurve animCurveImported = AnimationUtility.GetEditorCurve (animClipImported, impCurveBinding);
504510
Assert.That (animCurveImported, Is.Not.Null);
505511

506-
AnimTester.KeyValuesTest(animCurveImported, animCurveOrig,
507-
string.Format("path: {0}, property: {1}", curveBinding.path, curveBinding.propertyName));
512+
AnimTester.KeyValuesTest(
513+
animCurveImported,
514+
animCurveOrig,
515+
string.Format("path: {0}, property: {1}", curveBinding.path, curveBinding.propertyName),
516+
isRotation);
508517
}
509518
}
510519
}
@@ -545,7 +554,7 @@ public static void KeysTest (float [] expectedKeyTimes, float [] expectedKeyValu
545554
return ;
546555
}
547556

548-
public static void KeyValuesTest (float [] expectedKeyTimes, float [] expectedKeyValues, AnimationCurve actualAnimCurve, string message)
557+
public static void KeyValuesTest (float [] expectedKeyTimes, float [] expectedKeyValues, AnimationCurve actualAnimCurve, string message, bool isRotationCurve = false)
549558
{
550559
for (var i=0; i < expectedKeyTimes.Length; ++i)
551560
{
@@ -554,23 +563,45 @@ public static void KeyValuesTest (float [] expectedKeyTimes, float [] expectedKe
554563

555564
float actualKeyValue = actualAnimCurve.Evaluate(expectedKeyTime);
556565

557-
#if DEBUG_UNITTEST
566+
#if DEBUG_UNITTEST
558567
Debug.Log(string.Format("key time={0} expected={1} actual={2} delta={3}", expectedKeyTime.ToString(), expectedKeyValue.ToString(), actualKeyValue.ToString(), Mathf.Abs(expectedKeyValue-actualKeyValue).ToString()));
559-
#endif
560-
Assert.That(expectedKeyValue, Is.EqualTo(actualKeyValue).Within(0.000001), string.Format("{0} key ({1}) doesn't match", message, expectedKeyTime));
568+
#endif
569+
// also handles values that are equal but different signs (i.e. -90 == 270)
570+
if (isRotationCurve)
571+
{
572+
var expectedQuat = Quaternion.Euler(new Vector3(expectedKeyValue, 0, 0));
573+
var actualQuat = Quaternion.Euler(new Vector3(actualKeyValue, 0, 0));
574+
Assert.That(Quaternion.Angle(expectedQuat, actualQuat), Is.LessThan(0.1), string.Format("{0} key ({1}) doesn't match", message, expectedKeyTime));
575+
}
576+
else
577+
{
578+
Assert.That(expectedKeyValue, Is.EqualTo(actualKeyValue).Within(0.0001), string.Format("{0} key ({1}) doesn't match", message, expectedKeyTime));
579+
}
561580
}
562581
}
563582

564-
public static void KeyValuesTest (AnimationCurve expectedAnimCurve, AnimationCurve actualAnimCurve, string message)
583+
public static void KeyValuesTest (AnimationCurve expectedAnimCurve, AnimationCurve actualAnimCurve, string message, bool isRotationCurve = false)
565584
{
566585
foreach (var key in expectedAnimCurve.keys)
567586
{
568587
float actualKeyValue = actualAnimCurve.Evaluate(key.time);
569588

570-
#if DEBUG_UNITTEST
589+
#if DEBUG_UNITTEST
571590
Debug.Log(string.Format("key time={0} actual={1} expected={2} delta={3}", key.time.ToString(), key.value.ToString(), actualKeyValue.ToString(), Mathf.Abs(key.value-actualKeyValue).ToString()));
572-
#endif
573-
Assert.That(key.value, Is.EqualTo(actualKeyValue).Within(0.1), string.Format("{0} key ({1}) doesn't match", message, key.time));
591+
#endif
592+
var expectedKeyValue = key.value;
593+
594+
// also handles values that are equal but different signs (i.e. -90 == 270)
595+
if (isRotationCurve)
596+
{
597+
var expectedQuat = Quaternion.Euler(new Vector3(expectedKeyValue, 0, 0));
598+
var actualQuat = Quaternion.Euler(new Vector3(actualKeyValue, 0, 0));
599+
Assert.That(Quaternion.Angle(expectedQuat, actualQuat), Is.LessThan(0.1), string.Format("{0} key ({1}) doesn't match", message, key.time));
600+
}
601+
else
602+
{
603+
Assert.That(expectedKeyValue, Is.EqualTo(actualKeyValue).Within(0.1), string.Format("{0} key ({1}) doesn't match", message, key.time));
604+
}
574605
}
575606
}
576607

com.unity.formats.fbx/Tests/FbxTests/ModelExporterTest.cs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,6 @@ public void TestBasics ()
4343
var b = new Vector3(0,0,1);
4444
var crossLeft = Vector3.Cross(a,b);
4545

46-
var afbx = ModelExporter.ConvertToRightHanded(a);
47-
var bfbx = ModelExporter.ConvertToRightHanded(b);
48-
Assert.AreEqual(ModelExporter.ConvertToRightHanded(crossLeft), bfbx.CrossProduct(afbx));
49-
50-
// Test scale conversion. Nothing complicated here...
51-
var afbxPosition = ModelExporter.ConvertToRightHanded(a, ModelExporter.UnitScaleFactor);
52-
Assert.AreEqual(100, afbxPosition.Length());
53-
54-
// Test rotation conversion.
55-
var q = Quaternion.Euler(new Vector3(0, 90, 0));
56-
var fbxAngles = ModelExporter.ConvertQuaternionToXYZEuler(q);
57-
Assert.AreEqual(fbxAngles.X, 0);
58-
Assert.That(fbxAngles.Y, Is.InRange(-90.001, -89.999));
59-
Assert.AreEqual(fbxAngles.Z, 0);
60-
6146
Assert.That(ModelExporter.DefaultMaterial);
6247

6348
// Test non-static functions.
@@ -103,6 +88,32 @@ public void TestBasics ()
10388
ModelExporter.ExportObject(GetRandomFbxFilePath(), character);
10489
Assert.AreEqual(meshCount, Object.FindObjectsOfType<Mesh>().Length);
10590
}
91+
92+
// Test euler to quaternion conversion
93+
{
94+
// EulerToQuaternionZXY
95+
var v = new Vector3(50, 45, 190);
96+
var quat = ModelExporter.EulerToQuaternionZXY(v);
97+
var unityQuat = Quaternion.Euler(v);
98+
Assert.That((float)quat.X, Is.EqualTo(unityQuat.x));
99+
Assert.That((float)quat.Y, Is.EqualTo(unityQuat.y));
100+
Assert.That((float)quat.Z, Is.EqualTo(unityQuat.z));
101+
Assert.That((float)quat.W, Is.EqualTo(unityQuat.w));
102+
103+
// EulerToQuaternionXYZ
104+
var fbxV = new FbxVector4(v.x, v.y, v.z);
105+
var xyzQuat = ModelExporter.EulerToQuaternionXYZ(fbxV);
106+
107+
// get the vector from the quaternion
108+
FbxAMatrix m = new FbxAMatrix();
109+
m.SetR(fbxV);
110+
var actualQuat = m.GetQ();
111+
112+
// since this quaternion is XYZ instead of ZXY, it should not match the quaternion
113+
// created with EulerToQuaternionZXY
114+
Assert.That(xyzQuat, Is.Not.EqualTo(quat));
115+
Assert.That(xyzQuat, Is.EqualTo(actualQuat));
116+
}
106117
}
107118

108119
[Test]

0 commit comments

Comments
 (0)