| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- #region File Description
- //-----------------------------------------------------------------------------
- // KeyFrameSequence.cs
- //
- // Microsoft XNA Community Game Platform
- // Copyright (C) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- #endregion
- #region Using Statements
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Microsoft.Xna.Framework;
- using RobotGameData.Helper;
- #endregion
- namespace RobotGameData.GameObject
- {
- #region enum
- public enum AnimPlayMode
- {
- /// <summary>
- /// plays once.
- /// </summary>
- Once = 0,
- /// <summary>
- /// keeps repeating.
- /// </summary>
- Repeat,
- }
- #endregion
- #region key frame data
- /// <summary>
- /// key data of animation for one frame
- /// </summary>
- public struct KeyFrame
- {
- public bool HasTranslation;
- public bool HasRotation;
- public bool HasScale;
- public Vector3 Translation;
- public Quaternion Rotation;
- public Vector3 Scale;
- }
- #endregion
- /// <summary>
- /// this is the basic unit of animation which has single bone key frame.
- /// It calculates by interpolating two key frames.
- /// </summary>
- [Serializable]
- public class KeyFrameSequence
- {
- #region Fields
- public String BoneName = String.Empty;
- /// <summary>
- /// Key frame count
- /// </summary>
- public int KeyCount = 0;
- /// <summary>
- /// Animation playing time
- /// </summary>
- public float Duration = 0.0f;
- /// <summary>
- /// Gap of time for the each frame.
- /// </summary>
- public float KeyInterval = 0.0f;
- public bool HasTranslation = false;
- public bool HasRotation = false;
- public bool HasScale = false;
- public bool HasTime = false;
- /// <summary>
- /// If this flag is set to true, the first key frame’s translation value will be
- /// fixed during all key frame of the animation.
- /// </summary>
- public bool FixedTranslation = false;
- /// <summary>
- /// If this flag is set to true, the first key frame’s rotaion value will be
- /// fixed during all key frame of the animation.
- /// </summary>
- public bool FixedRotation = false;
- /// <summary>
- /// If this flag is set to true, the first key frame’s scale value will be
- /// fixed during all key frame of the animation.
- /// </summary>
- public bool FixedScale = false;
- /// <summary>
- /// The translation value in the list.
- /// </summary>
- public List<Vector3> Translation = null;
- /// <summary>
- /// The rotation value in the list.
- /// </summary>
- public List<Quaternion> Rotation = null;
- /// <summary>
- /// The scale value in the list.
- /// </summary>
- public List<Vector3> Scale = null;
- /// <summary>
- /// The time value in the list.
- /// </summary>
- public List<float> Time = null;
- #endregion
- /// <summary>
- /// Gets a key frame matrix by index
- /// </summary>
- /// <param name="keyIndex">key frame index</param>
- /// <returns></returns>
- public Matrix GetMatrix(int keyIndex)
- {
- Matrix mat = Matrix.Identity;
- if (HasRotation ) // Calculates rotation matrix using quaternion
- {
- if (FixedRotation )
- mat = Matrix.CreateFromQuaternion(Rotation[0]);
- else
- mat = Matrix.CreateFromQuaternion(Rotation[keyIndex]);
- }
- if (HasTranslation ) // Calculates position
- {
- if (FixedRotation )
- mat.Translation = Translation[0];
- else
- mat.Translation = Translation[keyIndex];
- }
- if (HasScale ) // Calculates scale
- {
- if (FixedRotation )
- mat = mat * Matrix.CreateScale(Scale[0]);
- else
- mat = mat * Matrix.CreateScale(Scale[keyIndex]);
- }
- return mat;
- }
- /// <summary>
- /// calculates by interpolating two key frames.
- /// </summary>
- /// <param name="keyIndex1">key frame index 1</param>
- /// <param name="keyIndex2">key frame index 2</param>
- /// <param name="t">interpolate time (0.0 to 1.0)</param>
- /// <returns>Interpolated key frame matrix</returns>
- public Matrix GetInterpolateMatrix(int keyIndex1, int keyIndex2, float t)
- {
- // Calculate KeyFrame interpolated matrix
- Matrix mat = Matrix.Identity;
- // Interpolate rotation value by Slerp
- if (HasRotation )
- {
- Quaternion q = Quaternion.Identity;
- if (FixedRotation )
- q = Rotation[0];
- else
- q = Quaternion.Slerp(Rotation[keyIndex1], Rotation[keyIndex2], t);
- // Apply interpolate rotation to matrix
- mat = Matrix.CreateFromQuaternion(q);
- }
- // Interpolate translation value by Lerp
- if (HasTranslation )
- {
- // Apply interpolate translation to matrix
- if (FixedTranslation )
- mat.Translation = Translation[0];
- else
- mat.Translation =
- Vector3.Lerp(Translation[keyIndex1], Translation[keyIndex2], t);
- }
- // Interpolate scale value by Lerp
- if (HasScale )
- {
- Vector3 v = Vector3.Zero;
- if (FixedScale )
- v = Scale[0];
- else
- v = Vector3.Lerp(Scale[keyIndex1], Scale[keyIndex2], t);
- // Apply interpolate scale to matrix
- mat = mat * Matrix.CreateScale(v);
- }
- return mat;
- }
- /// <summary>
- /// calculates by interpolating two key frames.
- /// </summary>
- /// <param name="keyIndex1">key frame index 1</param>
- /// <param name="keyIndex2">key frame index 2</param>
- /// <param name="t">interpolate time (0.0 to 1.0)</param>
- /// <returns>Interpolated key frame</returns>
- public KeyFrame GetInterpolateKeyFrame(int keyIndex1, int keyIndex2, float t)
- {
- // Calculate KeyFrame interpolated matrix
- KeyFrame keyFrame;
- // Interpolate rotation value by Slerp
- if (HasRotation )
- {
- if (FixedRotation )
- keyFrame.Rotation = Rotation[0];
- else
- keyFrame.Rotation = Quaternion.Slerp(
- Rotation[keyIndex1],
- Rotation[keyIndex2],
- t);
- }
- else
- {
- keyFrame.Rotation = Quaternion.Identity;
- }
- keyFrame.HasRotation = HasRotation;
- // Interpolate translation value by Lerp
- if (HasTranslation )
- {
- if (FixedTranslation )
- keyFrame.Translation = Translation[0];
- else
- keyFrame.Translation = Vector3.Lerp(
- Translation[keyIndex1],
- Translation[keyIndex2],
- t);
- }
- else
- {
- keyFrame.Translation = Vector3.Zero;
- }
- keyFrame.HasTranslation = HasTranslation;
- // Interpolate scale value by Lerp
- if (HasScale )
- {
- if (FixedScale )
- keyFrame.Scale = Scale[0];
- else
- keyFrame.Scale = Vector3.Lerp(Scale[keyIndex1], Scale[keyIndex2], t);
- }
- else
- {
- keyFrame.Scale = Vector3.One;
- }
- keyFrame.HasScale = HasScale;
- return keyFrame;
- }
- public Matrix GetInterpolateMatrix(float localTime, AnimPlayMode mode)
- {
- int index1 = 0; // first key frame index
- int index2 = 0; // second key frame index
- float interpolateTime = 0.0f;
- CalculateKeyFrameIndex(localTime, mode, out index1, out index2,
- out interpolateTime);
- // Calcurate interpolate key frame matrix between KeyFrame1 and KeyFrame2
- return GetInterpolateMatrix(index1, index2, interpolateTime);
- }
- public KeyFrame GetInterpolateKeyFrame(float localTime, AnimPlayMode mode)
- {
- int index1 = 0; // first key frame index
- int index2 = 0; // second key frame index
- float interpolateTime = 0.0f;
- CalculateKeyFrameIndex(localTime, mode, out index1, out index2,
- out interpolateTime);
- // Calcurate interpolate key frame matrix between KeyFrame1 and KeyFrame2
- return GetInterpolateKeyFrame(index1, index2, interpolateTime);
- }
- /// <summary>
- /// returns two key frame index, which is included in the specified time.
- /// </summary>
- public void CalculateKeyFrameIndex(float localTime, AnimPlayMode mode,
- out int index1, out int index2,
- out float interpolateTime)
- {
- index1 = 0; // first key frame index
- index2 = 0; // second key frame index
- interpolateTime = 0.0f;
- // Calculate first key frame index
- if (HasTime )
- index1 = GetKeyFrameIndex(localTime);
- else
- index1 = (int)(localTime / KeyInterval);
- // Calculate second key frame index by play mode
- switch (mode)
- {
- case AnimPlayMode.Once: // Just play once
- {
- // if index1 is last index
- index2 = (index1 >= KeyCount - 1 ? index1 : index1 + 1);
- }
- break;
- case AnimPlayMode.Repeat: // Play looping
- {
- // if index1 is last index, index2 must be begin (looping)
- index2 = (index1 >= KeyCount - 1 ? 0 : index1 + 1);
- }
- break;
- default:
- throw new NotSupportedException("Not supported play mode");
- }
- if (index1 >= KeyCount - 1)
- {
- index1 = index2 = KeyCount - 1;
- interpolateTime = 1.0f;
- }
- else
- {
- if (HasTime )
- {
- interpolateTime = (localTime - Time[index1]) /
- (Time[index2] - Time[index1]);
- }
- else
- {
- interpolateTime = HelperMath.CalculateModulo(localTime, KeyInterval)
- / KeyInterval;
- }
- }
- }
- /// <summary>
- /// returns two key frame index, which is included in the specified time.
- /// </summary>
- public int GetKeyFrameIndex(float localTime)
- {
- // Calculate index between two key frame on this time
- int startIndex, endIndex, middleIndex;
- startIndex = 0;
- endIndex = KeyCount - 1;
- if (localTime >= Time[endIndex])
- {
- return endIndex;
- }
- do
- {
- middleIndex = (startIndex + endIndex) / 2;
- if ((endIndex - startIndex) <= 1)
- {
- break;
- }
- else if (Time[middleIndex] < localTime)
- {
- startIndex = middleIndex;
- }
- else if (Time[middleIndex] > localTime)
- {
- endIndex = middleIndex;
- }
- else
- {
- startIndex = middleIndex;
- break;
- }
- } while ((endIndex - startIndex) > 1);
- return startIndex;
- }
- }
- }
|