CmMeshData.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #pragma once
  2. #include "CmPrerequisites.h"
  3. #include "CmGpuResourceData.h"
  4. #include "CmVertexBuffer.h"
  5. #include "CmIndexBuffer.h"
  6. #include "CmVertexDeclaration.h"
  7. #include "CmRenderOpMesh.h"
  8. namespace CamelotFramework
  9. {
  10. template<class T>
  11. class VertexElemIter
  12. {
  13. public:
  14. VertexElemIter()
  15. :mData(nullptr), mEnd(nullptr), mByteStride(0), mNumElements(0)
  16. {
  17. }
  18. VertexElemIter(UINT8* data, UINT32 byteStride, UINT32 numElements)
  19. :mData(data), mByteStride(byteStride), mNumElements(numElements)
  20. {
  21. mEnd = mData + byteStride * numElements;
  22. }
  23. void addValue(T& value)
  24. {
  25. setValue(value);
  26. moveNext();
  27. }
  28. void setValue(T& value)
  29. {
  30. memcpy(mData, &value, sizeof(T));
  31. }
  32. T& getValue()
  33. {
  34. return *((T*)mData);
  35. }
  36. void moveNext()
  37. {
  38. #ifdef CM_DEBUG_MODE
  39. if(mData >= mEnd)
  40. {
  41. CM_EXCEPT(InternalErrorException, "Vertex element iterator out of buffer bounds.");
  42. }
  43. #endif
  44. mData += mByteStride;
  45. }
  46. UINT32 getNumElements() const { return mNumElements; }
  47. private:
  48. UINT8* mData;
  49. UINT8* mEnd;
  50. UINT32 mByteStride;
  51. UINT32 mNumElements;
  52. };
  53. class CM_EXPORT MeshData : public GpuResourceData
  54. {
  55. public:
  56. struct IndexElementData
  57. {
  58. IndexElementData()
  59. :numIndices(0), subMesh(0), elementSize(0), drawOp(DOT_TRIANGLE_LIST)
  60. { }
  61. UINT32 numIndices;
  62. UINT32 elementSize;
  63. UINT32 subMesh;
  64. DrawOperationType drawOp;
  65. };
  66. MeshData(UINT32 numVertices, IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT);
  67. ~MeshData();
  68. /**
  69. * @brief Begins the mesh data definition. After this call you may call various add* methods to inform
  70. * the internal buffer which data it will need to hold. Each beginDesc() call needs to be followed with
  71. * an endDesc().
  72. */
  73. void beginDesc();
  74. /**
  75. * @brief Call after you are done defining data to actually allocate the internal buffer. Any previous buffer will be overwritten.
  76. * Must be called after beginDesc().
  77. */
  78. void endDesc();
  79. /**
  80. * @brief Informs the internal buffer that it needs to make room for the specified vertex element. If a vertex
  81. * with same stream and semantics already exists it will just be updated. This must be called between beginDesc and endDesc.
  82. *
  83. * @param type Type of the vertex element. Determines size.
  84. * @param semantic Semantic that allows the engine to connect the data to a shader input slot.
  85. * @param semanticIdx (optional) If there are multiple semantics with the same name, use different index to differentiate between them.
  86. * @param streamIdx (optional) Zero-based index of the stream. Each stream will internally be represented as a single vertex buffer.
  87. */
  88. void addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
  89. /**
  90. * @brief Informs the internal buffer that it needs to make room for an index buffer of the
  91. * specified size. If specified submesh already exists it will just be updated. This
  92. * must be called between beginDesc and endDesc.
  93. *
  94. * @param numIndices Number of indices.
  95. * @param subMesh (optional) Index of the sub-mesh to add/update.
  96. * @param drawOp (optional) Specifies the primitive type contained by the mesh.
  97. */
  98. void addSubMesh(UINT32 numIndices, UINT32 subMesh = 0, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
  99. /**
  100. * @brief Query if we have vertex data for the specified semantic.
  101. */
  102. bool hasElement(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
  103. /**
  104. * @brief Copies data from "data" parameter into the internal buffer for the specified semantic.
  105. *
  106. * @param semantic Semantic that allows the engine to connect the data to a shader input slot.
  107. * @param data Vertex data, containing at least "size" bytes.
  108. * @param size The size of the data. Must be the size of the vertex element type * number of vertices.
  109. * @param semanticIdx (optional) If there are multiple semantics with the same name, use different index to differentiate between them.
  110. * @param streamIdx (optional) Zero-based index of the stream. Each stream will internally be represented as a single vertex buffer.
  111. */
  112. void setVertexData(VertexElementSemantic semantic, UINT8* data, UINT32 size, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
  113. /**
  114. * @brief Returns an iterator you can use for easily retrieving or setting Vector2 vertex elements. This is the preferred
  115. * method of assigning or reading vertex data.
  116. *
  117. * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown.
  118. */
  119. VertexElemIter<Vector2> getVec2DataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
  120. /**
  121. * @brief Returns an iterator you can use for easily retrieving or setting Vector3 vertex elements. This is the preferred
  122. * method of assigning or reading vertex data.
  123. *
  124. * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown.
  125. */
  126. VertexElemIter<Vector3> getVec3DataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
  127. /**
  128. * @brief Returns an iterator you can use for easily retrieving or setting Vector4 vertex elements. This is the preferred
  129. * method of assigning or reading vertex data.
  130. *
  131. * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown.
  132. */
  133. VertexElemIter<Vector4> getVec4DataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
  134. /**
  135. * @brief Returns an iterator you can use for easily retrieving or setting DWORD vertex elements. This is the preferred
  136. * method of assigning or reading vertex data.
  137. *
  138. * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown.
  139. */
  140. VertexElemIter<UINT32> getDWORDDataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
  141. /**
  142. * @brief Creates a new vertex declaration based on set vertex elements.
  143. */
  144. VertexDeclarationPtr createDeclaration() const;
  145. UINT32 getNumSubmeshes() const { return (UINT32)mSubMeshes.size(); }
  146. UINT32 getNumVertices() const { return mNumVertices; }
  147. UINT32 getNumIndices(UINT32 subMesh) const;
  148. UINT32 getNumIndices() const;
  149. DrawOperationType getDrawOp(UINT32 subMesh) const;
  150. UINT16* getIndices16(UINT32 subMesh = 0) const;
  151. UINT32* getIndices32(UINT32 subMesh = 0) const;
  152. UINT32 getIndexElementSize() const;
  153. IndexBuffer::IndexType getIndexType() const { return mIndexType; }
  154. /**
  155. * @brief Returns the pointer to the first element of the specified type. If you want to
  156. * iterate over all elements you need to call getVertexStride() to get the number
  157. * of bytes you need to advance between each element.
  158. *
  159. * @param semantic Semantic that allows the engine to connect the data to a shader input slot.
  160. * @param semanticIdx (optional) If there are multiple semantics with the same name, use different index to differentiate between them.
  161. * @param streamIdx (optional) Zero-based index of the stream. Each stream will internally be represented as a single vertex buffer.
  162. *
  163. * @return null if it fails, else the element data.
  164. */
  165. UINT8* getElementData(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
  166. UINT32 getElementSize(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
  167. UINT32 getElementOffset(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
  168. UINT32 getVertexStride(UINT32 streamIdx = 0) const;
  169. static MeshDataPtr combine(const Vector<MeshDataPtr>::type& elements);
  170. protected:
  171. UINT32 getInternalBufferSize();
  172. private:
  173. friend class Mesh; // To avoid polluting the public interface with a bunch of nearly useless methods for outside world
  174. UINT32 mDescBuilding;
  175. UINT8* mData;
  176. UINT32 mNumVertices;
  177. IndexBuffer::IndexType mIndexType;
  178. Vector<IndexElementData>::type mSubMeshes;
  179. Vector<VertexElement>::type mVertexElements;
  180. UINT32 getMaxStreamIdx() const;
  181. bool hasStream(UINT32 streamIdx) const;
  182. UINT8* getIndexData() const { return getData(); }
  183. UINT8* getStreamData(UINT32 streamIdx) const;
  184. UINT32 getIndexBufferOffset(UINT32 subMesh) const;
  185. UINT32 getStreamOffset(UINT32 streamIdx = 0) const;
  186. UINT32 getIndexBufferSize() const { return getIndexBufferOffset(getNumSubmeshes()); }
  187. UINT32 getStreamSize(UINT32 streamIdx) const;
  188. UINT32 getStreamSize() const;
  189. void getDataForIterator(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx, UINT8*& data, UINT32& stride) const;
  190. void clearIfItExists(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx);
  191. /************************************************************************/
  192. /* SERIALIZATION */
  193. /************************************************************************/
  194. private:
  195. MeshData() {} // Serialization only
  196. public:
  197. friend class MeshDataRTTI;
  198. static RTTITypeBase* getRTTIStatic();
  199. virtual RTTITypeBase* getRTTI() const;
  200. };
  201. }