Пример #1
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);
                }
Пример #2
0
        public void BasicTests()
        {
            FbxQuaternion u, v;

            // make sure the no-arg constructor doesn't crash
            new FbxQuaternion();

            // test dispose
            using (new FbxQuaternion()) { }
            DisposeTester.TestDispose(new FbxQuaternion());

            // Test other constructors
            v = new FbxQuaternion(0.1, 0.2, 0.3, 0.4);
            u = new FbxQuaternion(v);
            Assert.AreEqual(v, u);
            u[0] = 0.5;
            Assert.AreEqual(0.5, u[0]);
            Assert.AreEqual(0.1, v[0]); // check that setting u doesn't set v

            // axis-angle constructor and setter
            v = new FbxQuaternion(new FbxVector4(1, 2, 3), 90);
            u = new FbxQuaternion();
            u.SetAxisAngle(new FbxVector4(1, 2, 3), 90);
            Assert.AreEqual(u, v);

            // euler
            v = new FbxQuaternion();
            v.ComposeSphericalXYZ(new FbxVector4(20, 30, 40));
            var euler = v.DecomposeSphericalXYZ();

            Assert.That(euler.X, Is.InRange(19.99, 20.01));
            Assert.That(euler.Y, Is.InRange(29.99, 30.01));
            Assert.That(euler.Z, Is.InRange(39.99, 40.01));
            Assert.AreEqual(0, euler.W);

            v = new FbxQuaternion(0.1, 0.2, 0.3);
            Assert.AreEqual(0.1, v[0]);
            Assert.AreEqual(0.2, v[1]);
            Assert.AreEqual(0.3, v[2]);
            Assert.AreEqual(1, v[3]); // w is assumed to be a homogenous coordinate

            v.Set(0.9, 0.8, 0.7, 0.6);
            Assert.AreEqual(0.9, v[0]);
            Assert.AreEqual(0.8, v[1]);
            Assert.AreEqual(0.7, v[2]);
            Assert.AreEqual(0.6, v[3]);
            v.Set(0.9, 0.8, 0.7);
            Assert.AreEqual(0.9, v[0]);
            Assert.AreEqual(0.8, v[1]);
            Assert.AreEqual(0.7, v[2]);

            v.SetAt(1, 2);
            Assert.AreEqual(2, v.GetAt(1));

            // Test operator[]
            v    = new FbxQuaternion();
            v[0] = 0.1;
            Assert.AreEqual(0.1, v[0]);
            v[1] = 0.2;
            Assert.AreEqual(0.2, v[1]);
            v[2] = 0.3;
            Assert.AreEqual(0.3, v[2]);
            v[3] = 0.4;
            Assert.AreEqual(0.4, v[3]);
            v.SetAt(3, 0.5);
            Assert.AreEqual(0.5, v.GetAt(3));
            Assert.That(() => v[-1], Throws.Exception.TypeOf <System.ArgumentOutOfRangeException>());
            Assert.That(() => v[4], Throws.Exception.TypeOf <System.ArgumentOutOfRangeException>());
            Assert.That(() => v.GetAt(-1), Throws.Exception.TypeOf <System.ArgumentOutOfRangeException>());
            Assert.That(() => v.GetAt(4), Throws.Exception.TypeOf <System.ArgumentOutOfRangeException>());
            Assert.That(() => v[-1] = 0.5, Throws.Exception.TypeOf <System.ArgumentOutOfRangeException>());
            Assert.That(() => v[4]  = 0.5, Throws.Exception.TypeOf <System.ArgumentOutOfRangeException>());
            Assert.That(() => v.SetAt(-1, 0.5), Throws.Exception.TypeOf <System.ArgumentOutOfRangeException>());
            Assert.That(() => v.SetAt(4, 0.5), Throws.Exception.TypeOf <System.ArgumentOutOfRangeException>());

            // Test W/X/Y/Z
            v.X = 0.1;
            Assert.AreEqual(0.1, v.X);
            v.Y = 0.2;
            Assert.AreEqual(0.2, v.Y);
            v.Z = 0.3;
            Assert.AreEqual(0.3, v.Z);
            v.W = 0.4;
            Assert.AreEqual(0.4, v.W);

            // call the multiply/divide/add/sub operators, make sure they're vaguely sane
            u = new FbxQuaternion(v);
            v = v * v;
            Assert.AreNotEqual(0, u.Compare(v, 1e-15)); // test compare can return false
            v = v * 9;
            v = 9 * v;
            v = v + 5;
            v = v - 5;                        // undo v + 5
            v = v + u;
            v = v - u;                        // undo v + u
            v = v / 81;                       // undo 9 * (v * 9)
            v = v / u;                        // undo v*v
            Assert.AreEqual(0, u.Compare(v)); // u and v are the same up to rounding
            Assert.AreEqual(u * u, u.Product(u));

            // unary negate and dot product
            Assert.AreEqual(0, (-u).Compare(-v));
            Assert.AreEqual(-0.3, v.DotProduct(-v), 1e-6);
            Assert.AreEqual(System.Math.Sqrt(0.3), v.Length(), 1e-6);
            v.Normalize();
            Assert.AreEqual(1, v.DotProduct(v), 1e-6);

            // various others where we assume that FBX works, just test that they don't crash
            v.Conjugate();
            v.Inverse();
            v.Slerp(u, 0.5);
        }