PageRenderTime 30ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/ContentSystem/Rendering/MeshAnimationData.cs

#
C# | 206 lines | 109 code | 16 blank | 81 comment | 11 complexity | e803a852f432ba8acda0b7440a919f28 MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using System.IO;
  3. using Delta.Utilities;
  4. using Delta.Utilities.Datatypes;
  5. using Delta.Utilities.Helpers;
  6. namespace Delta.ContentSystem.Rendering
  7. {
  8. /// <summary>
  9. /// Mesh Animation data class, which keeps all the data (matrices) for one
  10. /// mesh animation. This can be something like a simple Idle animation or
  11. /// some really complex cinematic animation for a character with bones.
  12. /// See BoneData for the bone details. Mesh and MeshAnimations must fit.
  13. /// </summary>
  14. public class MeshAnimationData : Content, ISaveLoadBinary
  15. {
  16. #region Constants
  17. /// <summary>
  18. /// Version number for this MeshData. If this goes above 1, we need
  19. /// to support loading older versions as well. Saving is always going
  20. /// to be the latest version (this one).
  21. /// </summary>
  22. private const int CurrentVersion = 1;
  23. #endregion
  24. #region Get (Static)
  25. /// <summary>
  26. /// Get and load content based on the content name. This method makes sure
  27. /// we do not load the same content twice (the constructor is protected).
  28. /// </summary>
  29. /// <param name="contentName">Content name we want to load, this is
  30. /// passed onto the Content System, which will do the actual loading with
  31. /// help of the Load method in this class.</param>
  32. /// <returns>The loaded Content object, always unique for the same
  33. /// name, this helps comparing data.</returns>
  34. public static MeshAnimationData Get(string contentName)
  35. {
  36. return Get<MeshAnimationData>(contentName,
  37. ContentType.MeshAnimation);
  38. }
  39. #endregion
  40. #region Frames (Public)
  41. /// <summary>
  42. /// Array of animation frames (as array of bone matrices), e.g.
  43. /// <para />
  44. /// Frames[0] -> Frame 1
  45. /// Frames[0][0] -> Bone Matrix 1
  46. /// Frames[0][1] -> Bone Matrix 2
  47. /// Frames[1] -> Frame 2
  48. /// Frames[1][0] -> Bone Matrix 1
  49. /// Frames[1][1] -> Bone Matrix 2
  50. /// </summary>
  51. public Matrix[][] Frames
  52. {
  53. get;
  54. private set;
  55. }
  56. #endregion
  57. #region Constructors
  58. /// <summary>
  59. /// Create mesh animation data with a given set of matrices for the bones.
  60. /// </summary>
  61. /// <param name="setAnimationFrames">Set animation frames</param>
  62. public MeshAnimationData(Matrix[][] setAnimationFrames)
  63. : base(EmptyName, ContentType.MeshAnimation)
  64. {
  65. Frames = setAnimationFrames;
  66. }
  67. /// <summary>
  68. /// Create mesh animation data by loading it from content, use the static
  69. /// Get method to call this.
  70. /// </summary>
  71. /// <param name="contentName">Name of the content.</param>
  72. protected MeshAnimationData(string contentName)
  73. : base(contentName, ContentType.MeshAnimation)
  74. {
  75. }
  76. #endregion
  77. #region ISaveLoadBinary Members
  78. /// <summary>
  79. /// Load animation data, which is mostly animation matrices.
  80. /// </summary>
  81. /// <param name="reader">Reader</param>
  82. public void Load(BinaryReader reader)
  83. {
  84. // We currently only support our version, if more versions are added,
  85. // we need to do different loading code depending on the version here.
  86. int version = reader.ReadInt32();
  87. if (version != CurrentVersion)
  88. {
  89. Log.InvalidVersionWarning(GetType().Name, version, CurrentVersion);
  90. return;
  91. }
  92. // Load the frames now
  93. // At first we need the number of frames we will get
  94. int frameCount = reader.ReadInt32();
  95. // and at second the number of bone transformations we will get for every
  96. // single frame
  97. // Note:
  98. // 1. The value is only be saved if we have any frames
  99. // 2. We only get one number for all bones, because for every frame the
  100. // number of bones is the same
  101. int boneCountPerFrame = (frameCount > 0)
  102. ? reader.ReadInt32()
  103. : 0;
  104. // Finally just reconstruct the frames now
  105. Frames = new Matrix[frameCount][];
  106. for (int frameId = 0; frameId < frameCount; frameId++)
  107. {
  108. Frames[frameId] = new Matrix[boneCountPerFrame];
  109. for (int boneIndex = 0; boneIndex < boneCountPerFrame; boneIndex++)
  110. {
  111. Frames[frameId][boneIndex].Load(reader);
  112. }
  113. }
  114. }
  115. /// <summary>
  116. /// Save animation data, which is mostly animation matrices.
  117. /// </summary>
  118. /// <param name="dataWriter">Data writer</param>
  119. public void Save(BinaryWriter dataWriter)
  120. {
  121. dataWriter.Write(CurrentVersion);
  122. // Save out the frames
  123. // at first the number of frames in total
  124. dataWriter.Write(Frames.Length);
  125. // and then the number of bones / bone transformations (only if needed)
  126. // Note:
  127. // We can do this only once, because here we have always the same amount
  128. // of bones for ALL frames, else we have to save the number of bones for
  129. // every single frame
  130. int boneCountPerFrame = (Frames.Length > 0)
  131. ? Frames[0].Length
  132. : 0;
  133. if (boneCountPerFrame > 0)
  134. {
  135. dataWriter.Write(boneCountPerFrame);
  136. }
  137. // Finally iterate through every frame
  138. for (int frameId = 0; frameId < Frames.Length; frameId++)
  139. {
  140. // and every bone transformation which is in the current frame
  141. for (int boneIndex = 0; boneIndex < boneCountPerFrame; boneIndex++)
  142. {
  143. // and save it out
  144. Frames[frameId][boneIndex].Save(dataWriter);
  145. }
  146. }
  147. }
  148. #endregion
  149. #region Methods (Private)
  150. #region Load
  151. /// <summary>
  152. /// Native load method, will just load the data.
  153. /// </summary>
  154. /// <param name="alreadyLoadedNativeData">
  155. /// The first instance that has already loaded the required content data
  156. /// of this content class or just 'null' if there is none loaded yet (or
  157. /// anymore).
  158. /// </param>
  159. protected override void Load(Content alreadyLoadedNativeData)
  160. {
  161. try
  162. {
  163. if (alreadyLoadedNativeData != null)
  164. {
  165. // Just clone all data
  166. MeshAnimationData otherData =
  167. alreadyLoadedNativeData as MeshAnimationData;
  168. Frames = otherData.Frames;
  169. // This object cannot be used for cloning now, but the caller (Mesh)
  170. // can set itself as the NativeClassObject and allow native cloning.
  171. return;
  172. }
  173. if (String.IsNullOrEmpty(RelativeFilePath) == false)
  174. {
  175. // Load via the ISaveLoadBinary interface methods below.
  176. // Cloning should not really happen for shaders anyway.
  177. FileHelper.Load(RelativeFilePath, this);
  178. }
  179. }
  180. catch (Exception ex)
  181. {
  182. Log.Warning("Failed to load mesh animation data from file '" +
  183. RelativeFilePath + "': " + ex);
  184. FailedToLoad = true;
  185. }
  186. }
  187. #endregion
  188. #endregion
  189. }
  190. }