Inheritance: IDisposable
        /// <summary>
        /// Advances the frame of an animation for a skeleton used on this mesh.
        /// </summary>
        /// <param name="Animation">The animation to advance.</param>
        /// <param name="TimeDelta">The timedelta of the rendering loop.</param>
        public void AdvanceFrame(Anim Animation, float TimeDelta)
        {
            float Duration = (float)Animation.Motions[0].FrameCount / 30;
            m_AnimationTime += TimeDelta;
            m_AnimationTime = m_AnimationTime % Duration; //Loop the animation

            for (int i = 0; i < Animation.Motions.Count; i++)
            {
                int BoneIndex = Skel.FindBone(Animation.Motions[i].BoneName);

                if (BoneIndex == -1)
                    continue;

                int Frame = (int)(m_AnimationTime * 30);
                float FractionShown = m_AnimationTime * 30 - Frame;
                int NextFrame = (Frame + 1 != Animation.Motions[0].FrameCount) ? Frame + 1 : 0;

                if (Animation.Motions[i].HasTranslation)
                {
                    Vector3 Translation = new Vector3(
                        Animation.Translations[Frame + Animation.Motions[i].FirstTranslationIndex, 0],
                        Animation.Translations[Frame + Animation.Motions[i].FirstTranslationIndex, 1],
                        Animation.Translations[Frame + Animation.Motions[i].FirstTranslationIndex, 2]);
                    Vector3 NextTranslation = new Vector3(
                        Animation.Translations[NextFrame + Animation.Motions[i].FirstTranslationIndex, 0],
                        Animation.Translations[NextFrame + Animation.Motions[i].FirstTranslationIndex, 1],
                        Animation.Translations[NextFrame + Animation.Motions[i].FirstTranslationIndex, 2]);

                    Vector3 UpdatedTranslation = new Vector3();
                    UpdatedTranslation.X = (1 - FractionShown) * Translation.X + FractionShown * NextTranslation.X;
                    UpdatedTranslation.Y = (1 - FractionShown) * Translation.Y + FractionShown * NextTranslation.Y;
                    UpdatedTranslation.Z = (1 - FractionShown) * Translation.Z + FractionShown * NextTranslation.Z;

                    Skel.Bones[BoneIndex].Translation = UpdatedTranslation;
                }

                if (Animation.Motions[i].HasRotation)
                {
                    Quaternion Rotation = new Quaternion(
                        Animation.Rotations[Frame + Animation.Motions[i].FirstRotationIndex, 0],
                        Animation.Rotations[Frame + Animation.Motions[i].FirstRotationIndex, 1],
                        Animation.Rotations[Frame + Animation.Motions[i].FirstRotationIndex, 2],
                        Animation.Rotations[Frame + Animation.Motions[i].FirstRotationIndex, 3]);
                    Quaternion NextRotation = new Quaternion(
                        Animation.Rotations[NextFrame + Animation.Motions[i].FirstRotationIndex, 0],
                        Animation.Rotations[NextFrame + Animation.Motions[i].FirstRotationIndex, 1],
                        Animation.Rotations[NextFrame + Animation.Motions[i].FirstRotationIndex, 2],
                        Animation.Rotations[NextFrame + Animation.Motions[i].FirstRotationIndex, 3]);

                    //Use Slerp to interpolate
                    float W1, W2 = 1.0f;
                    float CosTheta = Helpers.DotProduct(Rotation, NextRotation);

                    if (CosTheta < 0)
                    {
                        CosTheta *= -1;
                        W2 *= -1;
                    }

                    float Theta = (float)Math.Acos(CosTheta);
                    float SinTheta = (float)Math.Sin(Theta);

                    if (SinTheta > 0.001f)
                    {
                        W1 = (float)Math.Sin((1.0f - FractionShown) * Theta) / SinTheta;
                        W2 *= (float)Math.Sin(FractionShown * Theta) / SinTheta;
                    }
                    else
                    {
                        W1 = 1.0f - FractionShown;
                        W2 = FractionShown;
                    }

                    Quaternion UpdatedRotation = new Quaternion();
                    UpdatedRotation.X = W1 * Rotation.X + W2 * NextRotation.X;
                    UpdatedRotation.Y = W1 * Rotation.Y + W2 * NextRotation.Y;
                    UpdatedRotation.Z = W1 * Rotation.Z + W2 * NextRotation.Z;
                    UpdatedRotation.W = W1 * Rotation.W + W2 * NextRotation.W;

                    Skel.Bones[BoneIndex].Rotation.X = UpdatedRotation.X;
                    Skel.Bones[BoneIndex].Rotation.Y = UpdatedRotation.Y;
                    Skel.Bones[BoneIndex].Rotation.Z = UpdatedRotation.Z;
                    Skel.Bones[BoneIndex].Rotation.W = UpdatedRotation.W;
                }
            }
        }
Beispiel #2
0
 /// <summary>
 /// Sets the animation for this Sim.
 /// </summary>
 /// <param name="Animation">The animation to play.</param>
 public void SetAnimation(Anim Animation)
 {
     m_Avatar.Animation = Animation;
 }