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