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);
        }
        // compare the hierarchy and transform of two nodes
        private void CheckSceneHelper(FbxNode node1, FbxNode node2)
        {
            if (node1 == null && node2 == null)
            {
                return;
            }

            Assert.IsNotNull(node1);
            Assert.IsNotNull(node2);

            Assert.AreEqual(node1.GetChildCount(), node2.GetChildCount());

            // compare the transforms
            Assert.AreEqual(node1.LclTranslation.Get(), node2.LclTranslation.Get());
            Assert.AreEqual(node1.LclRotation.Get(), node2.LclRotation.Get());
            Assert.AreEqual(node1.LclScaling.Get(), node2.LclScaling.Get());

            Assert.AreEqual(node1.GetPreRotation(FbxNode.EPivotSet.eSourcePivot),
                            node2.GetPreRotation(FbxNode.EPivotSet.eSourcePivot));

            Assert.AreEqual(node1.GetPostRotation(FbxNode.EPivotSet.eSourcePivot),
                            node2.GetPostRotation(FbxNode.EPivotSet.eSourcePivot));

            Assert.AreEqual(node1.GetRotationPivot(FbxNode.EPivotSet.eSourcePivot),
                            node2.GetRotationPivot(FbxNode.EPivotSet.eSourcePivot));

            Assert.AreEqual(node1.GetScalingPivot(FbxNode.EPivotSet.eSourcePivot),
                            node2.GetScalingPivot(FbxNode.EPivotSet.eSourcePivot));

            Assert.AreEqual(node1.GetRotationOffset(FbxNode.EPivotSet.eSourcePivot),
                            node2.GetRotationOffset(FbxNode.EPivotSet.eSourcePivot));

            Assert.AreEqual(node1.GetScalingOffset(FbxNode.EPivotSet.eSourcePivot),
                            node2.GetScalingOffset(FbxNode.EPivotSet.eSourcePivot));

            Assert.AreEqual(node1.GetName(), node2.GetName());

            for (int i = 0; i < node1.GetChildCount(); i++)
            {
                // recurse through the hierarchy
                CheckSceneHelper(node1.GetChild(i), node2.GetChild(i));
            }
        }
예제 #3
0
            /// <summary>
            /// Process transformation data and setup Transform component
            /// </summary>
            private void ProcessTransform(FbxNode fbxNode, GameObject unityGo)
            {
                // Construct rotation matrices
                FbxVector4 fbxRotation  = new FbxVector4(fbxNode.LclRotation.Get());
                FbxAMatrix fbxRotationM = new FbxAMatrix();

                fbxRotationM.SetR(fbxRotation);

                FbxVector4 fbxPreRotation  = new FbxVector4(fbxNode.GetPreRotation(FbxNode.EPivotSet.eSourcePivot));
                FbxAMatrix fbxPreRotationM = new FbxAMatrix();

                fbxPreRotationM.SetR(fbxPreRotation);

                FbxVector4 fbxPostRotation  = new FbxVector4(fbxNode.GetPostRotation(FbxNode.EPivotSet.eSourcePivot));
                FbxAMatrix fbxPostRotationM = new FbxAMatrix();

                fbxPostRotationM.SetR(fbxPostRotation);

                // Construct translation matrix
                FbxAMatrix fbxTranslationM = new FbxAMatrix();
                FbxVector4 fbxTranslation  = new FbxVector4(fbxNode.LclTranslation.Get());

                fbxTranslationM.SetT(fbxTranslation);

                // Construct scaling matrix
                FbxAMatrix fbxScalingM = new FbxAMatrix();
                FbxVector4 fbxScaling  = new FbxVector4(fbxNode.LclScaling.Get());

                fbxScalingM.SetS(fbxScaling);

                // Construct offset and pivot matrices
                FbxAMatrix fbxRotationOffsetM = new FbxAMatrix();
                FbxVector4 fbxRotationOffset  = fbxNode.GetRotationOffset(FbxNode.EPivotSet.eSourcePivot);

                fbxRotationOffsetM.SetT(fbxRotationOffset);

                FbxAMatrix fbxRotationPivotM = new FbxAMatrix();
                FbxVector4 fbxRotationPivot  = fbxNode.GetRotationPivot(FbxNode.EPivotSet.eSourcePivot);

                fbxRotationPivotM.SetT(fbxRotationPivot);

                FbxAMatrix fbxScalingOffsetM = new FbxAMatrix();
                FbxVector4 fbxScalingOffset  = fbxNode.GetScalingOffset(FbxNode.EPivotSet.eSourcePivot);

                fbxScalingOffsetM.SetT(fbxScalingOffset);

                FbxAMatrix fbxScalingPivotM = new FbxAMatrix();
                FbxVector4 fbxScalingPivot  = fbxNode.GetScalingPivot(FbxNode.EPivotSet.eSourcePivot);

                fbxScalingPivotM.SetT(fbxScalingPivot);

                FbxAMatrix fbxTransform =
                    fbxTranslationM *
                    fbxRotationOffsetM *
                    fbxRotationPivotM *
                    fbxPreRotationM *
                    fbxRotationM *
                    fbxPostRotationM *
                    fbxRotationPivotM.Inverse() *
                    fbxScalingOffsetM *
                    fbxScalingPivotM *
                    fbxScalingM *
                    fbxScalingPivotM.Inverse();

                FbxVector4    lclTrs = fbxTransform.GetT();
                FbxQuaternion lclRot = fbxTransform.GetQ();
                FbxVector4    lclScl = fbxTransform.GetS();

                Debug.Log(string.Format("processing {3} Lcl : T({0}) R({1}) S({2})",
                                        lclTrs.ToString(),
                                        lclRot.ToString(),
                                        lclScl.ToString(),
                                        fbxNode.GetName()));

                unityGo.transform.localPosition = new Vector3((float)lclTrs[0], (float)lclTrs[1], (float)lclTrs[2]);
                unityGo.transform.localRotation = new Quaternion((float)lclRot[0], (float)lclRot[1], (float)lclRot[2], (float)lclRot[3]);
                unityGo.transform.localScale    = new Vector3((float)lclScl[0], (float)lclScl[1], (float)lclScl[2]);
            }
예제 #4
0
                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);
                }