KeyFrameSequence.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // KeyFrameSequence.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Text;
  13. using Microsoft.Xna.Framework;
  14. using RobotGameData.Helper;
  15. #endregion
  16. namespace RobotGameData.GameObject
  17. {
  18. #region enum
  19. public enum AnimPlayMode
  20. {
  21. /// <summary>
  22. /// plays once.
  23. /// </summary>
  24. Once = 0,
  25. /// <summary>
  26. /// keeps repeating.
  27. /// </summary>
  28. Repeat,
  29. }
  30. #endregion
  31. #region key frame data
  32. /// <summary>
  33. /// key data of animation for one frame
  34. /// </summary>
  35. public struct KeyFrame
  36. {
  37. public bool HasTranslation;
  38. public bool HasRotation;
  39. public bool HasScale;
  40. public Vector3 Translation;
  41. public Quaternion Rotation;
  42. public Vector3 Scale;
  43. }
  44. #endregion
  45. /// <summary>
  46. /// this is the basic unit of animation which has single bone key frame.
  47. /// It calculates by interpolating two key frames.
  48. /// </summary>
  49. [Serializable]
  50. public class KeyFrameSequence
  51. {
  52. #region Fields
  53. public String BoneName = String.Empty;
  54. /// <summary>
  55. /// Key frame count
  56. /// </summary>
  57. public int KeyCount = 0;
  58. /// <summary>
  59. /// Animation playing time
  60. /// </summary>
  61. public float Duration = 0.0f;
  62. /// <summary>
  63. /// Gap of time for the each frame.
  64. /// </summary>
  65. public float KeyInterval = 0.0f;
  66. public bool HasTranslation = false;
  67. public bool HasRotation = false;
  68. public bool HasScale = false;
  69. public bool HasTime = false;
  70. /// <summary>
  71. /// If this flag is set to true, the first key frame’s translation value will be
  72. /// fixed during all key frame of the animation.
  73. /// </summary>
  74. public bool FixedTranslation = false;
  75. /// <summary>
  76. /// If this flag is set to true, the first key frame’s rotaion value will be
  77. /// fixed during all key frame of the animation.
  78. /// </summary>
  79. public bool FixedRotation = false;
  80. /// <summary>
  81. /// If this flag is set to true, the first key frame’s scale value will be
  82. /// fixed during all key frame of the animation.
  83. /// </summary>
  84. public bool FixedScale = false;
  85. /// <summary>
  86. /// The translation value in the list.
  87. /// </summary>
  88. public List<Vector3> Translation = null;
  89. /// <summary>
  90. /// The rotation value in the list.
  91. /// </summary>
  92. public List<Quaternion> Rotation = null;
  93. /// <summary>
  94. /// The scale value in the list.
  95. /// </summary>
  96. public List<Vector3> Scale = null;
  97. /// <summary>
  98. /// The time value in the list.
  99. /// </summary>
  100. public List<float> Time = null;
  101. #endregion
  102. /// <summary>
  103. /// Gets a key frame matrix by index
  104. /// </summary>
  105. /// <param name="keyIndex">key frame index</param>
  106. /// <returns></returns>
  107. public Matrix GetMatrix(int keyIndex)
  108. {
  109. Matrix mat = Matrix.Identity;
  110. if (HasRotation ) // Calculates rotation matrix using quaternion
  111. {
  112. if (FixedRotation )
  113. mat = Matrix.CreateFromQuaternion(Rotation[0]);
  114. else
  115. mat = Matrix.CreateFromQuaternion(Rotation[keyIndex]);
  116. }
  117. if (HasTranslation ) // Calculates position
  118. {
  119. if (FixedRotation )
  120. mat.Translation = Translation[0];
  121. else
  122. mat.Translation = Translation[keyIndex];
  123. }
  124. if (HasScale ) // Calculates scale
  125. {
  126. if (FixedRotation )
  127. mat = mat * Matrix.CreateScale(Scale[0]);
  128. else
  129. mat = mat * Matrix.CreateScale(Scale[keyIndex]);
  130. }
  131. return mat;
  132. }
  133. /// <summary>
  134. /// calculates by interpolating two key frames.
  135. /// </summary>
  136. /// <param name="keyIndex1">key frame index 1</param>
  137. /// <param name="keyIndex2">key frame index 2</param>
  138. /// <param name="t">interpolate time (0.0 to 1.0)</param>
  139. /// <returns>Interpolated key frame matrix</returns>
  140. public Matrix GetInterpolateMatrix(int keyIndex1, int keyIndex2, float t)
  141. {
  142. // Calculate KeyFrame interpolated matrix
  143. Matrix mat = Matrix.Identity;
  144. // Interpolate rotation value by Slerp
  145. if (HasRotation )
  146. {
  147. Quaternion q = Quaternion.Identity;
  148. if (FixedRotation )
  149. q = Rotation[0];
  150. else
  151. q = Quaternion.Slerp(Rotation[keyIndex1], Rotation[keyIndex2], t);
  152. // Apply interpolate rotation to matrix
  153. mat = Matrix.CreateFromQuaternion(q);
  154. }
  155. // Interpolate translation value by Lerp
  156. if (HasTranslation )
  157. {
  158. // Apply interpolate translation to matrix
  159. if (FixedTranslation )
  160. mat.Translation = Translation[0];
  161. else
  162. mat.Translation =
  163. Vector3.Lerp(Translation[keyIndex1], Translation[keyIndex2], t);
  164. }
  165. // Interpolate scale value by Lerp
  166. if (HasScale )
  167. {
  168. Vector3 v = Vector3.Zero;
  169. if (FixedScale )
  170. v = Scale[0];
  171. else
  172. v = Vector3.Lerp(Scale[keyIndex1], Scale[keyIndex2], t);
  173. // Apply interpolate scale to matrix
  174. mat = mat * Matrix.CreateScale(v);
  175. }
  176. return mat;
  177. }
  178. /// <summary>
  179. /// calculates by interpolating two key frames.
  180. /// </summary>
  181. /// <param name="keyIndex1">key frame index 1</param>
  182. /// <param name="keyIndex2">key frame index 2</param>
  183. /// <param name="t">interpolate time (0.0 to 1.0)</param>
  184. /// <returns>Interpolated key frame</returns>
  185. public KeyFrame GetInterpolateKeyFrame(int keyIndex1, int keyIndex2, float t)
  186. {
  187. // Calculate KeyFrame interpolated matrix
  188. KeyFrame keyFrame;
  189. // Interpolate rotation value by Slerp
  190. if (HasRotation )
  191. {
  192. if (FixedRotation )
  193. keyFrame.Rotation = Rotation[0];
  194. else
  195. keyFrame.Rotation = Quaternion.Slerp(
  196. Rotation[keyIndex1],
  197. Rotation[keyIndex2],
  198. t);
  199. }
  200. else
  201. {
  202. keyFrame.Rotation = Quaternion.Identity;
  203. }
  204. keyFrame.HasRotation = HasRotation;
  205. // Interpolate translation value by Lerp
  206. if (HasTranslation )
  207. {
  208. if (FixedTranslation )
  209. keyFrame.Translation = Translation[0];
  210. else
  211. keyFrame.Translation = Vector3.Lerp(
  212. Translation[keyIndex1],
  213. Translation[keyIndex2],
  214. t);
  215. }
  216. else
  217. {
  218. keyFrame.Translation = Vector3.Zero;
  219. }
  220. keyFrame.HasTranslation = HasTranslation;
  221. // Interpolate scale value by Lerp
  222. if (HasScale )
  223. {
  224. if (FixedScale )
  225. keyFrame.Scale = Scale[0];
  226. else
  227. keyFrame.Scale = Vector3.Lerp(Scale[keyIndex1], Scale[keyIndex2], t);
  228. }
  229. else
  230. {
  231. keyFrame.Scale = Vector3.One;
  232. }
  233. keyFrame.HasScale = HasScale;
  234. return keyFrame;
  235. }
  236. public Matrix GetInterpolateMatrix(float localTime, AnimPlayMode mode)
  237. {
  238. int index1 = 0; // first key frame index
  239. int index2 = 0; // second key frame index
  240. float interpolateTime = 0.0f;
  241. CalculateKeyFrameIndex(localTime, mode, out index1, out index2,
  242. out interpolateTime);
  243. // Calcurate interpolate key frame matrix between KeyFrame1 and KeyFrame2
  244. return GetInterpolateMatrix(index1, index2, interpolateTime);
  245. }
  246. public KeyFrame GetInterpolateKeyFrame(float localTime, AnimPlayMode mode)
  247. {
  248. int index1 = 0; // first key frame index
  249. int index2 = 0; // second key frame index
  250. float interpolateTime = 0.0f;
  251. CalculateKeyFrameIndex(localTime, mode, out index1, out index2,
  252. out interpolateTime);
  253. // Calcurate interpolate key frame matrix between KeyFrame1 and KeyFrame2
  254. return GetInterpolateKeyFrame(index1, index2, interpolateTime);
  255. }
  256. /// <summary>
  257. /// returns two key frame index, which is included in the specified time.
  258. /// </summary>
  259. public void CalculateKeyFrameIndex(float localTime, AnimPlayMode mode,
  260. out int index1, out int index2,
  261. out float interpolateTime)
  262. {
  263. index1 = 0; // first key frame index
  264. index2 = 0; // second key frame index
  265. interpolateTime = 0.0f;
  266. // Calculate first key frame index
  267. if (HasTime )
  268. index1 = GetKeyFrameIndex(localTime);
  269. else
  270. index1 = (int)(localTime / KeyInterval);
  271. // Calculate second key frame index by play mode
  272. switch (mode)
  273. {
  274. case AnimPlayMode.Once: // Just play once
  275. {
  276. // if index1 is last index
  277. index2 = (index1 >= KeyCount - 1 ? index1 : index1 + 1);
  278. }
  279. break;
  280. case AnimPlayMode.Repeat: // Play looping
  281. {
  282. // if index1 is last index, index2 must be begin (looping)
  283. index2 = (index1 >= KeyCount - 1 ? 0 : index1 + 1);
  284. }
  285. break;
  286. default:
  287. throw new NotSupportedException("Not supported play mode");
  288. }
  289. if (index1 >= KeyCount - 1)
  290. {
  291. index1 = index2 = KeyCount - 1;
  292. interpolateTime = 1.0f;
  293. }
  294. else
  295. {
  296. if (HasTime )
  297. {
  298. interpolateTime = (localTime - Time[index1]) /
  299. (Time[index2] - Time[index1]);
  300. }
  301. else
  302. {
  303. interpolateTime = HelperMath.CalculateModulo(localTime, KeyInterval)
  304. / KeyInterval;
  305. }
  306. }
  307. }
  308. /// <summary>
  309. /// returns two key frame index, which is included in the specified time.
  310. /// </summary>
  311. public int GetKeyFrameIndex(float localTime)
  312. {
  313. // Calculate index between two key frame on this time
  314. int startIndex, endIndex, middleIndex;
  315. startIndex = 0;
  316. endIndex = KeyCount - 1;
  317. if (localTime >= Time[endIndex])
  318. {
  319. return endIndex;
  320. }
  321. do
  322. {
  323. middleIndex = (startIndex + endIndex) / 2;
  324. if ((endIndex - startIndex) <= 1)
  325. {
  326. break;
  327. }
  328. else if (Time[middleIndex] < localTime)
  329. {
  330. startIndex = middleIndex;
  331. }
  332. else if (Time[middleIndex] > localTime)
  333. {
  334. endIndex = middleIndex;
  335. }
  336. else
  337. {
  338. startIndex = middleIndex;
  339. break;
  340. }
  341. } while ((endIndex - startIndex) > 1);
  342. return startIndex;
  343. }
  344. }
  345. }