2
0

BsMesh.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. /** Returns an object containing all shapes used for morph animation, if any are available. */
  114. SPtr<MorphShapes> getMorphShapes() const { return mMorphShapes; }
  115. /** Retrieves a core implementation of a mesh usable only from the core thread. */
  116. SPtr<MeshCore> getCore() const;
  117. /** Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh. */
  118. static HMesh dummy();
  119. protected:
  120. friend class MeshManager;
  121. Mesh(const MESH_DESC& desc);
  122. Mesh(const SPtr<MeshData>& initialMeshData, const MESH_DESC& desc);
  123. /** Updates bounds by calculating them from the vertices in the provided mesh data object. */
  124. void updateBounds(const MeshData& meshData);
  125. /** @copydoc CoreObject::createCore */
  126. SPtr<CoreObjectCore> createCore() const override;
  127. /**
  128. * Creates buffers used for caching of CPU mesh data.
  129. *
  130. * @note Make sure to initialize all mesh properties before calling this.
  131. */
  132. void createCPUBuffer();
  133. /** Updates the cached CPU buffers with new data. */
  134. void updateCPUBuffer(UINT32 subresourceIdx, const MeshData& data);
  135. mutable SPtr<MeshData> mCPUData;
  136. SPtr<VertexDataDesc> mVertexDesc;
  137. int mUsage;
  138. IndexType mIndexType;
  139. SPtr<Skeleton> mSkeleton; // Immutable
  140. SPtr<MorphShapes> mMorphShapes; // Immutable
  141. /************************************************************************/
  142. /* SERIALIZATION */
  143. /************************************************************************/
  144. private:
  145. Mesh(); // Serialization only
  146. public:
  147. friend class MeshRTTI;
  148. static RTTITypeBase* getRTTIStatic();
  149. RTTITypeBase* getRTTI() const override;
  150. /************************************************************************/
  151. /* STATICS */
  152. /************************************************************************/
  153. public:
  154. /**
  155. * Creates a new empty mesh. Created mesh will have no sub-meshes.
  156. *
  157. * @param[in] numVertices Number of vertices in the mesh.
  158. * @param[in] numIndices Number of indices in the mesh.
  159. * @param[in] vertexDesc Vertex description structure that describes how are vertices organized in the
  160. * vertex buffer. When binding a mesh to the pipeline you must ensure vertex
  161. * description at least partially matches the input description of the currently bound
  162. * vertex GPU program.
  163. * @param[in] usage Optimizes performance depending on planned usage of the mesh.
  164. * @param[in] drawOp Determines how should the provided indices be interpreted by the pipeline. Default
  165. * option is a triangle list, where three indices represent a single triangle.
  166. * @param[in] indexType Size of indices, use smaller size for better performance, however be careful not to
  167. * go over the number of vertices limited by the size.
  168. */
  169. static HMesh create(UINT32 numVertices, UINT32 numIndices, const SPtr<VertexDataDesc>& vertexDesc,
  170. int usage = MU_STATIC, DrawOperationType drawOp = DOT_TRIANGLE_LIST, IndexType indexType = IT_32BIT);
  171. /**
  172. * Creates a new empty mesh.
  173. *
  174. * @param[in] desc Descriptor containing the properties of the mesh to create.
  175. */
  176. static HMesh create(const MESH_DESC& desc);
  177. /**
  178. * Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  179. * by the mesh data exactly. Mesh will have no sub-meshes.
  180. *
  181. * @param[in] initialData Vertex and index data to initialize the mesh with.
  182. * @param[in] desc Descriptor containing the properties of the mesh to create. Vertex and index count,
  183. * vertex descriptor and index type properties are ignored and are read from provided
  184. * mesh data instead.
  185. */
  186. static HMesh create(const SPtr<MeshData>& initialData, const MESH_DESC& desc);
  187. /**
  188. * Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  189. * by the mesh data exactly. Mesh will have no sub-meshes.
  190. *
  191. * @param[in] initialData Vertex and index data to initialize the mesh with.
  192. * @param[in] usage Optimizes performance depending on planned usage of the mesh.
  193. * @param[in] drawOp Determines how should the provided indices be interpreted by the pipeline. Default
  194. * option is a triangle strip, where three indices represent a single triangle.
  195. */
  196. static HMesh create(const SPtr<MeshData>& initialData, int usage = MU_STATIC,
  197. DrawOperationType drawOp = DOT_TRIANGLE_LIST);
  198. /** @name Internal
  199. * @{
  200. */
  201. /**
  202. * @copydoc create(const MESH_DESC&)
  203. *
  204. * @note Internal method. Use create() for normal use.
  205. */
  206. static SPtr<Mesh> _createPtr(const MESH_DESC& desc);
  207. /**
  208. * @copydoc create(const SPtr<MeshData>&, const MESH_DESC&)
  209. *
  210. * @note Internal method. Use create() for normal use.
  211. */
  212. static SPtr<Mesh> _createPtr(const SPtr<MeshData>& initialData, const MESH_DESC& desc);
  213. /**
  214. * @copydoc create(const SPtr<MeshData>&, int, DrawOperationType)
  215. *
  216. * @note Internal method. Use create() for normal use.
  217. */
  218. static SPtr<Mesh> _createPtr(const SPtr<MeshData>& initialData, int usage = MU_STATIC,
  219. DrawOperationType drawOp = DOT_TRIANGLE_LIST);
  220. /**
  221. * Creates a new empty and uninitialized mesh. You will need to manually initialize the mesh before using it.
  222. *
  223. * @note This should only be used for special cases like serialization and is not meant for normal use.
  224. */
  225. static SPtr<Mesh> createEmpty();
  226. /** @} */
  227. };
  228. /** @} */
  229. /** @addtogroup Resources-Internal
  230. * @{
  231. */
  232. /**
  233. * Core thread portion of a Mesh.
  234. *
  235. * @note Core thread.
  236. */
  237. class BS_CORE_EXPORT MeshCore : public MeshCoreBase
  238. {
  239. public:
  240. MeshCore(const SPtr<MeshData>& initialMeshData, const MESH_DESC& desc);
  241. ~MeshCore();
  242. /** @copydoc CoreObjectCore::initialize */
  243. void initialize() override;
  244. /** @copydoc MeshCoreBase::getVertexData */
  245. SPtr<VertexData> getVertexData() const override;
  246. /** @copydoc MeshCoreBase::getIndexBuffer */
  247. SPtr<IndexBufferCore> getIndexBuffer() const override;
  248. /** @copydoc MeshCoreBase::getVertexDesc */
  249. SPtr<VertexDataDesc> getVertexDesc() const override;
  250. /** Returns a skeleton that can be used for animating the mesh. */
  251. SPtr<Skeleton> getSkeleton() const { return mSkeleton; }
  252. /** Returns an object containing all shapes used for morph animation, if any are available. */
  253. SPtr<MorphShapes> getMorphShapes() const { return mMorphShapes; }
  254. /**
  255. * Updates a part of the current mesh with the provided data.
  256. *
  257. * @param[in] subresourceIdx Index of the subresource to update, if the mesh has more than one.
  258. * @param[in] data Data to update the mesh with.
  259. * @param[in] discardEntireBuffer When true the existing contents of the resource you are updating will be
  260. * discarded. This can make the operation faster. Resources with certain buffer
  261. * types might require this flag to be in a specific state otherwise the operation
  262. * will fail.
  263. * @param[in] updateBounds If true the internal bounds of the mesh will be recalculated based on the
  264. * provided data.
  265. */
  266. virtual void writeSubresource(UINT32 subresourceIdx, const MeshData& data, bool discardEntireBuffer, bool updateBounds = true);
  267. /**
  268. * Reads a part of the current resource into the provided @p data parameter. Data buffer needs to be pre-allocated.
  269. *
  270. * @param[in] subresourceIdx Index of the subresource to update, if the mesh has more than one.
  271. * @param[out] data Buffer that will receive the data. Should be allocated with
  272. * allocateSubresourceBuffer() to ensure it is of valid type and size.
  273. */
  274. virtual void readSubresource(UINT32 subresourceIdx, MeshData& data);
  275. /**
  276. * Creates a new empty mesh. Created mesh will have no sub-meshes.
  277. *
  278. * @param[in] numVertices Number of vertices in the mesh.
  279. * @param[in] numIndices Number of indices in the mesh.
  280. * @param[in] vertexDesc Vertex description structure that describes how are vertices organized in the
  281. * vertex buffer. When binding a mesh to the pipeline you must ensure vertex
  282. * description at least partially matches the input description of the currently
  283. * bound vertex GPU program.
  284. * @param[in] usage Optimizes performance depending on planned usage of the mesh.
  285. * @param[in] drawOp Determines how should the provided indices be interpreted by the pipeline. Default
  286. * option is a triangle list, where three indices represent a single triangle.
  287. * @param[in] indexType Size of indices, use smaller size for better performance, however be careful not to
  288. * go over the number of vertices limited by the size.
  289. */
  290. static SPtr<MeshCore> create(UINT32 numVertices, UINT32 numIndices, const SPtr<VertexDataDesc>& vertexDesc,
  291. int usage = MU_STATIC, DrawOperationType drawOp = DOT_TRIANGLE_LIST, IndexType indexType = IT_32BIT);
  292. /**
  293. * Creates a new empty mesh.
  294. *
  295. * @param[in] desc Descriptor containing the properties of the mesh to create.
  296. */
  297. static SPtr<MeshCore> create(const MESH_DESC& desc);
  298. /**
  299. * Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  300. * by the mesh data exactly.
  301. *
  302. * @param[in] initialData Vertex and index data to initialize the mesh with.
  303. * @param[in] desc Descriptor containing the properties of the mesh to create. Vertex and index count,
  304. * vertex descriptor and index type properties are ignored and are read from provided
  305. * mesh data instead.
  306. */
  307. static SPtr<MeshCore> create(const SPtr<MeshData>& initialData, const MESH_DESC& desc);
  308. /**
  309. * Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
  310. * by the mesh data exactly. Mesh will have no sub-meshes.
  311. *
  312. * @param[in] initialData Vertex and index data to initialize the mesh with.
  313. * @param[in] usage Optimizes performance depending on planned usage of the mesh.
  314. * @param[in] drawOp Determines how should the provided indices be interpreted by the pipeline. Default
  315. * option is a triangle strip, where three indices represent a single triangle.
  316. */
  317. static SPtr<MeshCore> create(const SPtr<MeshData>& initialData, int usage = MU_STATIC,
  318. DrawOperationType drawOp = DOT_TRIANGLE_LIST);
  319. protected:
  320. friend class Mesh;
  321. /** Updates bounds by calculating them from the vertices in the provided mesh data object. */
  322. void updateBounds(const MeshData& meshData);
  323. SPtr<VertexData> mVertexData;
  324. SPtr<IndexBufferCore> mIndexBuffer;
  325. SPtr<VertexDataDesc> mVertexDesc;
  326. int mUsage;
  327. IndexType mIndexType;
  328. SPtr<MeshData> mTempInitialMeshData;
  329. SPtr<Skeleton> mSkeleton; // Immutable
  330. SPtr<MorphShapes> mMorphShapes; // Immutable
  331. };
  332. /** @} */
  333. }