Skip to content

Commit 7bbea0c

Browse files
committed
move rotationcurve and subclasses to a new file
1 parent 1c03bc2 commit 7bbea0c

File tree

3 files changed

+255
-233
lines changed

3 files changed

+255
-233
lines changed

Assets/FbxExporters/Editor/FbxExporter.cs

Lines changed: 0 additions & 233 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,239 +1703,6 @@ public static bool TryGetValue(string uniPropertyName, out FbxPropertyChannelPai
17031703
}
17041704
}
17051705

1706-
/// <summary>
1707-
/// Exporting rotations is more complicated. We need to convert
1708-
/// from quaternion to euler. We use this class to help.
1709-
/// </summary>
1710-
class FbxAnimCurveModifyHelper : System.IDisposable
1711-
{
1712-
public List<FbxAnimCurve> Curves { get ; private set; }
1713-
1714-
public FbxAnimCurveModifyHelper(List<FbxAnimCurve> list)
1715-
{
1716-
Curves = list;
1717-
1718-
foreach (var curve in Curves)
1719-
curve.KeyModifyBegin();
1720-
}
1721-
1722-
~FbxAnimCurveModifyHelper() {
1723-
Dispose();
1724-
}
1725-
1726-
public void Dispose()
1727-
{
1728-
foreach (var curve in Curves)
1729-
curve.KeyModifyEnd();
1730-
}
1731-
}
1732-
1733-
/// <summary>
1734-
/// Base class for QuaternionCurve and EulerCurve.
1735-
/// Provides implementation for computing keys and generating FbxAnimCurves
1736-
/// for euler rotation.
1737-
/// </summary>
1738-
abstract class RotationCurve {
1739-
public double sampleRate;
1740-
public AnimationCurve[] m_curves;
1741-
1742-
public struct Key {
1743-
public FbxTime time;
1744-
public FbxVector4 euler;
1745-
}
1746-
1747-
public RotationCurve() { }
1748-
1749-
public void SetCurve(int i, AnimationCurve curve) {
1750-
if (i < 0 || i >= m_curves.Length) {
1751-
throw new System.IndexOutOfRangeException();
1752-
}
1753-
m_curves [i] = curve;
1754-
}
1755-
1756-
protected abstract FbxQuaternion GetConvertedQuaternionRotation (float seconds, UnityEngine.Quaternion restRotation);
1757-
1758-
private Key [] ComputeKeys(UnityEngine.Quaternion restRotation, FbxNode node) {
1759-
// Get the source pivot pre-rotation if any, so we can
1760-
// remove it from the animation we get from Unity.
1761-
var fbxPreRotationEuler = node.GetRotationActive()
1762-
? node.GetPreRotation(FbxNode.EPivotSet.eSourcePivot)
1763-
: new FbxVector4();
1764-
1765-
// Get the inverse of the prerotation
1766-
var fbxPreRotationInverse = ModelExporter.EulerToQuaternion (fbxPreRotationEuler);
1767-
fbxPreRotationInverse.Inverse();
1768-
1769-
// Find when we have keys set.
1770-
var keyTimes =
1771-
(FbxExporters.Editor.ModelExporter.ExportSettings.BakeAnimation)
1772-
? ModelExporter.GetSampleTimes(m_curves, sampleRate)
1773-
: ModelExporter.GetKeyTimes(m_curves);
1774-
1775-
// Convert to the Key type.
1776-
var keys = new Key[keyTimes.Count];
1777-
int i = 0;
1778-
foreach(var seconds in keyTimes) {
1779-
var fbxFinalAnimation = GetConvertedQuaternionRotation (seconds, restRotation);
1780-
1781-
// Cancel out the pre-rotation. Order matters. FBX reads left-to-right.
1782-
// When we run animation we will apply:
1783-
// pre-rotation
1784-
// then pre-rotation inverse
1785-
// then animation.
1786-
var fbxFinalQuat = fbxPreRotationInverse * fbxFinalAnimation;
1787-
1788-
// Store the key so we can sort them later.
1789-
Key key;
1790-
key.time = FbxTime.FromSecondDouble(seconds);
1791-
key.euler = ModelExporter.QuaternionToEuler (fbxFinalQuat);
1792-
keys[i++] = key;
1793-
}
1794-
1795-
// Sort the keys by time
1796-
System.Array.Sort(keys, (Key a, Key b) => a.time.CompareTo(b.time));
1797-
1798-
return keys;
1799-
}
1800-
1801-
public void Animate(Transform unityTransform, FbxNode fbxNode, FbxAnimLayer fbxAnimLayer, bool Verbose) {
1802-
1803-
/* Find or create the three curves. */
1804-
var fbxAnimCurveX = fbxNode.LclRotation.GetCurve(fbxAnimLayer, Globals.FBXSDK_CURVENODE_COMPONENT_X, true);
1805-
var fbxAnimCurveY = fbxNode.LclRotation.GetCurve(fbxAnimLayer, Globals.FBXSDK_CURVENODE_COMPONENT_Y, true);
1806-
var fbxAnimCurveZ = fbxNode.LclRotation.GetCurve(fbxAnimLayer, Globals.FBXSDK_CURVENODE_COMPONENT_Z, true);
1807-
1808-
/* set the keys */
1809-
using (new FbxAnimCurveModifyHelper(new List<FbxAnimCurve>{fbxAnimCurveX,fbxAnimCurveY,fbxAnimCurveZ}))
1810-
{
1811-
foreach (var key in ComputeKeys(unityTransform.localRotation, fbxNode)) {
1812-
1813-
int i = fbxAnimCurveX.KeyAdd(key.time);
1814-
fbxAnimCurveX.KeySet(i, key.time, (float)key.euler.X);
1815-
1816-
i = fbxAnimCurveY.KeyAdd(key.time);
1817-
fbxAnimCurveY.KeySet(i, key.time, (float)key.euler.Y);
1818-
1819-
i = fbxAnimCurveZ.KeyAdd(key.time);
1820-
fbxAnimCurveZ.KeySet(i, key.time, (float)key.euler.Z);
1821-
}
1822-
}
1823-
1824-
// Uni-35616 unroll curves to preserve continuous rotations
1825-
var fbxCurveNode = fbxNode.LclRotation.GetCurveNode(fbxAnimLayer, false /*should already exist*/);
1826-
1827-
FbxAnimCurveFilterUnroll fbxAnimUnrollFilter = new FbxAnimCurveFilterUnroll();
1828-
fbxAnimUnrollFilter.Apply(fbxCurveNode);
1829-
1830-
if (Verbose) {
1831-
Debug.Log("Exported rotation animation for " + fbxNode.GetName());
1832-
}
1833-
}
1834-
}
1835-
1836-
/// <summary>
1837-
/// Convert from ZXY to XYZ euler, and remove
1838-
/// prerotation from animated rotation.
1839-
/// </summary>
1840-
class EulerCurve : RotationCurve {
1841-
public EulerCurve() { m_curves = new AnimationCurve[3]; }
1842-
1843-
/// <summary>
1844-
/// Gets the index of the euler curve by property name.
1845-
/// x = 0, y = 1, z = 2
1846-
/// </summary>
1847-
/// <returns>The index of the curve, or -1 if property doesn't map to Euler curve.</returns>
1848-
/// <param name="uniPropertyName">Unity property name.</param>
1849-
public static int GetEulerIndex(string uniPropertyName) {
1850-
System.StringComparison ct = System.StringComparison.CurrentCulture;
1851-
bool isEulerComponent = uniPropertyName.StartsWith ("localEulerAnglesRaw.", ct);
1852-
1853-
if (!isEulerComponent) { return -1; }
1854-
1855-
switch(uniPropertyName[uniPropertyName.Length - 1]) {
1856-
case 'x': return 0;
1857-
case 'y': return 1;
1858-
case 'z': return 2;
1859-
default: return -1;
1860-
}
1861-
}
1862-
1863-
protected override FbxQuaternion GetConvertedQuaternionRotation (float seconds, Quaternion restRotation)
1864-
{
1865-
var eulerRest = restRotation.eulerAngles;
1866-
AnimationCurve x = m_curves [0], y = m_curves [1], z = m_curves [2];
1867-
1868-
// The final animation, including the effect of pre-rotation.
1869-
// If we have no curve, assume the node has the correct rotation right now.
1870-
// We need to evaluate since we might only have keys in one of the axes.
1871-
var unityFinalAnimation = Quaternion.Euler (
1872-
(x == null) ? eulerRest [0] : x.Evaluate (seconds),
1873-
(y == null) ? eulerRest [1] : y.Evaluate (seconds),
1874-
(z == null) ? eulerRest [2] : z.Evaluate (seconds)
1875-
);
1876-
1877-
// convert the final animation to righthanded coords
1878-
var finalEuler = ModelExporter.ConvertQuaternionToXYZEuler(unityFinalAnimation);
1879-
1880-
return ModelExporter.EulerToQuaternion (new FbxVector4(finalEuler));
1881-
}
1882-
}
1883-
1884-
/// <summary>
1885-
/// Exporting rotations is more complicated. We need to convert
1886-
/// from quaternion to euler. We use this class to help.
1887-
/// </summary>
1888-
class QuaternionCurve : RotationCurve {
1889-
1890-
public QuaternionCurve() { m_curves = new AnimationCurve[4]; }
1891-
1892-
/// <summary>
1893-
/// Gets the index of the curve by property name.
1894-
/// x = 0, y = 1, z = 2, w = 3
1895-
/// </summary>
1896-
/// <returns>The index of the curve, or -1 if property doesn't map to Quaternion curve.</returns>
1897-
/// <param name="uniPropertyName">Unity property name.</param>
1898-
public static int GetQuaternionIndex(string uniPropertyName) {
1899-
System.StringComparison ct = System.StringComparison.CurrentCulture;
1900-
bool isQuaternionComponent = false;
1901-
1902-
isQuaternionComponent |= uniPropertyName.StartsWith ("m_LocalRotation.", ct);
1903-
isQuaternionComponent |= uniPropertyName.EndsWith ("Q.x", ct);
1904-
isQuaternionComponent |= uniPropertyName.EndsWith ("Q.y", ct);
1905-
isQuaternionComponent |= uniPropertyName.EndsWith ("Q.z", ct);
1906-
isQuaternionComponent |= uniPropertyName.EndsWith ("Q.w", ct);
1907-
1908-
if (!isQuaternionComponent) { return -1; }
1909-
1910-
switch(uniPropertyName[uniPropertyName.Length - 1]) {
1911-
case 'x': return 0;
1912-
case 'y': return 1;
1913-
case 'z': return 2;
1914-
case 'w': return 3;
1915-
default: return -1;
1916-
}
1917-
}
1918-
1919-
protected override FbxQuaternion GetConvertedQuaternionRotation (float seconds, Quaternion restRotation)
1920-
{
1921-
AnimationCurve x = m_curves [0], y = m_curves [1], z = m_curves [2], w = m_curves[3];
1922-
1923-
// The final animation, including the effect of pre-rotation.
1924-
// If we have no curve, assume the node has the correct rotation right now.
1925-
// We need to evaluate since we might only have keys in one of the axes.
1926-
var fbxFinalAnimation = new FbxQuaternion(
1927-
(x == null) ? restRotation[0] : x.Evaluate(seconds),
1928-
(y == null) ? restRotation[1] : y.Evaluate(seconds),
1929-
(z == null) ? restRotation[2] : z.Evaluate(seconds),
1930-
(w == null) ? restRotation[3] : w.Evaluate(seconds));
1931-
1932-
// convert the final animation to righthanded coords
1933-
var finalEuler = ModelExporter.ConvertQuaternionToXYZEuler(fbxFinalAnimation);
1934-
1935-
return ModelExporter.EulerToQuaternion (finalEuler);
1936-
}
1937-
}
1938-
19391706
/// <summary>
19401707
/// Export an AnimationClip as a single take
19411708
/// </summary>

0 commit comments

Comments
 (0)