diff --git a/include/nbl/asset/ICPUPolygonGeometry.h b/include/nbl/asset/ICPUPolygonGeometry.h index 89249af4ac..d30f10a873 100644 --- a/include/nbl/asset/ICPUPolygonGeometry.h +++ b/include/nbl/asset/ICPUPolygonGeometry.h @@ -30,7 +30,7 @@ class NBL_API2 ICPUPolygonGeometry final : public IPolygonGeometry inline core::smart_refctd_ptr clone(uint32_t _depth=~0u) const override { const auto nextDepth = _depth ? (_depth-1):0; - auto retval = core::smart_refctd_ptr(); + auto retval = core::smart_refctd_ptr(new ICPUPolygonGeometry()); retval->m_positionView = m_positionView.clone(nextDepth); retval->m_jointOBBView = m_jointOBBView.clone(nextDepth); retval->m_indexView = m_indexView.clone(nextDepth); diff --git a/include/nbl/asset/utils/CPolygonGeometryManipulator.h b/include/nbl/asset/utils/CPolygonGeometryManipulator.h index 3aa3c25304..8e02ea9877 100644 --- a/include/nbl/asset/utils/CPolygonGeometryManipulator.h +++ b/include/nbl/asset/utils/CPolygonGeometryManipulator.h @@ -81,6 +81,92 @@ class NBL_API2 CPolygonGeometryManipulator const_cast(geo->getAABBStorage()) = computeAABB(geo); } + static inline core::smart_refctd_ptr createTriangleListIndexing(const ICPUPolygonGeometry* geo) + { + const auto* indexing = geo->getIndexingCallback(); + if (!indexing) return nullptr; + if (indexing->degree() != 3) return nullptr; + + const auto originalView = geo->getIndexView(); + const auto originalIndexSize = originalView ? originalView.composed.stride : 0; + const auto primCount = geo->getPrimitiveCount(); + const auto maxIndex = geo->getPositionView().getElementCount() - 1; + const uint8_t indexSize = maxIndex <= std::numeric_limits::max() ? sizeof(uint16_t) : sizeof(uint32_t); + const auto outGeometry = core::move_and_static_cast(geo->clone(0u)); + + if (indexing && indexing->knownTopology() == EPT_TRIANGLE_LIST) + return outGeometry; + + + auto* outGeo = outGeometry.get(); + const auto indexBufferUsages = [&] + { + if (originalView) return originalView.src.buffer->getUsageFlags(); + return core::bitflag(IBuffer::EUF_INDEX_BUFFER_BIT); + }(); + auto indexBuffer = ICPUBuffer::create({ primCount * indexing->degree() * indexSize, indexBufferUsages }); + auto indexBufferPtr = indexBuffer->getPointer(); + auto indexView = ICPUPolygonGeometry::SDataView{ + .composed = { + .stride = indexSize, + }, + .src = { + .offset = 0, + .size = indexBuffer->getSize(), + .buffer = std::move(indexBuffer) + } + }; + + switch (indexSize) + { + case 2: + { + IPolygonGeometryBase::IIndexingCallback::SContext context{ + .indexBuffer = geo->getIndexView().getPointer(), + .indexSize = originalIndexSize, + .beginPrimitive = 0, + .endPrimitive = primCount, + .out = indexBufferPtr, + }; + indexing->operator()(context); + + indexView.composed.encodedDataRange.u16.minVx[0] = 0; + indexView.composed.encodedDataRange.u16.maxVx[0] = maxIndex; + indexView.composed.format = EF_R16_UINT; + indexView.composed.rangeFormat = IGeometryBase::EAABBFormat::U16; + break; + } + case 4: + { + IPolygonGeometryBase::IIndexingCallback::SContext context{ + .indexBuffer = geo->getIndexView().getPointer(), + .indexSize = originalIndexSize, + .beginPrimitive = 0, + .endPrimitive = primCount, + .out = indexBufferPtr, + }; + indexing->operator()(context); + + indexView.composed.encodedDataRange.u32.minVx[0] = 0; + indexView.composed.encodedDataRange.u32.maxVx[0] = maxIndex; + indexView.composed.format = EF_R32_UINT; + indexView.composed.rangeFormat = IGeometryBase::EAABBFormat::U32; + break; + } + default: + { + assert(false); + return nullptr; + } + } + + outGeo->setIndexing(IPolygonGeometryBase::TriangleList()); + outGeo->setIndexView(std::move(indexView)); + CGeometryManipulator::recomputeContentHash(outGeo->getIndexView()); + + return outGeometry; + } + //! Comparison methods enum E_ERROR_METRIC {