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#include "Renderer/BsRendererMeshData.h"
4#include "RenderAPI/BsVertexDataDesc.h"
5#include "Math/BsVector2.h"
6#include "Math/BsVector3.h"
7#include "Math/BsVector4.h"
8#include "Image/BsColor.h"
9#include "Image/BsPixelUtil.h"
10#include "Renderer/BsRendererManager.h"
11#include "Renderer/BsRenderer.h"
12#include "Mesh/BsMeshUtility.h"
13
14namespace bs
15{
16 RendererMeshData::RendererMeshData(UINT32 numVertices, UINT32 numIndices, VertexLayout layout, IndexType indexType)
17 {
18 SPtr<VertexDataDesc> vertexDesc = vertexLayoutVertexDesc(layout);
19
20 mMeshData = bs_shared_ptr_new<MeshData>(numVertices, numIndices, vertexDesc, indexType);
21 }
22
23 RendererMeshData::RendererMeshData(const SPtr<MeshData>& meshData)
24 :mMeshData(meshData)
25 {
26
27 }
28
29 void RendererMeshData::getPositions(Vector3* buffer, UINT32 size)
30 {
31 if (!mMeshData->getVertexDesc()->hasElement(VES_POSITION))
32 return;
33
34 UINT32 numElements = mMeshData->getNumVertices();
35 assert(numElements * sizeof(Vector3) == size);
36
37 mMeshData->getVertexData(VES_POSITION, buffer, size);
38 }
39
40 void RendererMeshData::setPositions(Vector3* buffer, UINT32 size)
41 {
42 if (!mMeshData->getVertexDesc()->hasElement(VES_POSITION))
43 return;
44
45 UINT32 numElements = mMeshData->getNumVertices();
46 assert(numElements * sizeof(Vector3) == size);
47
48 mMeshData->setVertexData(VES_POSITION, buffer, size);
49 }
50
51 void RendererMeshData::getNormals(Vector3* buffer, UINT32 size)
52 {
53 if (!mMeshData->getVertexDesc()->hasElement(VES_NORMAL))
54 return;
55
56 UINT32 numElements = mMeshData->getNumVertices();
57 assert(numElements * sizeof(Vector3) == size);
58
59 UINT8* normalSrc = mMeshData->getElementData(VES_NORMAL);
60 UINT32 stride = mMeshData->getVertexDesc()->getVertexStride(0);
61
62 MeshUtility::unpackNormals(normalSrc, buffer, numElements, stride);
63 }
64
65 void RendererMeshData::setNormals(Vector3* buffer, UINT32 size)
66 {
67 if (!mMeshData->getVertexDesc()->hasElement(VES_NORMAL))
68 return;
69
70 UINT32 numElements = mMeshData->getNumVertices();
71 assert(numElements * sizeof(Vector3) == size);
72
73 UINT8* normalDst = mMeshData->getElementData(VES_NORMAL);
74 UINT32 stride = mMeshData->getVertexDesc()->getVertexStride(0);
75
76 MeshUtility::packNormals(buffer, normalDst, numElements, sizeof(Vector3), stride);
77 }
78
79 void RendererMeshData::getTangents(Vector4* buffer, UINT32 size)
80 {
81 if (!mMeshData->getVertexDesc()->hasElement(VES_TANGENT))
82 return;
83
84 UINT32 numElements = mMeshData->getNumVertices();
85 assert(numElements * sizeof(Vector4) == size);
86
87 UINT8* tangentSrc = mMeshData->getElementData(VES_TANGENT);
88 UINT32 stride = mMeshData->getVertexDesc()->getVertexStride(0);
89
90 MeshUtility::unpackNormals(tangentSrc, buffer, numElements, stride);
91 }
92
93 void RendererMeshData::setTangents(Vector4* buffer, UINT32 size)
94 {
95 if (!mMeshData->getVertexDesc()->hasElement(VES_TANGENT))
96 return;
97
98 UINT32 numElements = mMeshData->getNumVertices();
99 assert(numElements * sizeof(Vector4) == size);
100
101 UINT8* tangentDst = mMeshData->getElementData(VES_TANGENT);
102 UINT32 stride = mMeshData->getVertexDesc()->getVertexStride(0);
103
104 MeshUtility::packNormals(buffer, tangentDst, numElements, sizeof(Vector4), stride);
105 }
106
107 void RendererMeshData::getColors(Color* buffer, UINT32 size)
108 {
109 if (!mMeshData->getVertexDesc()->hasElement(VES_COLOR))
110 return;
111
112 UINT32 numElements = mMeshData->getNumVertices();
113 assert(numElements * sizeof(Vector4) == size);
114
115 UINT8* colorSrc = mMeshData->getElementData(VES_COLOR);
116 UINT32 stride = mMeshData->getVertexDesc()->getVertexStride(0);
117
118 Color* colorDst = buffer;
119 for (UINT32 i = 0; i < numElements; i++)
120 {
121 PixelUtil::unpackColor(colorDst, PF_RGBA8, (void*)colorSrc);
122
123 colorSrc += stride;
124 colorDst++;
125 }
126 }
127
128 void RendererMeshData::setColors(Color* buffer, UINT32 size)
129 {
130 if (!mMeshData->getVertexDesc()->hasElement(VES_COLOR))
131 return;
132
133 UINT32 numElements = mMeshData->getNumVertices();
134 assert(numElements * sizeof(Vector4) == size);
135
136 UINT8* colorDst = mMeshData->getElementData(VES_COLOR);
137 UINT32 stride = mMeshData->getVertexDesc()->getVertexStride(0);
138
139 Color* colorSrc = buffer;
140 for (UINT32 i = 0; i < numElements; i++)
141 {
142 PixelUtil::packColor(*colorSrc, PF_RGBA8, (void*)colorDst);
143
144 colorSrc++;
145 colorDst += stride;
146 }
147 }
148
149 void RendererMeshData::setColors(UINT32* buffer, UINT32 size)
150 {
151 if (!mMeshData->getVertexDesc()->hasElement(VES_COLOR))
152 return;
153
154 UINT32 numElements = mMeshData->getNumVertices();
155 assert(numElements * sizeof(UINT32) == size);
156
157 mMeshData->setVertexData(VES_COLOR, buffer, size);
158 }
159
160 void RendererMeshData::getUV0(Vector2* buffer, UINT32 size)
161 {
162 if (!mMeshData->getVertexDesc()->hasElement(VES_TEXCOORD, 0))
163 return;
164
165 UINT32 numElements = mMeshData->getNumVertices();
166 assert(numElements * sizeof(Vector2) == size);
167
168 mMeshData->getVertexData(VES_TEXCOORD, buffer, size, 0);
169 }
170
171 void RendererMeshData::setUV0(Vector2* buffer, UINT32 size)
172 {
173 if (!mMeshData->getVertexDesc()->hasElement(VES_TEXCOORD, 0))
174 return;
175
176 UINT32 numElements = mMeshData->getNumVertices();
177 assert(numElements * sizeof(Vector2) == size);
178
179 mMeshData->setVertexData(VES_TEXCOORD, buffer, size, 0);
180 }
181
182 void RendererMeshData::getUV1(Vector2* buffer, UINT32 size)
183 {
184 if (!mMeshData->getVertexDesc()->hasElement(VES_TEXCOORD, 1))
185 return;
186
187 UINT32 numElements = mMeshData->getNumVertices();
188 assert(numElements * sizeof(Vector2) == size);
189
190 mMeshData->getVertexData(VES_TEXCOORD, buffer, size, 1);
191 }
192
193 void RendererMeshData::setUV1(Vector2* buffer, UINT32 size)
194 {
195 if (!mMeshData->getVertexDesc()->hasElement(VES_TEXCOORD, 1))
196 return;
197
198 UINT32 numElements = mMeshData->getNumVertices();
199 assert(numElements * sizeof(Vector2) == size);
200
201 mMeshData->setVertexData(VES_TEXCOORD, buffer, size, 1);
202 }
203
204 void RendererMeshData::getBoneWeights(BoneWeight* buffer, UINT32 size)
205 {
206 SPtr<VertexDataDesc> vertexDesc = mMeshData->getVertexDesc();
207
208 if (!vertexDesc->hasElement(VES_BLEND_WEIGHTS) ||
209 !vertexDesc->hasElement(VES_BLEND_INDICES))
210 return;
211
212 UINT32 numElements = mMeshData->getNumVertices();
213 assert(numElements * sizeof(BoneWeight) == size);
214
215 UINT8* weightPtr = mMeshData->getElementData(VES_BLEND_WEIGHTS);
216 UINT8* indexPtr = mMeshData->getElementData(VES_BLEND_INDICES);
217
218 UINT32 stride = vertexDesc->getVertexStride(0);
219
220 BoneWeight* weightDst = buffer;
221 for (UINT32 i = 0; i < numElements; i++)
222 {
223 UINT8* indices = indexPtr;
224 float* weights = (float*)weightPtr;
225
226 weightDst->index0 = indices[0];
227 weightDst->index1 = indices[1];
228 weightDst->index2 = indices[2];
229 weightDst->index3 = indices[3];
230
231 weightDst->weight0 = weights[0];
232 weightDst->weight1 = weights[1];
233 weightDst->weight2 = weights[2];
234 weightDst->weight3 = weights[3];
235
236 weightDst++;
237 indexPtr += stride;
238 weightPtr += stride;
239 }
240 }
241
242 void RendererMeshData::setBoneWeights(BoneWeight* buffer, UINT32 size)
243 {
244 SPtr<VertexDataDesc> vertexDesc = mMeshData->getVertexDesc();
245
246 if (!vertexDesc->hasElement(VES_BLEND_WEIGHTS) ||
247 !vertexDesc->hasElement(VES_BLEND_INDICES))
248 return;
249
250 UINT32 numElements = mMeshData->getNumVertices();
251 assert(numElements * sizeof(BoneWeight) == size);
252
253 UINT8* weightPtr = mMeshData->getElementData(VES_BLEND_WEIGHTS);
254 UINT8* indexPtr = mMeshData->getElementData(VES_BLEND_INDICES);
255
256 UINT32 stride = vertexDesc->getVertexStride(0);
257
258 BoneWeight* weightSrc = buffer;
259 for (UINT32 i = 0; i < numElements; i++)
260 {
261 UINT8* indices = indexPtr;
262 float* weights = (float*)weightPtr;
263
264 indices[0] = weightSrc->index0;
265 indices[1] = weightSrc->index1;
266 indices[2] = weightSrc->index2;
267 indices[3] = weightSrc->index3;
268
269 weights[0] = weightSrc->weight0;
270 weights[1] = weightSrc->weight1;
271 weights[2] = weightSrc->weight2;
272 weights[3] = weightSrc->weight3;
273
274 weightSrc++;
275 indexPtr += stride;
276 weightPtr += stride;
277 }
278 }
279
280 void RendererMeshData::getIndices(UINT32* buffer, UINT32 size)
281 {
282 UINT32 indexSize = mMeshData->getIndexElementSize();
283 UINT32 numIndices = mMeshData->getNumIndices();
284
285 assert(numIndices * indexSize == size);
286
287 if (mMeshData->getIndexType() == IT_16BIT)
288 {
289 UINT16* src = mMeshData->getIndices16();
290 UINT32* dest = buffer;
291
292 for (UINT32 i = 0; i < numIndices; i++)
293 {
294 *dest = *src;
295
296 src++;
297 dest++;
298 }
299 }
300 else
301 {
302 memcpy(buffer, mMeshData->getIndices32(), size);
303 }
304 }
305
306 void RendererMeshData::setIndices(UINT32* buffer, UINT32 size)
307 {
308 UINT32 indexSize = mMeshData->getIndexElementSize();
309 UINT32 numIndices = mMeshData->getNumIndices();
310
311 assert(numIndices * indexSize == size);
312
313 if (mMeshData->getIndexType() == IT_16BIT)
314 {
315 UINT16* dest = mMeshData->getIndices16();
316 UINT32* src = buffer;
317
318 for (UINT32 i = 0; i < numIndices; i++)
319 {
320 *dest = *src;
321
322 src++;
323 dest++;
324 }
325 }
326 else
327 {
328 memcpy(mMeshData->getIndices32(), buffer, size);
329 }
330 }
331
332 SPtr<RendererMeshData> RendererMeshData::create(UINT32 numVertices, UINT32 numIndices, VertexLayout layout, IndexType indexType)
333 {
334 return RendererManager::instance().getActive()->_createMeshData(numVertices, numIndices, layout, indexType);
335 }
336
337 SPtr<RendererMeshData> RendererMeshData::create(const SPtr<MeshData>& meshData)
338 {
339 return RendererManager::instance().getActive()->_createMeshData(meshData);
340 }
341
342 SPtr<VertexDataDesc> RendererMeshData::vertexLayoutVertexDesc(VertexLayout type)
343 {
344 SPtr<VertexDataDesc> vertexDesc = VertexDataDesc::create();
345
346 INT32 intType = (INT32)type;
347
348 if (intType == 0)
349 type = VertexLayout::Position;
350
351 if ((intType & (INT32)VertexLayout::Position) != 0)
352 vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
353
354 if ((intType & (INT32)VertexLayout::Normal) != 0)
355 vertexDesc->addVertElem(VET_UBYTE4_NORM, VES_NORMAL);
356
357 if ((intType & (INT32)VertexLayout::Tangent) != 0)
358 vertexDesc->addVertElem(VET_UBYTE4_NORM, VES_TANGENT);
359
360 if ((intType & (INT32)VertexLayout::UV0) != 0)
361 vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD, 0);
362
363 if ((intType & (INT32)VertexLayout::UV1) != 0)
364 vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD, 1);
365
366 if ((intType & (INT32)VertexLayout::Color) != 0)
367 vertexDesc->addVertElem(VET_COLOR, VES_COLOR);
368
369 if ((intType & (INT32)VertexLayout::BoneWeights) != 0)
370 {
371 vertexDesc->addVertElem(VET_UBYTE4, VES_BLEND_INDICES);
372 vertexDesc->addVertElem(VET_FLOAT4, VES_BLEND_WEIGHTS);
373 }
374
375 return vertexDesc;
376 }
377
378 SPtr<MeshData> RendererMeshData::convert(const SPtr<MeshData>& meshData)
379 {
380 // Note: Only converting between packed normals/tangents for now
381 SPtr<VertexDataDesc> vertexDesc = meshData->getVertexDesc();
382
383 UINT32 numVertices = meshData->getNumVertices();
384 UINT32 numIndices = meshData->getNumIndices();
385 UINT32 inputStride = vertexDesc->getVertexStride();
386
387 INT32 type = 0;
388
389 const VertexElement* posElem = vertexDesc->getElement(VES_POSITION);
390 if (posElem != nullptr && posElem->getType() == VET_FLOAT3)
391 type = (INT32)VertexLayout::Position;
392
393 const VertexElement* normalElem = vertexDesc->getElement(VES_NORMAL);
394 bool packNormals = false;
395 if(normalElem != nullptr)
396 {
397 if (normalElem->getType() == VET_FLOAT3)
398 {
399 packNormals = true;
400 type |= (INT32)VertexLayout::Normal;
401 }
402 else if(normalElem->getType() == VET_UBYTE4_NORM)
403 type |= (INT32)VertexLayout::Normal;
404 }
405
406 const VertexElement* tanElem = vertexDesc->getElement(VES_TANGENT);
407 bool packTangents = false;
408 if (tanElem != nullptr)
409 {
410 if (tanElem->getType() == VET_FLOAT4)
411 {
412 packTangents = true;
413 type |= (INT32)VertexLayout::Tangent;
414 }
415 else if (tanElem->getType() == VET_UBYTE4_NORM)
416 type |= (INT32)VertexLayout::Tangent;
417 }
418
419 const VertexElement* uv0Elem = vertexDesc->getElement(VES_TEXCOORD, 0);
420 if (uv0Elem != nullptr && uv0Elem->getType() == VET_FLOAT2)
421 type |= (INT32)VertexLayout::UV0;
422
423 const VertexElement* uv1Elem = vertexDesc->getElement(VES_TEXCOORD, 1);
424 if (uv1Elem != nullptr && uv1Elem->getType() == VET_FLOAT2)
425 type |= (INT32)VertexLayout::UV1;
426
427 const VertexElement* colorElem = vertexDesc->getElement(VES_COLOR);
428 if (colorElem != nullptr && colorElem->getType() == VET_COLOR)
429 type |= (INT32)VertexLayout::Color;
430
431 const VertexElement* blendIndicesElem = vertexDesc->getElement(VES_BLEND_INDICES);
432 const VertexElement* blendWeightsElem = vertexDesc->getElement(VES_BLEND_WEIGHTS);
433 if (blendIndicesElem != nullptr && blendIndicesElem->getType() == VET_UBYTE4 &&
434 blendWeightsElem != nullptr && blendWeightsElem->getType() == VET_FLOAT4)
435 type |= (INT32)VertexLayout::BoneWeights;
436
437 SPtr<RendererMeshData> rendererMeshData = create(numVertices, numIndices, (VertexLayout)type,
438 meshData->getIndexType());
439
440 SPtr<MeshData> output = rendererMeshData->mMeshData;
441 SPtr<VertexDataDesc> outputVertexDesc = output->getVertexDesc();
442 UINT32 outputStride = outputVertexDesc->getVertexStride();
443
444 if((type & (INT32)VertexLayout::Position) != 0)
445 {
446 UINT8* inData = meshData->getElementData(VES_POSITION);
447 UINT8* outData = output->getElementData(VES_POSITION);
448 for(UINT32 i = 0; i < numVertices; i++)
449 memcpy(outData + i * outputStride, inData + i * inputStride, sizeof(Vector3));
450 }
451
452 if ((type & (INT32)VertexLayout::Normal) != 0)
453 {
454 UINT8* inData = meshData->getElementData(VES_NORMAL);
455 UINT8* outData = output->getElementData(VES_NORMAL);
456
457 if (packNormals)
458 MeshUtility::packNormals((Vector3*)inData, outData, numVertices, inputStride, outputStride);
459 else
460 {
461 for (UINT32 i = 0; i < numVertices; i++)
462 memcpy(outData + i * outputStride, inData + i * inputStride, sizeof(UINT32));
463 }
464 }
465
466 if ((type & (INT32)VertexLayout::Tangent) != 0)
467 {
468 UINT8* inData = meshData->getElementData(VES_TANGENT);
469 UINT8* outData = output->getElementData(VES_TANGENT);
470
471 if (packTangents)
472 MeshUtility::packNormals((Vector4*)inData, outData, numVertices, inputStride, outputStride);
473 else
474 {
475 for (UINT32 i = 0; i < numVertices; i++)
476 memcpy(outData + i * outputStride, inData + i * inputStride, sizeof(UINT32));
477 }
478 }
479
480 if ((type & (INT32)VertexLayout::UV0) != 0)
481 {
482 UINT8* inData = meshData->getElementData(VES_TEXCOORD, 0);
483 UINT8* outData = output->getElementData(VES_TEXCOORD, 0);
484 for (UINT32 i = 0; i < numVertices; i++)
485 memcpy(outData + i * outputStride, inData + i * inputStride, sizeof(Vector2));
486 }
487
488 if ((type & (INT32)VertexLayout::UV1) != 0)
489 {
490 UINT8* inData = meshData->getElementData(VES_TEXCOORD, 1);
491 UINT8* outData = output->getElementData(VES_TEXCOORD, 1);
492 for (UINT32 i = 0; i < numVertices; i++)
493 memcpy(outData + i * outputStride, inData + i * inputStride, sizeof(Vector2));
494 }
495
496 if ((type & (INT32)VertexLayout::Color) != 0)
497 {
498 UINT8* inData = meshData->getElementData(VES_COLOR, 0);
499 UINT8* outData = output->getElementData(VES_COLOR, 0);
500 for (UINT32 i = 0; i < numVertices; i++)
501 memcpy(outData + i * outputStride, inData + i * inputStride, sizeof(UINT32));
502 }
503
504 if ((type & (INT32)VertexLayout::BoneWeights) != 0)
505 {
506 {
507 UINT8* inData = meshData->getElementData(VES_BLEND_INDICES, 0);
508 UINT8* outData = output->getElementData(VES_BLEND_INDICES, 0);
509 for (UINT32 i = 0; i < numVertices; i++)
510 memcpy(outData + i * outputStride, inData + i * inputStride, sizeof(UINT32));
511 }
512
513 {
514 UINT8* inData = meshData->getElementData(VES_BLEND_WEIGHTS, 0);
515 UINT8* outData = output->getElementData(VES_BLEND_WEIGHTS, 0);
516 for (UINT32 i = 0; i < numVertices; i++)
517 memcpy(outData + i * outputStride, inData + i * inputStride, sizeof(Vector4));
518 }
519 }
520
521 if(meshData->getIndexType() == IT_32BIT)
522 {
523 UINT32* dst = output->getIndices32();
524 memcpy(dst, meshData->getIndices32(), numIndices * sizeof(UINT32));
525 }
526 else
527 {
528 UINT16* dst = output->getIndices16();
529 memcpy(dst, meshData->getIndices16(), numIndices * sizeof(UINT16));
530 }
531
532 return output;
533 }
534}