Mesh.cs 9.6 KB

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