/// <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; } } }
/// <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; }