1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #pragma once |
4 | |
5 | #include "BsCorePrerequisites.h" |
6 | #include "Resources/BsGpuResourceData.h" |
7 | #include "RenderAPI/BsVertexBuffer.h" |
8 | #include "RenderAPI/BsIndexBuffer.h" |
9 | #include "RenderAPI/BsVertexDeclaration.h" |
10 | #include "RenderAPI/BsSubMesh.h" |
11 | #include "Math/BsBounds.h" |
12 | |
13 | namespace bs |
14 | { |
15 | /** @addtogroup Resources |
16 | * @{ |
17 | */ |
18 | |
19 | /** Iterator that allows you to easily populate or read vertex elements in MeshData. */ |
20 | template<class T> |
21 | class VertexElemIter |
22 | { |
23 | public: |
24 | VertexElemIter() |
25 | :mData(nullptr), mEnd(nullptr), mByteStride(0), mNumElements(0) |
26 | { |
27 | |
28 | } |
29 | |
30 | VertexElemIter(UINT8* data, UINT32 byteStride, UINT32 numElements) |
31 | :mData(data), mByteStride(byteStride), mNumElements(numElements) |
32 | { |
33 | mEnd = mData + byteStride * numElements; |
34 | } |
35 | |
36 | /** |
37 | * Adds a new value to the iterators current position and advances the iterator. Returns true if there is more room |
38 | * in the container. |
39 | */ |
40 | bool addValue(const T& value) |
41 | { |
42 | setValue(value); |
43 | return moveNext(); |
44 | } |
45 | |
46 | /** Sets a new value at the iterators current position. */ |
47 | void setValue(const T& value) |
48 | { |
49 | memcpy(mData, &value, sizeof(T)); |
50 | } |
51 | |
52 | /** Returns the value at the iterators current position. */ |
53 | T& getValue() |
54 | { |
55 | return *((T*)mData); |
56 | } |
57 | |
58 | /** Moves the iterator to the next position. Returns true if there are more elements. */ |
59 | bool moveNext() |
60 | { |
61 | #ifdef BS_DEBUG_MODE |
62 | if(mData >= mEnd) |
63 | { |
64 | BS_EXCEPT(InternalErrorException, "Vertex element iterator out of buffer bounds." ); |
65 | } |
66 | #endif |
67 | |
68 | mData += mByteStride; |
69 | |
70 | return mData <= mEnd; |
71 | } |
72 | |
73 | /** Returns the number of elements this iterator can iterate over. */ |
74 | UINT32 getNumElements() const { return mNumElements; } |
75 | |
76 | private: |
77 | UINT8* mData; |
78 | UINT8* mEnd; |
79 | UINT32 mByteStride; |
80 | UINT32 mNumElements; |
81 | }; |
82 | |
83 | /** Contains per-vertex bone weights and indexes used for skinning, for up to four bones. */ |
84 | struct BS_SCRIPT_EXPORT(pl:true,m:Utility) BoneWeight |
85 | { |
86 | int index0; |
87 | int index1; |
88 | int index2; |
89 | int index3; |
90 | |
91 | float weight0; |
92 | float weight1; |
93 | float weight2; |
94 | float weight3; |
95 | }; |
96 | |
97 | /** Contains mesh vertex and index data used for initializing, updating and reading mesh data from Mesh. */ |
98 | class BS_CORE_EXPORT MeshData : public GpuResourceData |
99 | { |
100 | public: |
101 | /** |
102 | * Constructs a new object that can hold number of vertices described by the provided vertex data description. As |
103 | * well as a number of indices of the provided type. |
104 | */ |
105 | MeshData(UINT32 numVertices, UINT32 numIndexes, const SPtr<VertexDataDesc>& vertexData, IndexType indexType = IT_32BIT); |
106 | ~MeshData(); |
107 | |
108 | /** |
109 | * Copies data from @p data parameter into the internal buffer for the specified semantic. |
110 | * |
111 | * @param[in] semantic Semantic that allows the engine to connect the data to a shader input slot. |
112 | * @param[in] data Vertex data, containing at least @p size bytes. |
113 | * @param[in] size The size of the data. Must be the size of the vertex element type * number of |
114 | * vertices. |
115 | * @param[in] semanticIdx (optional) If there are multiple semantics with the same name, use different index |
116 | * to differentiate between them. |
117 | * @param[in] streamIdx (optional) Zero-based index of the stream. Each stream will internally be |
118 | * represented as a single vertex buffer. |
119 | */ |
120 | void setVertexData(VertexElementSemantic semantic, void* data, UINT32 size, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); |
121 | |
122 | /** |
123 | * Copies data from the internal buffer to the pre-allocated buffer for the specified semantic. |
124 | * |
125 | * @param[in] semantic Semantic that allows the engine to connect the data to a shader input slot. |
126 | * @param[in] data Buffer that will receive vertex data, of at least @p size bytes. |
127 | * @param[in] size The size of the data. Must be the size of the vertex element type * number of |
128 | * vertices. |
129 | * @param[in] semanticIdx (optional) If there are multiple semantics with the same name, use different index |
130 | * to differentiate between them. |
131 | * @param[in] streamIdx (optional) Zero-based index of the stream. Each stream will internally be |
132 | * represented as a single vertex buffer. |
133 | */ |
134 | void getVertexData(VertexElementSemantic semantic, void* data, UINT32 size, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); |
135 | |
136 | /** |
137 | * Returns an iterator you can use for easily retrieving or setting Vector2 vertex elements. This is the preferred |
138 | * method of assigning or reading vertex data. |
139 | * |
140 | * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown. |
141 | */ |
142 | VertexElemIter<Vector2> getVec2DataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); |
143 | |
144 | /** |
145 | * Returns an iterator you can use for easily retrieving or setting Vector3 vertex elements. This is the preferred |
146 | * method of assigning or reading vertex data. |
147 | * |
148 | * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown. |
149 | */ |
150 | VertexElemIter<Vector3> getVec3DataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); |
151 | |
152 | /** |
153 | * Returns an iterator you can use for easily retrieving or setting Vector4 vertex elements. This is the preferred |
154 | * method of assigning or reading vertex data. |
155 | * |
156 | * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown. |
157 | */ |
158 | VertexElemIter<Vector4> getVec4DataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); |
159 | |
160 | /** |
161 | * Returns an iterator you can use for easily retrieving or setting DWORD vertex elements. This is the preferred |
162 | * method of assigning or reading vertex data. |
163 | * |
164 | * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown. |
165 | */ |
166 | VertexElemIter<UINT32> getDWORDDataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); |
167 | |
168 | /** Returns the total number of vertices this object can hold. */ |
169 | UINT32 getNumVertices() const { return mNumVertices; } |
170 | |
171 | /** Returns the total number of indices this object can hold. */ |
172 | UINT32 getNumIndices() const; |
173 | |
174 | /** Returns a 16-bit pointer to the start of the internal index buffer. */ |
175 | UINT16* getIndices16() const; |
176 | |
177 | /** Returns a 32-bit pointer to the start of the internal index buffer. */ |
178 | UINT32* getIndices32() const; |
179 | |
180 | /** Returns the size of an index element in bytes. */ |
181 | UINT32 getIndexElementSize() const; |
182 | |
183 | /** Returns the type of an index element. */ |
184 | IndexType getIndexType() const { return mIndexType; } |
185 | |
186 | /** |
187 | * Returns the pointer to the first element of the specified type. If you want to iterate over all elements you |
188 | * need to call getVertexStride() to get the number of bytes you need to advance between each element. |
189 | * |
190 | * @param[in] semantic Semantic that allows the engine to connect the data to a shader input slot. |
191 | * @param[in] semanticIdx (optional) If there are multiple semantics with the same name, use different index |
192 | * to differentiate between them. |
193 | * @param[in] streamIdx (optional) Zero-based index of the stream. Each stream will internally be |
194 | * represented as a single vertex buffer. |
195 | * @return null if it fails, else the element data. |
196 | */ |
197 | UINT8* getElementData(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const; |
198 | |
199 | /** |
200 | * Returns an offset into the internal buffer where this element with the provided semantic starts. Offset is |
201 | * provided in number of bytes. |
202 | * |
203 | * @param[in] semantic Semantic that allows the engine to connect the data to a shader input slot. |
204 | * @param[in] semanticIdx (optional) If there are multiple semantics with the same name, use different index |
205 | * to differentiate between them. |
206 | * @param[in] streamIdx (optional) Zero-based index of the stream. Each stream will internally be |
207 | * represented as a single vertex buffer. |
208 | */ |
209 | UINT32 getElementOffset(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const; |
210 | |
211 | /** Returns a pointer to the start of the index buffer. */ |
212 | UINT8* getIndexData() const { return getData(); } |
213 | |
214 | /** Returns a pointer to the start of the specified vertex stream. */ |
215 | UINT8* getStreamData(UINT32 streamIdx) const; |
216 | |
217 | /** Returns the size of the specified stream in bytes. */ |
218 | UINT32 getStreamSize(UINT32 streamIdx) const; |
219 | |
220 | /** Returns the size of all the streams in bytes. */ |
221 | UINT32 getStreamSize() const; |
222 | |
223 | /** Returns an object that describes data contained in a single vertex. */ |
224 | const SPtr<VertexDataDesc>& getVertexDesc() const { return mVertexData; } |
225 | |
226 | /** Return the size (in bytes) of the entire buffer. */ |
227 | UINT32 getSize() const { return getInternalBufferSize(); } |
228 | |
229 | /** Calculates the bounds of all vertices stored in the internal buffer. */ |
230 | Bounds calculateBounds() const; |
231 | |
232 | /** |
233 | * Combines a number of submeshes and their mesh data into one large mesh data buffer. |
234 | * |
235 | * @param[in] elements Data containing vertices and indices referenced by the submeshes. Number of elements |
236 | * must be the same as number of submeshes. |
237 | * @param[in] allSubMeshes Submeshes representing vertex and index range to take from mesh data and combine. |
238 | * Number of submeshes must match the number of provided MeshData elements. |
239 | * @param[out] subMeshes Outputs all combined sub-meshes with their new index and vertex offsets referencing |
240 | * the newly created MeshData. |
241 | * @return Combined mesh data containing all vertices and indexes references by the provided |
242 | * sub-meshes. |
243 | */ |
244 | static SPtr<MeshData> combine(const Vector<SPtr<MeshData>>& elements, const Vector<Vector<SubMesh>>& allSubMeshes, |
245 | Vector<SubMesh>& subMeshes); |
246 | |
247 | /** |
248 | * Constructs a new object that can hold number of vertices described by the provided vertex data description. As |
249 | * well as a number of indices of the provided type. |
250 | */ |
251 | static SPtr<MeshData> create(UINT32 numVertices, UINT32 numIndexes, const SPtr<VertexDataDesc>& vertexData, |
252 | IndexType indexType = IT_32BIT) |
253 | { |
254 | return bs_shared_ptr_new<MeshData>(numVertices, numIndexes, vertexData, indexType); |
255 | } |
256 | |
257 | protected: |
258 | /** Returns the size of the internal buffer in bytes. */ |
259 | UINT32 getInternalBufferSize() const override; |
260 | |
261 | private: |
262 | /** Returns an offset in bytes to the start of the index buffer from the start of the internal buffer. */ |
263 | UINT32 getIndexBufferOffset() const; |
264 | |
265 | /** Returns an offset in bytes to the start of the stream from the start of the internal buffer. */ |
266 | UINT32 getStreamOffset(UINT32 streamIdx = 0) const; |
267 | |
268 | /** Returns the size of the index buffer in bytes. */ |
269 | UINT32 getIndexBufferSize() const; |
270 | |
271 | /** |
272 | * Returns the data needed for iterating over the requested vertex element. |
273 | * |
274 | * @param[in] semantic Semantic of the element we are looking for. |
275 | * @param[in] semanticIdx If there are multiple semantics with the same name, use different index to |
276 | * differentiate between them. |
277 | * @param[in] streamIdx Zero-based index of the stream the element resides in. |
278 | * @param[out] data Pointer to the start of this elements data. |
279 | * @param[out] stride Number of bytes between vertex elements of this type. |
280 | */ |
281 | void getDataForIterator(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx, UINT8*& data, UINT32& stride) const; |
282 | |
283 | private: |
284 | friend class Mesh; |
285 | friend class ct::Mesh; |
286 | friend class MeshHeap; |
287 | friend class ct::MeshHeap; |
288 | |
289 | UINT32 mDescBuilding; |
290 | |
291 | UINT32 mNumVertices; |
292 | UINT32 mNumIndices; |
293 | IndexType mIndexType; |
294 | |
295 | SPtr<VertexDataDesc> mVertexData; |
296 | |
297 | /************************************************************************/ |
298 | /* SERIALIZATION */ |
299 | /************************************************************************/ |
300 | private: |
301 | MeshData(); // Serialization only |
302 | |
303 | public: |
304 | friend class MeshDataRTTI; |
305 | static RTTITypeBase* getRTTIStatic(); |
306 | virtual RTTITypeBase* getRTTI() const override; |
307 | }; |
308 | |
309 | /** @} */ |
310 | } |