Mesh.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.InteropServices;
  4. namespace BansheeEngine
  5. {
  6. /// <summary>
  7. /// Primary class for holding geometry. Stores data in the form of a vertex buffers and optionally index buffer,
  8. /// which may be bound to the pipeline for drawing. May contain multiple sub-meshes.
  9. /// </summary>
  10. public class Mesh : Resource
  11. {
  12. /// <summary>
  13. /// Constructor for internal use by the runtime.
  14. /// </summary>
  15. private Mesh()
  16. { }
  17. /// <summary>
  18. /// Creates a new mesh with enough space to hold the a number of primitives using the specified layout. All indices
  19. /// will be part of a single sub-mesh.
  20. /// </summary>
  21. /// <param name="numVertices">Number of vertices in the mesh.</param>
  22. /// <param name="numIndices">Number of indices in the mesh. </param>
  23. /// <param name="topology">Determines how should the provided indices be interpreted by the pipeline. Default option
  24. /// is a triangle list, where three indices represent a single triangle.</param>
  25. /// <param name="usage">Optimizes performance depending on planned usage of the mesh.</param>
  26. /// <param name="vertex">Controls how are vertices organized in the vertex buffer and what data they contain.</param>
  27. /// <param name="index">Size of indices, use smaller size for better performance, however be careful not to go over
  28. /// the number of vertices limited by the size.</param>
  29. public Mesh(int numVertices, int numIndices, MeshTopology topology = MeshTopology.TriangleList,
  30. MeshUsage usage = MeshUsage.Default, VertexType vertex = VertexType.Position,
  31. IndexType index = IndexType.Index32)
  32. {
  33. SubMesh[] subMeshes = {new SubMesh(0, numIndices, topology)};
  34. Internal_CreateInstance(this, numVertices, numIndices, subMeshes, usage, vertex, index);
  35. }
  36. /// <summary>
  37. /// Creates a new mesh with enough space to hold the a number of primitives using the specified layout. Indices can
  38. /// be references by multiple sub-meshes.
  39. /// </summary>
  40. /// <param name="numVertices">Number of vertices in the mesh.</param>
  41. /// <param name="numIndices">Number of indices in the mesh. </param>
  42. /// <param name="subMeshes">Defines how are indices separated into sub-meshes, and how are those sub-meshes rendered.
  43. /// Sub-meshes may be rendered independently.</param>
  44. /// <param name="usage">Optimizes performance depending on planned usage of the mesh.</param>
  45. /// <param name="vertex">Controls how are vertices organized in the vertex buffer and what data they contain.</param>
  46. /// <param name="index">Size of indices, use smaller size for better performance, however be careful not to go over
  47. /// the number of vertices limited by the size.</param>
  48. public Mesh(int numVertices, int numIndices, SubMesh[] subMeshes, MeshUsage usage = MeshUsage.Default,
  49. VertexType vertex = VertexType.Position, IndexType index = IndexType.Index32)
  50. {
  51. Internal_CreateInstance(this, numVertices, numIndices, subMeshes, usage, vertex, index);
  52. }
  53. /// <summary>
  54. /// Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  55. /// by the mesh data exactly. Mesh will have no sub-meshes.
  56. /// </summary>
  57. /// <param name="data">Vertex and index data to initialize the mesh with.</param>
  58. /// <param name="topology">Determines how should the provided indices be interpreted by the pipeline. Default option
  59. /// is a triangle list, where three indices represent a single triangle.</param>
  60. /// <param name="usage">Optimizes performance depending on planned usage of the mesh.</param>
  61. public Mesh(MeshData data, MeshTopology topology = MeshTopology.TriangleList, MeshUsage usage = MeshUsage.Default)
  62. {
  63. int numIndices = 0;
  64. IntPtr dataPtr = IntPtr.Zero;
  65. if (data != null)
  66. {
  67. numIndices = data.IndexCount;
  68. dataPtr = data.GetCachedPtr();
  69. }
  70. SubMesh[] subMeshes = { new SubMesh(0, numIndices, topology) };
  71. Internal_CreateInstanceMeshData(this, dataPtr, subMeshes, usage);
  72. }
  73. /// <summary>
  74. /// Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  75. /// by the mesh data exactly. Mesh will have specified the sub-meshes.
  76. /// </summary>
  77. /// <param name="data">Vertex and index data to initialize the mesh with.</param>
  78. /// <param name="subMeshes">Defines how are indices separated into sub-meshes, and how are those sub-meshes rendered.
  79. /// Sub-meshes may be rendered independently.</param>
  80. /// <param name="usage">Optimizes performance depending on planned usage of the mesh.</param>
  81. public Mesh(MeshData data, SubMesh[] subMeshes, MeshUsage usage = MeshUsage.Default)
  82. {
  83. IntPtr dataPtr = IntPtr.Zero;
  84. if (data != null)
  85. dataPtr = data.GetCachedPtr();
  86. Internal_CreateInstanceMeshData(this, dataPtr, subMeshes, usage);
  87. }
  88. /// <summary>
  89. /// Returns the number of sub-meshes contained in the mesh.
  90. /// </summary>
  91. public int SubMeshCount
  92. {
  93. get { return Internal_GetSubMeshCount(mCachedPtr); }
  94. }
  95. /// <summary>
  96. /// Returns all sub-meshes contained in the mesh.
  97. /// </summary>
  98. public SubMesh[] SubMeshes
  99. {
  100. get { return Internal_GetSubMeshes(mCachedPtr); }
  101. }
  102. /// <summary>
  103. /// Returns local bounds of the geometry contained in the vertex buffers for all sub-meshes.
  104. /// </summary>
  105. public Bounds Bounds
  106. {
  107. get
  108. {
  109. AABox box;
  110. Sphere sphere;
  111. Internal_GetBounds(mCachedPtr, out box, out sphere);
  112. return new Bounds(box, sphere);
  113. }
  114. }
  115. /// <summary>
  116. /// Returns the vertex and index data contained in the mesh. Mesh must have been created with a
  117. /// <see cref="MeshUsage.CPUCached"/> flag.
  118. /// </summary>
  119. /// <returns>Vertex and index data contained in the mesh</returns>
  120. public MeshData GetMeshData()
  121. {
  122. return Internal_GetMeshData(mCachedPtr);
  123. }
  124. /// <summary>
  125. /// Updates the vertex and index data contained in the mesh.
  126. /// </summary>
  127. /// <param name="data">Vertex and index data. Data must match mesh vertex/index counts, vertex layout and index
  128. /// format.</param>
  129. public void SetMeshData(MeshData data)
  130. {
  131. IntPtr dataPtr = IntPtr.Zero;
  132. if (data != null)
  133. dataPtr = data.GetCachedPtr();
  134. Internal_SetMeshData(mCachedPtr, dataPtr);
  135. }
  136. [MethodImpl(MethodImplOptions.InternalCall)]
  137. private static extern void Internal_CreateInstance(Mesh instance, int numVertices,
  138. int numIndices, SubMesh[] subMeshes, MeshUsage usage, VertexType vertex, IndexType index);
  139. [MethodImpl(MethodImplOptions.InternalCall)]
  140. private static extern void Internal_CreateInstanceMeshData(Mesh instance, IntPtr data, SubMesh[] subMeshes,
  141. MeshUsage usage);
  142. [MethodImpl(MethodImplOptions.InternalCall)]
  143. private static extern SubMesh[] Internal_GetSubMeshes(IntPtr thisPtr);
  144. [MethodImpl(MethodImplOptions.InternalCall)]
  145. private static extern int Internal_GetSubMeshCount(IntPtr thisPtr);
  146. [MethodImpl(MethodImplOptions.InternalCall)]
  147. private static extern void Internal_GetBounds(IntPtr thisPtr, out AABox box, out Sphere sphere);
  148. [MethodImpl(MethodImplOptions.InternalCall)]
  149. private static extern MeshData Internal_GetMeshData(IntPtr thisPtr);
  150. [MethodImpl(MethodImplOptions.InternalCall)]
  151. private static extern void Internal_SetMeshData(IntPtr thisPtr, IntPtr value);
  152. }
  153. /// <summary>
  154. /// Data about a sub-mesh range and the type of primitives contained in the range.
  155. /// </summary>
  156. [StructLayout(LayoutKind.Sequential)]
  157. public struct SubMesh // Note: Must match C++ class SubMesh
  158. {
  159. public SubMesh(int indexOffset, int indexCount, MeshTopology topology = MeshTopology.TriangleList)
  160. {
  161. IndexOffset = indexOffset;
  162. IndexCount = indexCount;
  163. Topology = topology;
  164. }
  165. public int IndexOffset;
  166. public int IndexCount;
  167. public MeshTopology Topology;
  168. }
  169. /// <summary>
  170. /// Determines how are mesh indices interpreted by the renderer.
  171. /// </summary>
  172. public enum MeshTopology // Note: Must match C++ class MeshTopology
  173. {
  174. PointList = 1,
  175. LineList = 2,
  176. LineStrip = 3,
  177. TriangleList = 4,
  178. TriangleStrip = 5,
  179. TriangleFan = 6
  180. }
  181. /// <summary>
  182. /// Planned usage for the mesh that allow various optimizations.
  183. /// </summary>
  184. public enum MeshUsage // Note: Must match C++ enum MeshUsage
  185. {
  186. /// <summary>
  187. /// Specify for a mesh that is not often updated from the CPU.
  188. /// </summary>
  189. Default = 0x1,
  190. /// <summary>
  191. /// Specify for a mesh that is often updated from the CPU.
  192. /// </summary>
  193. Dynamic = 0x2,
  194. /// <summary>
  195. /// All mesh data will also be cached in CPU memory allowing the mesh data to be read.
  196. /// </summary>
  197. CPUCached = 0x1000
  198. }
  199. }