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
13namespace 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}