@@ -207,7 +207,7 @@ namespace asset
207
207
return dst;
208
208
}
209
209
210
- // ! Creates new index buffer with invalid triangles removed.
210
+ // ! Swaps the index buffer for a new index buffer with invalid triangles removed.
211
211
/* *
212
212
Invalid triangle is such consisting of two or more same indices.
213
213
@param _input Input index buffer.
@@ -216,21 +216,149 @@ namespace asset
216
216
*/
217
217
static void filterInvalidTriangles (ICPUMeshBuffer* _input);
218
218
219
- // ! Creates index buffer from input converting it to indices for triangle primitives. Input is assumed to be indices for triangle strip.
219
+ // ! Creates index buffer from input converting it to indices for line list primitives. Input is assumed to be indices for line strip.
220
220
/* *
221
221
@param _input Input index buffer's data.
222
222
@param _idxCount Index count.
223
- @param _idxType Type of indices (16bit or 32bit).
223
+ @param _inIndexType Type of input index buffer data (32bit or 16bit).
224
+ @param _outIndexType Type of output index buffer data (32bit or 16bit).
224
225
*/
225
- static core::smart_refctd_ptr<ICPUBuffer> idxBufferFromTriangleStripsToTriangles (const void * _input, size_t _idxCount, E_INDEX_TYPE _idxType );
226
+ static core::smart_refctd_ptr<ICPUBuffer> idxBufferFromLineStripsToLines (const void * _input, size_t _idxCount, E_INDEX_TYPE _inIndexType, E_INDEX_TYPE _outIndexType );
226
227
227
- // ! Creates index buffer from input converting it to indices for triangle primitives. Input is assumed to be indices for triangle fan .
228
+ // ! Creates index buffer from input converting it to indices for triangle list primitives. Input is assumed to be indices for triangle strip .
228
229
/* *
229
230
@param _input Input index buffer's data.
230
231
@param _idxCount Index count.
231
- @param _idxType Type of indices (16bit or 32bit).
232
+ @param _inIndexType Type of input index buffer data (32bit or 16bit).
233
+ @param _outIndexType Type of output index buffer data (32bit or 16bit).
232
234
*/
233
- static core::smart_refctd_ptr<ICPUBuffer> idxBufferFromTrianglesFanToTriangles (const void * _input, size_t _idxCount, E_INDEX_TYPE _idxType);
235
+ static core::smart_refctd_ptr<ICPUBuffer> idxBufferFromTriangleStripsToTriangles (const void * _input, size_t _idxCount, E_INDEX_TYPE _inIndexType, E_INDEX_TYPE _outIndexType);
236
+
237
+ // ! Creates index buffer from input converting it to indices for triangle list primitives. Input is assumed to be indices for triangle fan.
238
+ /* *
239
+ @param _input Input index buffer's data.
240
+ @param _idxCount Index count.
241
+ @param _inIndexType Type of input index buffer data (32bit or 16bit).
242
+ @param _outIndexType Type of output index buffer data (32bit or 16bit).
243
+ */
244
+ static core::smart_refctd_ptr<ICPUBuffer> idxBufferFromTrianglesFanToTriangles (const void * _input, size_t _idxCount, E_INDEX_TYPE _inIndexType, E_INDEX_TYPE _outIndexType);
245
+
246
+ // ! Creates a 32bit index buffer for a mesh with primitive types changed to list types
247
+ /* *#
248
+ @param _newPrimitiveType
249
+ @param _begin non-const iterator to beginning of meshbuffer range
250
+ @param _end non-const iterator to ending of meshbuffer range
251
+ */
252
+ template <typename Iterator>
253
+ static inline void homogenizePrimitiveTypeAndIndices (Iterator _begin, Iterator _end, const E_PRIMITIVE_TOPOLOGY _newPrimitiveType, const E_INDEX_TYPE outIndexType = EIT_32BIT)
254
+ {
255
+ // analyse
256
+ uint32_t iotaLength = 0u ;
257
+ uint32_t patchVertexCount = 0u ;
258
+ for (auto it=_begin; it!=_end; it++)
259
+ {
260
+ ICPUMeshBuffer* cpumb = *it;
261
+ assert (!cpumb->isADummyObjectForCache ());
262
+ assert (cpumb->isMutable ());
263
+
264
+ const auto & params = cpumb->getPipeline ()->getPrimitiveAssemblyParams ();
265
+ switch (params.primitiveType )
266
+ {
267
+ case EPT_POINT_LIST:
268
+ assert (_newPrimitiveType==EPT_POINT_LIST);
269
+ break ;
270
+ case EPT_LINE_LIST:
271
+ assert (_newPrimitiveType==EPT_LINE_LIST);
272
+ break ;
273
+ case EPT_LINE_STRIP:
274
+ assert (_newPrimitiveType==EPT_LINE_LIST);
275
+ break ;
276
+ case EPT_TRIANGLE_LIST:
277
+ assert (_newPrimitiveType==EPT_TRIANGLE_LIST);
278
+ break ;
279
+ case EPT_TRIANGLE_STRIP:
280
+ assert (_newPrimitiveType==EPT_TRIANGLE_LIST);
281
+ break ;
282
+ case EPT_TRIANGLE_FAN:
283
+ assert (_newPrimitiveType==EPT_TRIANGLE_LIST);
284
+ break ;
285
+ case EPT_PATCH_LIST:
286
+ assert (_newPrimitiveType==EPT_PATCH_LIST);
287
+ if (patchVertexCount)
288
+ assert (params.tessPatchVertCount ==patchVertexCount);
289
+ else
290
+ patchVertexCount = params.tessPatchVertCount ;
291
+ break ;
292
+ default :
293
+ assert (false );
294
+ break ;
295
+ }
296
+
297
+ const bool iota = cpumb->getIndexType ()==EIT_UNKNOWN||!cpumb->getIndexBufferBinding ()->buffer ;
298
+ if (iota)
299
+ iotaLength = core::max (cpumb->getIndexCount (),iotaLength);
300
+ }
301
+ core::smart_refctd_ptr<ICPUBuffer> iotaUint32Buffer;
302
+ if (iotaLength)
303
+ {
304
+ iotaUint32Buffer = core::make_smart_refctd_ptr<ICPUBuffer>(sizeof (uint32_t )*iotaLength);
305
+ auto ptr = reinterpret_cast <uint32_t *>(iotaUint32Buffer->getPointer ());
306
+ std::iota (ptr,ptr+iotaLength,0u );
307
+ }
308
+ // modify
309
+ for (auto it=_begin; it!=_end; it++)
310
+ {
311
+ ICPUMeshBuffer* cpumb = *it;
312
+
313
+ const auto indexType = cpumb->getIndexType ();
314
+ const auto indexCount = cpumb->getIndexCount ();
315
+
316
+ auto & params = cpumb->getPipeline ()->getPrimitiveAssemblyParams ();
317
+ core::smart_refctd_ptr<ICPUBuffer> newIndexBuffer;
318
+
319
+ void * correctlyOffsetIndexBufferPtr;
320
+ const bool iota = indexType==EIT_UNKNOWN||!cpumb->getIndexBufferBinding ()->buffer ;
321
+ if (iota)
322
+ correctlyOffsetIndexBufferPtr = iotaUint32Buffer->getPointer ();
323
+ else
324
+ correctlyOffsetIndexBufferPtr = reinterpret_cast <uint8_t *>(cpumb->getIndexBufferBinding ()->buffer ->getPointer ())+cpumb->getIndexBufferBinding ()->offset ;
325
+ switch (params.primitiveType )
326
+ {
327
+ case EPT_LINE_STRIP:
328
+ assert (_newPrimitiveType==EPT_LINE_LIST);
329
+ newIndexBuffer = idxBufferFromLineStripsToLines (correctlyOffsetIndexBufferPtr,indexCount,iota ? EIT_32BIT:indexType,outIndexType);
330
+ break ;
331
+ case EPT_TRIANGLE_STRIP:
332
+ newIndexBuffer = idxBufferFromTriangleStripsToTriangles (correctlyOffsetIndexBufferPtr,indexCount,iota ? EIT_32BIT:indexType,outIndexType);
333
+ break ;
334
+ case EPT_TRIANGLE_FAN:
335
+ newIndexBuffer = idxBufferFromTrianglesFanToTriangles (correctlyOffsetIndexBufferPtr,indexCount,iota ? EIT_32BIT:indexType,outIndexType);
336
+ break ;
337
+ default : // prim types match
338
+ if (iota)
339
+ newIndexBuffer = core::smart_refctd_ptr (iotaUint32Buffer);
340
+ else if (indexType!=outIndexType)
341
+ {
342
+ newIndexBuffer = core::make_smart_refctd_ptr<ICPUBuffer>(sizeof (uint32_t )*indexCount);
343
+ if (indexType==EIT_16BIT)
344
+ {
345
+ auto inPtr = reinterpret_cast <const uint16_t *>(correctlyOffsetIndexBufferPtr);
346
+ std::copy (inPtr,inPtr+indexCount,reinterpret_cast <uint32_t *>(newIndexBuffer->getPointer ()));
347
+ }
348
+ else
349
+ {
350
+ auto inPtr = reinterpret_cast <const uint32_t *>(correctlyOffsetIndexBufferPtr);
351
+ std::copy (inPtr,inPtr+indexCount,reinterpret_cast <uint16_t *>(newIndexBuffer->getPointer ()));
352
+ }
353
+ }
354
+ break ;
355
+ }
356
+ if (newIndexBuffer)
357
+ cpumb->setIndexBufferBinding ({0ull ,std::move (newIndexBuffer)});
358
+ cpumb->setIndexType (outIndexType);
359
+ params.primitiveType = _newPrimitiveType;
360
+ }
361
+ }
234
362
235
363
// ! Compares two attributes of floating point types in accordance with passed error metric.
236
364
/* *
@@ -317,33 +445,37 @@ namespace asset
317
445
if (!meshbuffer->getPipeline ())
318
446
return false ;
319
447
320
- const E_PRIMITIVE_TOPOLOGY primType = meshbuffer->getPipeline ()->getPrimitiveAssemblyParams ().primitiveType ;
321
-
322
- uint32_t trianglecount;
323
-
448
+ const auto & assemblyParams = meshbuffer->getPipeline ()->getPrimitiveAssemblyParams ();
449
+ const E_PRIMITIVE_TOPOLOGY primType = assemblyParams.primitiveType ;
324
450
switch (primType)
325
451
{
326
- case EPT_POINT_LIST:
327
- trianglecount = meshbuffer->getIndexCount ();
328
- break ;
329
- case EPT_LINE_STRIP:
330
- trianglecount = meshbuffer->getIndexCount () - 1 ;
331
- break ;
332
- case EPT_LINE_LIST:
333
- trianglecount = meshbuffer->getIndexCount () / 2 ;
334
- break ;
335
- case EPT_TRIANGLE_STRIP:
336
- trianglecount = meshbuffer->getIndexCount () - 2 ;
337
- break ;
338
- case EPT_TRIANGLE_FAN:
339
- trianglecount = meshbuffer->getIndexCount () - 2 ;
340
- break ;
341
- case EPT_TRIANGLE_LIST:
342
- trianglecount = meshbuffer->getIndexCount () / 3 ;
343
- break ;
452
+ case EPT_POINT_LIST:
453
+ outCount = meshbuffer->getIndexCount ();
454
+ break ;
455
+ case EPT_LINE_STRIP:
456
+ outCount = meshbuffer->getIndexCount () - 1 ;
457
+ break ;
458
+ case EPT_LINE_LIST:
459
+ outCount = meshbuffer->getIndexCount () / 2 ;
460
+ break ;
461
+ case EPT_TRIANGLE_STRIP:
462
+ outCount = meshbuffer->getIndexCount () - 2 ;
463
+ break ;
464
+ case EPT_TRIANGLE_FAN:
465
+ outCount = meshbuffer->getIndexCount () - 2 ;
466
+ break ;
467
+ case EPT_TRIANGLE_LIST:
468
+ outCount = meshbuffer->getIndexCount () / 3 ;
469
+ break ;
470
+ case EPT_PATCH_LIST:
471
+ outCount = meshbuffer->getIndexCount () / assemblyParams.tessPatchVertCount ;
472
+ break ;
473
+ default :
474
+ assert (false ); // need to implement calculation for more types
475
+ return false ;
476
+ break ;
344
477
}
345
478
346
- outCount = trianglecount;
347
479
return true ;
348
480
}
349
481
0 commit comments