예제 #1
0
        static bool Test()
        {
#if DEBUG && !MATRIXFRAMES
            Keyframe kf = new Keyframe();
            Matrix   mx = Matrix.CreateScale(0.15f, 0.20f, 0.25f) *
                          Matrix.CreateRotationY((float)(Math.PI / 6)) *
                          Matrix.CreateRotationX(0.1f) *
                          Matrix.CreateRotationZ(-0.1f) *
                          Matrix.CreateTranslation(2, 0, 1);
            Keyframe.CreateFromMatrix(ref mx, kf);
            Matrix two;
            kf.ToMatrix(out two);
            Matrix three = Matrix.Invert(mx) * two;
            //  verify that forward and back is transparent
            for (int i = 0; i != 16; ++i)
            {
                float f = MatrixElement(ref three, i);
                if ((i % 5) == 0)
                {
                    System.Diagnostics.Debug.Assert(Math.Abs(f - 1) < 1e-4);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(Math.Abs(f) < 1e-4);
                }
            }
#endif
            return(true);
        }
예제 #2
0
        /// <summary>
        /// An ultra convenient function that will copy all the keyframes
        /// to a given Model bone array. Only the bones that are actually
        /// animated will be affected.
        /// </summary>
        /// <param name="model">The model to apply the animation to.</param>
        public void CopyPoseTo(Model model)
        {
            if (appliedTime_ != time_)
            {
                CalculateKeyframes();
            }
            int n = model.Bones.Count;

            if (n > keyframes_.Length)
            {
                n = keyframes_.Length;
            }
            Matrix mat;

            unchecked
            {
                for (int i = 0; i != n; ++i)
                {
                    Keyframe kf = keyframes_[i];
                    if (kf != null)
                    {
                        kf.ToMatrix(out mat);
                        model.Bones[i].Transform = mat;
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Decompose the given matrix into a scale/rotation/translation
        /// keyframe. The method used is not well behaved when the scale
        /// along one axis is very close to 0, so don't scale down by more
        /// than about 1/10,000.
        ///  This works for matrices that don't contain shear or off-axis scale.
        /// </summary>
        /// <param name="xform">The transform to decompose.</param>
        /// <param name="ret">The keyframe to decompose into.</param>
        /// <returns>ret (for convenience)</returns>
        public static Keyframe CreateFromMatrix(ref Matrix xform, Keyframe ret)
        {
#if DEBUG
            if (ret == null)
            {
                throw new ArgumentNullException("ret");
            }
#endif
#if !MATRIXFRAMES
            //  decompose the matrix into scale, rotation and translaction
            ret.Scale = new Vector3(
                (new Vector3(xform.M11, xform.M12, xform.M13)).Length(),
                (new Vector3(xform.M21, xform.M22, xform.M23)).Length(),
                (new Vector3(xform.M31, xform.M32, xform.M33)).Length());
            ret.Pos = xform.Translation;
            //  I can't extract rotation if one of the axes is zero scale.
            //  That's unfortunate, as someone might want to animation an object
            //  becoming pancaked and spinning. Just don't make it THAT much
            //  of a pancake then.
            Matrix mat = Matrix.Identity;
            if (Math.Abs(ret.Scale.X) > 1e-6 && Math.Abs(ret.Scale.Y) > 1e-6 &&
                Math.Abs(ret.Scale.Z) > 1e-6)
            {
                Vector3 right    = Vector3.Normalize(xform.Right);
                Vector3 up       = Vector3.Normalize(xform.Up - right * Vector3.Dot(xform.Up, right));
                Vector3 backward = Vector3.Cross(right, up);
                if (Vector3.Dot(xform.Backward, backward) < 0)
                {
                    //  matrix is mirrored
                    ret.Scale = ret.Scale * new Vector3(1, 1, -1);
                }
                mat.Right    = right;
                mat.Up       = up;
                mat.Backward = backward;
                ret.Ori      = Quaternion.CreateFromRotationMatrix(mat);
            }
            ret.ToMatrix(out mat);
            for (int i = 0; i != 16; ++i)
            {
                //  Make sure that the matrix that comes out of the keyframe is a good decomposition
                //  of the original matrix.
                if (Math.Abs(MatrixElement(ref mat, i) - MatrixElement(ref xform, i)) > 1e-2)
                {
#if DEBUG
                    System.Diagnostics.Debugger.Break();
#endif
                    throw new System.ArgumentException("Matrix could not be properly decomposed into TRS keyframe.");
                }
            }
#else
            ret.transform_ = xform;
#endif
            return(ret);
        }
예제 #4
0
        /// <summary>
        /// Extract the pose as a number of parent-relative matrices.
        /// Note that this is not typically what you want to use for
        /// rendering, as you then want object-relative matrices.
        /// </summary>
        /// <param name="output">Each bones parent relative matrix will be stored
        /// here, if the bone is animated. Else that matrix will be untouched.</param>
        public void CopyPoseTo(Matrix[] output)
        {
            if (appliedTime_ != time_)
            {
                CalculateKeyframes();
            }
            int n = output.Length;

            if (n > keyframes_.Length)
            {
                n = keyframes_.Length;
            }
            unchecked
            {
                for (int i = 0; i != n; ++i)
                {
                    Keyframe kf = keyframes_[i];
                    if (kf != null)
                    {
                        kf.ToMatrix(out output[i]);
                    }
                }
            }
        }