private Key [] ComputeKeys(UnityEngine.Quaternion restRotation, FbxNode node) { // Get the source pivot pre-rotation if any, so we can // remove it from the animation we get from Unity. var fbxPreRotationEuler = node.GetRotationActive() ? node.GetPreRotation(FbxNode.EPivotSet.eSourcePivot) : new FbxVector4(); // Get the inverse of the prerotation var fbxPreRotationInverse = ModelExporter.EulerToQuaternion(fbxPreRotationEuler); fbxPreRotationInverse.Inverse(); // Find when we have keys set. var keyTimes = (UnityEditor.Formats.Fbx.Exporter.ModelExporter.ExportSettings.BakeAnimationProperty) ? ModelExporter.GetSampleTimes(GetCurves(), SampleRate) : ModelExporter.GetKeyTimes(GetCurves()); // Convert to the Key type. var keys = new Key[keyTimes.Count]; int i = 0; foreach (var seconds in keyTimes) { var fbxFinalAnimation = GetConvertedQuaternionRotation(seconds, restRotation); // Cancel out the pre-rotation. Order matters. FBX reads left-to-right. // When we run animation we will apply: // pre-rotation // then pre-rotation inverse // then animation. var fbxFinalQuat = fbxPreRotationInverse * fbxFinalAnimation; // Store the key so we can sort them later. Key key = new Key(); key.time = FbxTime.FromSecondDouble(seconds); key.euler = ModelExporter.QuaternionToEuler(fbxFinalQuat); keys[i++] = key; } // Sort the keys by time System.Array.Sort(keys, (Key a, Key b) => a.time.CompareTo(b.time)); return(keys); }
Key [] ComputeKeys(UnityEngine.Quaternion restRotation, FbxNode node) { // Get the source pivot pre-rotation if any, so we can // remove it from the animation we get from Unity. var fbxPreRotationEuler = node.GetRotationActive() ? node.GetPreRotation(FbxNode.EPivotSet.eSourcePivot) : new FbxVector4(); var fbxPreRotationInverse = new FbxQuaternion(); fbxPreRotationInverse.ComposeSphericalXYZ(fbxPreRotationEuler); fbxPreRotationInverse.Inverse(); // If we're only animating along certain coords for some // reason, we'll need to fill in the other coords with the // rest-pose value. var lclQuaternion = new FbxQuaternion(restRotation.x, restRotation.y, restRotation.z, restRotation.w); // Find when we have keys set. var keyTimes = new HashSet <float>(); if (x != null) { foreach (var key in x.keys) { keyTimes.Add(key.time); } } if (y != null) { foreach (var key in y.keys) { keyTimes.Add(key.time); } } if (z != null) { foreach (var key in z.keys) { keyTimes.Add(key.time); } } if (w != null) { foreach (var key in w.keys) { keyTimes.Add(key.time); } } // Convert to the Key type. var keys = new Key[keyTimes.Count]; int i = 0; foreach (var seconds in keyTimes) { // The final animation, including the effect of pre-rotation. // If we have no curve, assume the node has the correct rotation right now. // We need to evaluate since we might only have keys in one of the axes. var fbxFinalAnimation = new FbxQuaternion( (x == null) ? lclQuaternion[0] : x.Evaluate(seconds), (y == null) ? lclQuaternion[1] : y.Evaluate(seconds), (z == null) ? lclQuaternion[2] : z.Evaluate(seconds), (w == null) ? lclQuaternion[3] : w.Evaluate(seconds)); // Cancel out the pre-rotation. Order matters. FBX reads left-to-right. // When we run animation we will apply: // pre-rotation // then pre-rotation inverse // then animation. var fbxAnimation = fbxPreRotationInverse * fbxFinalAnimation; // Store the key so we can sort them later. Key key; key.time = FbxTime.FromSecondDouble(seconds); key.euler = fbxAnimation.DecomposeSphericalXYZ(); keys[i++] = key; } // Sort the keys by time System.Array.Sort(keys, (Key a, Key b) => a.time.CompareTo(b.time)); return(keys); }