BsMesh.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "BsMeshBase.h"
  6. #include "BsMeshData.h"
  7. #include "BsVertexData.h"
  8. #include "BsDrawOps.h"
  9. #include "BsSubMesh.h"
  10. #include "BsBounds.h"
  11. namespace BansheeEngine
  12. {
  13. /** @addtogroup Resources
  14. * @{
  15. */
  16. /** Descriptor object used for creation of a new Mesh object. */
  17. struct BS_CORE_EXPORT MESH_DESC
  18. {
  19. MESH_DESC() { }
  20. /** Number of vertices in the mesh. */
  21. UINT32 numVertices = 0;
  22. /** Number of indices in the mesh. */
  23. UINT32 numIndices = 0;
  24. /**
  25. * Vertex description structure that describes how are vertices organized in the vertex buffer. When binding a mesh
  26. * to the pipeline you must ensure vertex description at least partially matches the input description of the
  27. * currently bound vertex GPU program.
  28. */
  29. SPtr<VertexDataDesc> vertexDesc;
  30. /**
  31. * Defines how are indices separated into sub-meshes, and how are those sub-meshes rendered. Sub-meshes may be
  32. * rendered independently.
  33. */
  34. Vector<SubMesh> subMeshes;
  35. /** Optimizes performance depending on planned usage of the mesh. */
  36. INT32 usage = MU_STATIC;
  37. /**
  38. * Size of indices, use smaller size for better performance, however be careful not to go over the number of
  39. * vertices limited by the size.
  40. */
  41. IndexType indexType = IT_32BIT;
  42. /** Optional skeleton that can be used for skeletal animation of the mesh. */
  43. SPtr<Skeleton> skeleton;
  44. /** Optional set of morph shapes that can be used for per-vertex animation of the mesh. */
  45. SPtr<MorphShapes> morphShapes;
  46. static MESH_DESC DEFAULT;
  47. };
  48. /**
  49. * Primary class for holding geometry. Stores data in the form of a vertex buffers and optionally index buffer, which
  50. * may be bound to the pipeline for drawing. May contain multiple sub-meshes.
  51. *
  52. * @note Sim thread.
  53. */
  54. class BS_CORE_EXPORT Mesh : public MeshBase
  55. {
  56. public:
  57. virtual ~Mesh();
  58. /** @copydoc MeshBase::initialize */
  59. void initialize() override;
  60. /**
  61. * Updates the mesh with new data. The actual write will be queued for later execution on the core thread. Provided
  62. * data buffer will be locked until the operation completes.
  63. *
  64. * @param[in] accessor Accessor to queue the operation on.
  65. * @param[in] subresourceIdx Index of the subresource to write to. Ignored for now.
  66. * @param[in] data Data of valid size and format to write to the subresource.
  67. * @param[in] discardEntireBuffer When true the existing contents of the resource you are updating will be
  68. * discarded. This can make the operation faster. Resources with certain buffer
  69. * types might require this flag to be in a specific state otherwise the operation
  70. * will fail.
  71. * @return Async operation object you can use to track operation completion.
  72. *
  73. * @see MeshCore::writeSubresource
  74. */
  75. AsyncOp writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<MeshData>& data,
  76. bool discardEntireBuffer);
  77. /**
  78. * Reads internal mesh data to the provided previously allocated buffer. The read is queued for execution on the
  79. * core thread and not executed immediately. Provided data buffer will be locked until the operation completes.
  80. *
  81. * @param[in] accessor Accessor to queue the operation on.
  82. * @param[in] subresourceIdx Index of the subresource to read from. Ignored for now.
  83. * @param[out] data Previously allocated buffer of valid size and format to read the data into. Can be
  84. * allocated using allocateSubresourceBuffer().
  85. * @return Async operation object you can use to track operation completion.
  86. *
  87. * @see MeshCore::readSubresource
  88. */
  89. AsyncOp readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<MeshData>& data);
  90. /**
  91. * Allocates a buffer you may use for storage when reading a subresource. You need to allocate such a buffer if you
  92. * are calling readSubresource().
  93. *
  94. * @param[in] subresourceIdx Only 0 is supported. You can only update entire mesh at once.
  95. *
  96. * @note Thread safe.
  97. */
  98. SPtr<MeshData> allocateSubresourceBuffer(UINT32 subresourceIdx) const;
  99. /**
  100. * Reads data from the cached system memory mesh buffer into the provided buffer.
  101. *
  102. * @param[in] dest Previously allocated buffer to read data into.
  103. *
  104. * @note
  105. * The data read is the cached mesh data. Any data written to the mesh from the GPU or core thread will not be
  106. * reflected in this data. Use readSubresource() if you require those changes.
  107. * @note
  108. * The mesh must have been created with MU_CPUCACHED usage otherwise this method will not return any data.
  109. */
  110. void readData(MeshData& dest);
  111. /** Gets the skeleton required for animation of this mesh, if any is available. */
  112. SPtr<Skeleton> getSkeleton() const { return mSkeleton; }
  113. /** Retrieves a core implementation of a mesh usable only from the core thread. */
  114. SPtr<MeshCore> getCore() const;
  115. /** Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh. */
  116. static HMesh dummy();
  117. protected:
  118. friend class MeshManager;
  119. Mesh(const MESH_DESC& desc);
  120. Mesh(const SPtr<MeshData>& initialMeshData, const MESH_DESC& desc);
  121. /** Updates bounds by calculating them from the vertices in the provided mesh data object. */
  122. void updateBounds(const MeshData& meshData);
  123. /** @copydoc CoreObject::createCore */
  124. SPtr<CoreObjectCore> createCore() const override;
  125. /**
  126. * Creates buffers used for caching of CPU mesh data.
  127. *
  128. * @note Make sure to initialize all mesh properties before calling this.
  129. */
  130. void createCPUBuffer();
  131. /** Updates the cached CPU buffers with new data. */
  132. void updateCPUBuffer(UINT32 subresourceIdx, const MeshData& data);
  133. mutable SPtr<MeshData> mCPUData;
  134. SPtr<VertexDataDesc> mVertexDesc;
  135. int mUsage;
  136. IndexType mIndexType;
  137. SPtr<Skeleton> mSkeleton; // Immutable
  138. SPtr<MorphShapes> mMorphShapes; // Immutable
  139. /************************************************************************/
  140. /* SERIALIZATION */
  141. /************************************************************************/
  142. private:
  143. Mesh(); // Serialization only
  144. public:
  145. friend class MeshRTTI;
  146. static RTTITypeBase* getRTTIStatic();
  147. RTTITypeBase* getRTTI() const override;
  148. /************************************************************************/
  149. /* STATICS */
  150. /************************************************************************/
  151. public:
  152. /**
  153. * Creates a new empty mesh. Created mesh will have no sub-meshes.
  154. *
  155. * @param[in] numVertices Number of vertices in the mesh.
  156. * @param[in] numIndices Number of indices in the mesh.
  157. * @param[in] vertexDesc Vertex description structure that describes how are vertices organized in the
  158. * vertex buffer. When binding a mesh to the pipeline you must ensure vertex
  159. * description at least partially matches the input description of the currently bound
  160. * vertex GPU program.
  161. * @param[in] usage Optimizes performance depending on planned usage of the mesh.
  162. * @param[in] drawOp Determines how should the provided indices be interpreted by the pipeline. Default
  163. * option is a triangle list, where three indices represent a single triangle.
  164. * @param[in] indexType Size of indices, use smaller size for better performance, however be careful not to
  165. * go over the number of vertices limited by the size.
  166. */
  167. static HMesh create(UINT32 numVertices, UINT32 numIndices, const SPtr<VertexDataDesc>& vertexDesc,
  168. int usage = MU_STATIC, DrawOperationType drawOp = DOT_TRIANGLE_LIST, IndexType indexType = IT_32BIT);
  169. /**
  170. * Creates a new empty mesh.
  171. *
  172. * @param[in] desc Descriptor containing the properties of the mesh to create.
  173. */
  174. static HMesh create(const MESH_DESC& desc);
  175. /**
  176. * Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  177. * by the mesh data exactly. Mesh will have no sub-meshes.
  178. *
  179. * @param[in] initialData Vertex and index data to initialize the mesh with.
  180. * @param[in] desc Descriptor containing the properties of the mesh to create. Vertex and index count,
  181. * vertex descriptor and index type properties are ignored and are read from provided
  182. * mesh data instead.
  183. */
  184. static HMesh create(const SPtr<MeshData>& initialData, const MESH_DESC& desc);
  185. /**
  186. * Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  187. * by the mesh data exactly. Mesh will have no sub-meshes.
  188. *
  189. * @param[in] initialData Vertex and index data to initialize the mesh with.
  190. * @param[in] usage Optimizes performance depending on planned usage of the mesh.
  191. * @param[in] drawOp Determines how should the provided indices be interpreted by the pipeline. Default
  192. * option is a triangle strip, where three indices represent a single triangle.
  193. */
  194. static HMesh create(const SPtr<MeshData>& initialData, int usage = MU_STATIC,
  195. DrawOperationType drawOp = DOT_TRIANGLE_LIST);
  196. /** @name Internal
  197. * @{
  198. */
  199. /**
  200. * @copydoc create(const MESH_DESC&)
  201. *
  202. * @note Internal method. Use create() for normal use.
  203. */
  204. static SPtr<Mesh> _createPtr(const MESH_DESC& desc);
  205. /**
  206. * @copydoc create(const SPtr<MeshData>&, const MESH_DESC&)
  207. *
  208. * @note Internal method. Use create() for normal use.
  209. */
  210. static SPtr<Mesh> _createPtr(const SPtr<MeshData>& initialData, const MESH_DESC& desc);
  211. /**
  212. * @copydoc create(const SPtr<MeshData>&, int, DrawOperationType)
  213. *
  214. * @note Internal method. Use create() for normal use.
  215. */
  216. static SPtr<Mesh> _createPtr(const SPtr<MeshData>& initialData, int usage = MU_STATIC,
  217. DrawOperationType drawOp = DOT_TRIANGLE_LIST);
  218. /**
  219. * Creates a new empty and uninitialized mesh. You will need to manually initialize the mesh before using it.
  220. *
  221. * @note This should only be used for special cases like serialization and is not meant for normal use.
  222. */
  223. static SPtr<Mesh> createEmpty();
  224. /** @} */
  225. };
  226. /** @} */
  227. /** @addtogroup Resources-Internal
  228. * @{
  229. */
  230. /**
  231. * Core thread portion of a Mesh.
  232. *
  233. * @note Core thread.
  234. */
  235. class BS_CORE_EXPORT MeshCore : public MeshCoreBase
  236. {
  237. public:
  238. MeshCore(const SPtr<MeshData>& initialMeshData, const MESH_DESC& desc);
  239. ~MeshCore();
  240. /** @copydoc CoreObjectCore::initialize */
  241. void initialize() override;
  242. /** @copydoc MeshCoreBase::getVertexData */
  243. SPtr<VertexData> getVertexData() const override;
  244. /** @copydoc MeshCoreBase::getIndexBuffer */
  245. SPtr<IndexBufferCore> getIndexBuffer() const override;
  246. /** @copydoc MeshCoreBase::getVertexDesc */
  247. SPtr<VertexDataDesc> getVertexDesc() const override;
  248. /** Returns a skeleton that can be used for animating the mesh. */
  249. SPtr<Skeleton> getSkeleton() const { return mSkeleton; }
  250. /**
  251. * Updates a part of the current mesh with the provided data.
  252. *
  253. * @param[in] subresourceIdx Index of the subresource to update, if the mesh has more than one.
  254. * @param[in] data Data to update the mesh with.
  255. * @param[in] discardEntireBuffer When true the existing contents of the resource you are updating will be
  256. * discarded. This can make the operation faster. Resources with certain buffer
  257. * types might require this flag to be in a specific state otherwise the operation
  258. * will fail.
  259. * @param[in] updateBounds If true the internal bounds of the mesh will be recalculated based on the
  260. * provided data.
  261. */
  262. virtual void writeSubresource(UINT32 subresourceIdx, const MeshData& data, bool discardEntireBuffer, bool updateBounds = true);
  263. /**
  264. * Reads a part of the current resource into the provided @p data parameter. Data buffer needs to be pre-allocated.
  265. *
  266. * @param[in] subresourceIdx Index of the subresource to update, if the mesh has more than one.
  267. * @param[out] data Buffer that will receive the data. Should be allocated with
  268. * allocateSubresourceBuffer() to ensure it is of valid type and size.
  269. */
  270. virtual void readSubresource(UINT32 subresourceIdx, MeshData& data);
  271. /**
  272. * Creates a new empty mesh. Created mesh will have no sub-meshes.
  273. *
  274. * @param[in] numVertices Number of vertices in the mesh.
  275. * @param[in] numIndices Number of indices in the mesh.
  276. * @param[in] vertexDesc Vertex description structure that describes how are vertices organized in the
  277. * vertex buffer. When binding a mesh to the pipeline you must ensure vertex
  278. * description at least partially matches the input description of the currently
  279. * bound vertex GPU program.
  280. * @param[in] usage Optimizes performance depending on planned usage of the mesh.
  281. * @param[in] drawOp Determines how should the provided indices be interpreted by the pipeline. Default
  282. * option is a triangle list, where three indices represent a single triangle.
  283. * @param[in] indexType Size of indices, use smaller size for better performance, however be careful not to
  284. * go over the number of vertices limited by the size.
  285. */
  286. static SPtr<MeshCore> create(UINT32 numVertices, UINT32 numIndices, const SPtr<VertexDataDesc>& vertexDesc,
  287. int usage = MU_STATIC, DrawOperationType drawOp = DOT_TRIANGLE_LIST, IndexType indexType = IT_32BIT);
  288. /**
  289. * Creates a new empty mesh.
  290. *
  291. * @param[in] desc Descriptor containing the properties of the mesh to create.
  292. */
  293. static SPtr<MeshCore> create(const MESH_DESC& desc);
  294. /**
  295. * Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  296. * by the mesh data exactly.
  297. *
  298. * @param[in] initialData Vertex and index data to initialize the mesh with.
  299. * @param[in] desc Descriptor containing the properties of the mesh to create. Vertex and index count,
  300. * vertex descriptor and index type properties are ignored and are read from provided
  301. * mesh data instead.
  302. */
  303. static SPtr<MeshCore> create(const SPtr<MeshData>& initialData, const MESH_DESC& desc);
  304. /**
  305. * Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  306. * by the mesh data exactly. Mesh will have no sub-meshes.
  307. *
  308. * @param[in] initialData Vertex and index data to initialize the mesh with.
  309. * @param[in] usage Optimizes performance depending on planned usage of the mesh.
  310. * @param[in] drawOp Determines how should the provided indices be interpreted by the pipeline. Default
  311. * option is a triangle strip, where three indices represent a single triangle.
  312. */
  313. static SPtr<MeshCore> create(const SPtr<MeshData>& initialData, int usage = MU_STATIC,
  314. DrawOperationType drawOp = DOT_TRIANGLE_LIST);
  315. protected:
  316. friend class Mesh;
  317. /** Updates bounds by calculating them from the vertices in the provided mesh data object. */
  318. void updateBounds(const MeshData& meshData);
  319. SPtr<VertexData> mVertexData;
  320. SPtr<IndexBufferCore> mIndexBuffer;
  321. SPtr<VertexDataDesc> mVertexDesc;
  322. int mUsage;
  323. IndexType mIndexType;
  324. SPtr<MeshData> mTempInitialMeshData;
  325. SPtr<Skeleton> mSkeleton; // Immutable
  326. SPtr<MorphShapes> mMorphShapes; // Immutable
  327. };
  328. /** @} */
  329. }