From 4a37ba53b067bba3f04333423299fd4a34080086 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Wed, 25 Jun 2025 18:29:12 +0700 Subject: [PATCH 1/7] Implement createCylinder, createCone, createSphere, CreateArrow --- src/nbl/asset/utils/CGeometryCreator.cpp | 1010 +++++++++++++++------- 1 file changed, 684 insertions(+), 326 deletions(-) diff --git a/src/nbl/asset/utils/CGeometryCreator.cpp b/src/nbl/asset/utils/CGeometryCreator.cpp index c5c6ac6765..c25a222a53 100644 --- a/src/nbl/asset/utils/CGeometryCreator.cpp +++ b/src/nbl/asset/utils/CGeometryCreator.cpp @@ -15,6 +15,11 @@ namespace nbl::asset { +static uint8_t packSnorm(float val) +{ + return round(hlsl::clamp(val, -1.0f, 1.0f) * 127); +} + core::smart_refctd_ptr CGeometryCreator::createCube(const hlsl::float32_t3 size) const { using namespace hlsl; @@ -156,7 +161,7 @@ core::smart_refctd_ptr CGeometryCreator::createCube(const h { const hlsl::vector norm[6] = { - hlsl::vector(0, 0, 127), + hlsl::vector(0, 0, 1), hlsl::vector(127, 0, 0), hlsl::vector(0, 0,-127), hlsl::vector(-127, 0, 0), @@ -186,121 +191,12 @@ core::smart_refctd_ptr CGeometryCreator::createCube(const h return retval; } -#if 0 - -/* - a cylinder, a cone and a cross - point up on (0,1.f, 0.f ) -*/ -core::smart_refctd_ptr CGeometryCreator::createArrow( - const uint32_t tesselationCylinder, - const uint32_t tesselationCone, - const float height, - const float cylinderHeight, - const float width0, - const float width1, - const video::SColor vtxColor0, - const video::SColor vtxColor1 -) const +core::smart_refctd_ptr CGeometryCreator::createSphere(float radius, + uint32_t polyCountX, uint32_t polyCountY, CQuantNormalCache* const quantNormalCacheOverride) const { - assert(height > cylinderHeight); - - auto cylinder = createCylinderMesh(width0, cylinderHeight, tesselationCylinder, vtxColor0); - auto cone = createConeMesh(width1, height-cylinderHeight, tesselationCone, vtxColor1, vtxColor1); - - auto cylinderVertices = reinterpret_cast(cylinder.bindings[0].buffer->getPointer()); - auto coneVertices = reinterpret_cast(cone.bindings[0].buffer->getPointer()); - - auto cylinderIndecies = reinterpret_cast(cylinder.indexBuffer.buffer->getPointer()); - auto coneIndecies = reinterpret_cast(cone.indexBuffer.buffer->getPointer()); - - const auto cylinderVertexCount = cylinder.bindings[0].buffer->getSize() / sizeof(CylinderVertex); - const auto coneVertexCount = cone.bindings[0].buffer->getSize() / sizeof(ConeVertex); - const auto newArrowVertexCount = cylinderVertexCount + coneVertexCount; - - const auto cylinderIndexCount = cylinder.indexBuffer.buffer->getSize() / sizeof(uint16_t); - const auto coneIndexCount = cone.indexBuffer.buffer->getSize() / sizeof(uint16_t); - const auto newArrowIndexCount = cylinderIndexCount + coneIndexCount; - - for (auto i = 0ull; i < coneVertexCount; ++i) - { - core::vector3df_SIMD newPos = coneVertices[i].pos; - newPos.rotateYZByRAD(-1.5707963268); - - for (auto c = 0; c < 3; ++c) - coneVertices[i].pos[c] = newPos[c]; - } - - auto newArrowVertexBuffer = asset::ICPUBuffer::create({ newArrowVertexCount * sizeof(ArrowVertex) }); - newArrowVertexBuffer->setUsageFlags(newArrowVertexBuffer->getUsageFlags() | asset::IBuffer::EUF_VERTEX_BUFFER_BIT); - auto newArrowIndexBuffer = asset::ICPUBuffer::create({ newArrowIndexCount * sizeof(uint16_t) }); - newArrowIndexBuffer->setUsageFlags(newArrowIndexBuffer->getUsageFlags() | asset::IBuffer::EUF_INDEX_BUFFER_BIT); - - for (auto z = 0ull; z < newArrowVertexCount; ++z) - { - auto arrowVertex = reinterpret_cast(newArrowVertexBuffer->getPointer()) + z; - - if (z < cylinderVertexCount) - { - auto cylinderVertex = (cylinderVertices + z); - memcpy(arrowVertex, cylinderVertex, sizeof(ArrowVertex)); - } - else - { - auto coneVertex = (coneVertices + z - cylinderVertexCount); - memcpy(arrowVertex, coneVertex, offsetof(ConeVertex, normal)); // copy position and color - arrowVertex->uv[0] = 0; - arrowVertex->uv[1] = 0; - arrowVertex->normal = coneVertex->normal; - } - } - - { - auto ArrowIndices = reinterpret_cast(newArrowIndexBuffer->getPointer()); - auto newConeIndices = (ArrowIndices + cylinderIndexCount); - - memcpy(ArrowIndices, cylinderIndecies, sizeof(uint16_t) * cylinderIndexCount); - memcpy(newConeIndices, coneIndecies, sizeof(uint16_t) * coneIndexCount); - - for (auto i = 0ull; i < coneIndexCount; ++i) - *(newConeIndices + i) += cylinderVertexCount; - } - - return_type arrow; - - constexpr size_t vertexSize = sizeof(ArrowVertex); - arrow.inputParams = - { 0b1111u,0b1u, - { - {0u,EF_R32G32B32_SFLOAT,offsetof(ArrowVertex,pos)}, - {0u,EF_R8G8B8A8_UNORM,offsetof(ArrowVertex,color)}, - {0u,EF_R32G32_SFLOAT,offsetof(ArrowVertex,uv)}, - {0u,EF_A2B10G10R10_SNORM_PACK32,offsetof(ArrowVertex,normal)} - }, - {vertexSize,SVertexInputBindingParams::EVIR_PER_VERTEX} - }; - - arrow.bindings[0] = { 0, std::move(newArrowVertexBuffer) }; - arrow.indexBuffer = { 0, std::move(newArrowIndexBuffer) }; - arrow.indexCount = newArrowIndexCount; - arrow.indexType = EIT_16BIT; - - return arrow; -} + using namespace hlsl; -/* A sphere with proper normals and texture coords */ -core::smart_refctd_ptr CGeometryCreator::createSphere(float radius, uint32_t polyCountX, uint32_t polyCountY, IMeshManipulator* const meshManipulatorOverride) const -{ - // we are creating the sphere mesh here. - return_type retval; - constexpr size_t vertexSize = sizeof(CGeometryCreator::SphereVertex); - CQuantNormalCache* const quantNormalCache = (meshManipulatorOverride == nullptr) ? defaultMeshManipulator->getQuantNormalCache() : meshManipulatorOverride->getQuantNormalCache(); - retval.inputParams = { 0b1111u,0b1u,{ - {0u,EF_R32G32B32_SFLOAT,offsetof(SphereVertex,pos)}, - {0u,EF_R8G8B8A8_UNORM,offsetof(SphereVertex,color)}, - {0u,EF_R32G32_SFLOAT,offsetof(SphereVertex,uv)}, - {0u,EF_A2B10G10R10_SNORM_PACK32,offsetof(SphereVertex,normal)} - },{vertexSize,SVertexInputBindingParams::EVIR_PER_VERTEX} }; + CQuantNormalCache* const quantNormalCache = quantNormalCacheOverride == nullptr ? m_params.normalCache.get() : quantNormalCacheOverride; if (polyCountX < 2) polyCountX = 2; @@ -308,15 +204,20 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float polyCountY = 2; const uint32_t polyCountXPitch = polyCountX + 1; // get to same vertex on next level + const size_t vertexCount = (polyCountXPitch * polyCountY) + 2; - retval.indexCount = (polyCountX * polyCountY) * 6; - auto indices = asset::ICPUBuffer::create({ sizeof(uint32_t) * retval.indexCount }); + auto retval = core::make_smart_refctd_ptr(); + retval->setIndexing(IPolygonGeometryBase::TriangleList()); // Create indices + using index_t = uint32_t; { - uint32_t level = 0; + const auto indexCount = (polyCountX * polyCountY) * 6; + const auto bytesize = sizeof(index_t) * indexCount; + auto indices = ICPUBuffer::create({bytesize,IBuffer::EUF_INDEX_BUFFER_BIT}); + auto indexPtr = reinterpret_cast(indices->getPointer()); + uint32_t level = 0; size_t indexAddIx = 0; - uint32_t* indexPtr = (uint32_t*)indices->getPointer(); for (uint32_t p1 = 0; p1 < polyCountY - 1; ++p1) { //main quads, top to bottom @@ -372,23 +273,123 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float indexPtr[indexAddIx++] = polyCountSqM1 + polyCountX - 1; indexPtr[indexAddIx++] = polyCountSqM1; indexPtr[indexAddIx++] = polyCountSq1; + + shapes::AABB<4,index_t> aabb; + aabb.minVx[0] = 0; + aabb.maxVx[0] = vertexCount - 1; + retval->setIndexView({ + .composed = { + .encodedDataRange = {.u32=aabb}, + .stride = sizeof(index_t), + .format = EF_R16_UINT, + .rangeFormat = IGeometryBase::EAABBFormat::U16 + }, + .src = {.offset=0,.size=bytesize,.buffer=std::move(indices)} + }); } - indices->setUsageFlags(indices->getUsageFlags() | asset::IBuffer::EUF_INDEX_BUFFER_BIT); - retval.indexBuffer = {0ull, std::move(indices)}; - // handle vertices + constexpr auto NormalCacheFormat = EF_R8G8B8_SNORM; + constexpr auto NormalFormat = EF_R8G8B8A8_SNORM; + + // Create vertex attributes with NONE usage because we have no clue how they'll be used + hlsl::float32_t3* positions; + hlsl::vector* normals; + hlsl::vector* uvs; + hlsl::vector* colors; + { + { + constexpr auto AttrSize = sizeof(decltype(*positions)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + positions = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, float32_t> aabb; + aabb.maxVx = float32_t4(radius, radius, radius, 0.0f); + aabb.minVx = float32_t4(-radius, -radius, -radius, 0.0f); + retval->setPositionView({ + .composed = { + .encodedDataRange = {.f32 = aabb}, + .stride = AttrSize, + .format = EF_R32G32B32_SFLOAT, + .rangeFormat = IGeometryBase::EAABBFormat::F32 + }, + .src = { + .offset=0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*normals)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + normals = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, int8_t> aabb; + aabb.maxVx = hlsl::vector(127,127,127,0); + aabb.minVx = -aabb.maxVx; + retval->setNormalView({ + .composed = { + .encodedDataRange = {.s8=aabb}, + .stride = AttrSize, + .format = NormalFormat, + .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff) + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*uvs)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + uvs = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, uint8_t> aabb; + aabb.minVx = hlsl::vector(0,0,0,0); + aabb.maxVx = hlsl::vector(255,255,0,0); + retval->getAuxAttributeViews()->push_back({ + .composed = { + .encodedDataRange = {.u8=aabb}, + .stride = AttrSize, + .format = EF_R8G8_UNORM, + .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*colors)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + colors = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, uint8_t> aabb; + aabb.minVx = hlsl::vector(0,0,0,0); + aabb.maxVx = hlsl::vector(255,255,0,0); + retval->getAuxAttributeViews()->push_back({ + .composed = { + .encodedDataRange = {.u8=aabb}, + .stride = AttrSize, + .format = EF_R8G8B8A8_UNORM, + .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + } + + // fill vertices { - size_t vertexSize = 3 * 4 + 4 + 2 * 4 + 4; - size_t vertexCount = (polyCountXPitch * polyCountY) + 2; - auto vtxBuf = asset::ICPUBuffer::create({ vertexCount * vertexSize }); - auto* tmpMem = reinterpret_cast(vtxBuf->getPointer()); for (size_t i = 0; i < vertexCount; i++) { - tmpMem[i * vertexSize + 3 * 4 + 0] = 255; - tmpMem[i * vertexSize + 3 * 4 + 1] = 255; - tmpMem[i * vertexSize + 3 * 4 + 2] = 255; - tmpMem[i * vertexSize + 3 * 4 + 3] = 255; + colors[i] = { 255,255,255,255 }; } + // calculate the angle which separates all points in a circle const float AngleX = 2 * core::PI() / polyCountX; const float AngleY = core::PI() / polyCountY; @@ -398,258 +399,615 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float // we don't start at 0. double ay = 0;//AngleY / 2; - - using quant_normal_t = CQuantNormalCache::value_type_t; - uint8_t* tmpMemPtr = tmpMem; - for (uint32_t y = 0; y < polyCountY; ++y) - { - ay += AngleY; - const double sinay = sin(ay); - axz = 0; - - // calculate the necessary vertices without the doubled one - uint8_t* oldTmpMemPtr = tmpMemPtr; - for (uint32_t xz = 0; xz < polyCountX; ++xz) - { - // calculate points position - - float32_t3 pos(static_cast(cos(axz) * sinay), - static_cast(cos(ay)), - static_cast(sin(axz) * sinay)); - // for spheres the normal is the position - core::vectorSIMDf normal(&pos.X); - normal.makeSafe3D(); - quant_normal_t quantizedNormal = quantNormalCache->quantize(normal); - pos *= radius; - - // calculate texture coordinates via sphere mapping - // tu is the same on each level, so only calculate once - float tu = 0.5f; - //if (y==0) - //{ - if (normal.Y != -1.0f && normal.Y != 1.0f) - tu = static_cast(acos(core::clamp(normal.X / sinay, -1.0, 1.0)) * 0.5 * core::RECIPROCAL_PI()); - if (normal.Z < 0.0f) - tu = 1 - tu; - //} - //else - //tu = ((float*)(tmpMem+(i-polyCountXPitch)*vertexSize))[4]; - - ((float*)tmpMemPtr)[0] = pos.X; - ((float*)tmpMemPtr)[1] = pos.Y; - ((float*)tmpMemPtr)[2] = pos.Z; - ((float*)tmpMemPtr)[4] = tu; - ((float*)tmpMemPtr)[5] = static_cast(ay * core::RECIPROCAL_PI()); - ((quant_normal_t*)tmpMemPtr)[6] = quantizedNormal; - static_assert(sizeof(quant_normal_t)==4u); - - tmpMemPtr += vertexSize; - axz += AngleX; - } - // This is the doubled vertex on the initial position - - ((float*)tmpMemPtr)[0] = ((float*)oldTmpMemPtr)[0]; - ((float*)tmpMemPtr)[1] = ((float*)oldTmpMemPtr)[1]; - ((float*)tmpMemPtr)[2] = ((float*)oldTmpMemPtr)[2]; - ((float*)tmpMemPtr)[4] = 1.f; - ((float*)tmpMemPtr)[5] = ((float*)oldTmpMemPtr)[5]; - ((uint32_t*)tmpMemPtr)[6] = ((uint32_t*)oldTmpMemPtr)[6]; - tmpMemPtr += vertexSize; - } + auto vertex_i = 0; + for (uint32_t y = 0; y < polyCountY; ++y) + { + ay += AngleY; + const double sinay = sin(ay); + axz = 0; + + // calculate the necessary vertices without the doubled one + const auto old_vertex_i = vertex_i; + for (uint32_t xz = 0; xz < polyCountX; ++xz) + { + // calculate points position + + float32_t3 pos(static_cast(cos(axz) * sinay), + static_cast(cos(ay)), + static_cast(sin(axz) * sinay)); + // for spheres the normal is the position + core::vectorSIMDf normal(&pos.x); + normal.makeSafe3D(); + const auto quantizedNormal = quantNormalCache->quantize(normal); + pos *= radius; + + // calculate texture coordinates via sphere mapping + // tu is the same on each level, so only calculate once + float tu = 0.5f; + //if (y==0) + //{ + if (normal.Y != -1.0f && normal.Y != 1.0f) + tu = static_cast(acos(core::clamp(normal.X / sinay, -1.0, 1.0)) * 0.5 * core::RECIPROCAL_PI()); + if (normal.Z < 0.0f) + tu = 1 - tu; + //} + //else + //tu = ((float*)(tmpMem+(i-polyCountXPitch)*vertexSize))[4]; + + positions[vertex_i] = pos; + uvs[vertex_i] = { packSnorm(tu), packSnorm(static_cast(ay * core::RECIPROCAL_PI())) }; + memcpy(normals + vertex_i, &quantizedNormal, sizeof(quantizedNormal)); + + vertex_i++; + axz += AngleX; + } + // This is the doubled vertex on the initial position + + positions[vertex_i] = positions[old_vertex_i]; + uvs[vertex_i] = { 127, uvs[old_vertex_i].y }; + normals[vertex_i] = normals[old_vertex_i]; + + vertex_i++; + } // the vertex at the top of the sphere - ((float*)tmpMemPtr)[0] = 0.f; - ((float*)tmpMemPtr)[1] = radius; - ((float*)tmpMemPtr)[2] = 0.f; - ((float*)tmpMemPtr)[4] = 0.5f; - ((float*)tmpMemPtr)[5] = 0.f; - ((quant_normal_t*)tmpMemPtr)[6] = quantNormalCache->quantize(core::vectorSIMDf(0.f, 1.f, 0.f)); + positions[vertex_i] = { 0.f, radius, 0.f }; + uvs[vertex_i] = { 0, 63}; + const auto quantizedTopNormal = quantNormalCache->quantize(core::vectorSIMDf(0.f, 1.f, 0.f)); + memcpy(normals + vertex_i, &quantizedTopNormal, sizeof(quantizedTopNormal)); // the vertex at the bottom of the sphere - tmpMemPtr += vertexSize; - ((float*)tmpMemPtr)[0] = 0.f; - ((float*)tmpMemPtr)[1] = -radius; - ((float*)tmpMemPtr)[2] = 0.f; - ((float*)tmpMemPtr)[4] = 0.5f; - ((float*)tmpMemPtr)[5] = 1.f; - ((quant_normal_t*)tmpMemPtr)[6] = quantNormalCache->quantize(core::vectorSIMDf(0.f, -1.f, 0.f)); - - // recalculate bounding box - core::aabbox3df BoundingBox; - BoundingBox.reset(float32_t3(radius)); - BoundingBox.addInternalPoint(-radius, -radius, -radius); - - // set vertex buffer - vtxBuf->setUsageFlags(vtxBuf->getUsageFlags() | asset::IBuffer::EUF_VERTEX_BUFFER_BIT); - retval.bindings[0] = { 0ull,std::move(vtxBuf) }; - retval.indexType = asset::EIT_32BIT; - retval.bbox = BoundingBox; + vertex_i++; + positions[vertex_i] = { 0.f, -radius, 0.f }; + uvs[vertex_i] = { 63, 127}; + const auto quantizedBottomNormal = quantNormalCache->quantize(core::vectorSIMDf(0.f, -1.f, 0.f)); + memcpy(normals + vertex_i, &quantizedBottomNormal, sizeof(quantizedBottomNormal)); } + CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); return retval; } -/* A cylinder with proper normals and texture coords */ core::smart_refctd_ptr CGeometryCreator::createCylinder( float radius, float length, - uint32_t tesselation, const video::SColor& color, IMeshManipulator* const meshManipulatorOverride -) const + uint32_t tesselation, const video::SColor& color, CQuantNormalCache* const quantNormalCacheOverride) const { - return_type retval; - constexpr size_t vertexSize = sizeof(CGeometryCreator::CylinderVertex); - CQuantNormalCache* const quantNormalCache = (meshManipulatorOverride == nullptr) ? defaultMeshManipulator->getQuantNormalCache() : meshManipulatorOverride->getQuantNormalCache(); - retval.inputParams = { 0b1111u,0b1u,{ - {0u,EF_R32G32B32_SFLOAT,offsetof(CylinderVertex,pos)}, - {0u,EF_R8G8B8A8_UNORM,offsetof(CylinderVertex,color)}, - {0u,EF_R32G32_SFLOAT,offsetof(CylinderVertex,uv)}, - {0u,EF_A2B10G10R10_SNORM_PACK32,offsetof(CylinderVertex,normal)} - },{vertexSize,SVertexInputBindingParams::EVIR_PER_VERTEX} }; - - const size_t vtxCnt = 2u*tesselation; - auto vtxBuf = asset::ICPUBuffer::create({ vtxCnt*sizeof(CylinderVertex) }); - - CylinderVertex* vertices = reinterpret_cast(vtxBuf->getPointer()); - for (auto i=0ull; i(tesselation); - const float step = 2.f*core::PI()*tesselationRec; - for (uint32_t i = 0u; iquantize(core::normalize(p)); - - memcpy(vertices[i].pos, p.pointer, 12u); - vertices[i].normal = n; - memcpy(vertices[i].color, glcolor, 4u); - vertices[i].uv[0] = float(i) * tesselationRec; - - vertices[i+halfIx] = vertices[i]; - vertices[i+halfIx].pos[2] = length; - vertices[i+halfIx].uv[1] = 1.f; - } + using namespace hlsl; + + CQuantNormalCache* const quantNormalCache = quantNormalCacheOverride == nullptr ? m_params.normalCache.get() : quantNormalCacheOverride; + + const uint16_t halfIx = static_cast(tesselation); + const uint16_t vertexCount = 2 * static_cast(tesselation); - constexpr uint32_t rows = 2u; - retval.indexCount = rows * 3u * tesselation; - auto idxBuf = asset::ICPUBuffer::create({ retval.indexCount *sizeof(uint16_t) }); - uint16_t* indices = (uint16_t*)idxBuf->getPointer(); + auto retval = core::make_smart_refctd_ptr(); + retval->setIndexing(IPolygonGeometryBase::TriangleList()); - for (uint32_t i = 0u, j = 0u; i < halfIx; ++i) + // Create indices + using index_t = uint16_t; + { + constexpr uint32_t RowCount = 2u; + const auto IndexCount = RowCount * 3 * tesselation; + const auto bytesize = sizeof(index_t) * IndexCount; + auto indices = ICPUBuffer::create({bytesize,IBuffer::EUF_INDEX_BUFFER_BIT}); + auto u = reinterpret_cast(indices->getPointer()); + for (uint16_t i = 0u, j = 0u; i < halfIx; ++i) { - indices[j++] = i; - indices[j++] = (i+1u)!=halfIx ? (i+1u):0u; - indices[j++] = i+halfIx; - indices[j++] = i+halfIx; - indices[j++] = (i+1u)!=halfIx ? (i+1u):0u; - indices[j++] = (i+1u)!=halfIx ? (i+1u+halfIx):halfIx; + u[j++] = i; + u[j++] = (i + 1u) != halfIx ? (i + 1u):0u; + u[j++] = i + halfIx; + u[j++] = i + halfIx; + u[j++] = (i + 1u)!= halfIx ? (i + 1u):0u; + u[j++] = (i + 1u)!= halfIx ? (i + 1u + halfIx) : halfIx; } - // set vertex buffer - idxBuf->setUsageFlags(idxBuf->getUsageFlags() | asset::IBuffer::EUF_INDEX_BUFFER_BIT); - retval.indexBuffer = { 0ull, std::move(idxBuf) }; - vtxBuf->setUsageFlags(vtxBuf->getUsageFlags() | asset::IBuffer::EUF_VERTEX_BUFFER_BIT); - retval.bindings[0] = { 0ull, std::move(vtxBuf) }; - retval.indexType = asset::EIT_16BIT; - //retval.bbox = ?; + shapes::AABB<4,index_t> aabb; + aabb.minVx[0] = 0; + aabb.maxVx[0] = vertexCount - 1; + retval->setIndexView({ + .composed = { + .encodedDataRange = {.u16=aabb}, + .stride = sizeof(index_t), + .format = EF_R16_UINT, + .rangeFormat = IGeometryBase::EAABBFormat::U16 + }, + .src = {.offset=0,.size=bytesize,.buffer=std::move(indices)} + }); + } + + constexpr auto NormalCacheFormat = EF_R8G8B8_SNORM; + constexpr auto NormalFormat = EF_R8G8B8A8_SNORM; + + // Create vertex attributes with NONE usage because we have no clue how they'll be used + hlsl::float32_t3* positions; + hlsl::vector* normals; + hlsl::vector* uvs; + hlsl::vector* colors; + { + { + constexpr auto AttrSize = sizeof(decltype(*positions)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + positions = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, float32_t> aabb; + aabb.maxVx = float32_t4(radius, radius, length, 0.0f); + aabb.minVx = float32_t4(-radius, -radius, 0.0f, 0.0f); + retval->setPositionView({ + .composed = { + .encodedDataRange = {.f32 = aabb}, + .stride = AttrSize, + .format = EF_R32G32B32_SFLOAT, + .rangeFormat = IGeometryBase::EAABBFormat::F32 + }, + .src = { + .offset=0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*normals)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + normals = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, int8_t> aabb; + aabb.maxVx = hlsl::vector(127,127,127,0); + aabb.minVx = -aabb.maxVx; + retval->setNormalView({ + .composed = { + .encodedDataRange = {.s8=aabb}, + .stride = AttrSize, + .format = NormalFormat, + .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff) + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*uvs)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + uvs = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, uint8_t> aabb; + aabb.minVx = hlsl::vector(0,0,0,0); + aabb.maxVx = hlsl::vector(255,255,0,0); + retval->getAuxAttributeViews()->push_back({ + .composed = { + .encodedDataRange = {.u8=aabb}, + .stride = AttrSize, + .format = EF_R8G8_UNORM, + .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*colors)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + colors = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, uint8_t> aabb; + aabb.minVx = hlsl::vector(0,0,0,0); + aabb.maxVx = hlsl::vector(255,255,0,0); + retval->getAuxAttributeViews()->push_back({ + .composed = { + .encodedDataRange = {.u8=aabb}, + .stride = AttrSize, + .format = EF_R8G8B8A8_UNORM, + .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + } + + uint8_t glcolor[4]; + color.toOpenGLColor(glcolor); + + const float tesselationRec = core::reciprocal_approxim(static_cast(tesselation)); + const float step = 2.f * core::PI() * tesselationRec; + for (uint32_t i = 0u; i < tesselation; ++i) + { + const auto f_i = static_cast(i); + core::vectorSIMDf p(std::cos(f_i * step), std::sin(f_i * step), 0.f); + p *= radius; + const auto n = quantNormalCache->quantize(core::normalize(p)); + + positions[i] = { p.x, p.y, p.z }; + memcpy(normals + i, &n, sizeof(n)); + uvs[i] = { f_i * tesselationRec, 0.0 }; + colors[i] = { glcolor[0], glcolor[1], glcolor[2], glcolor[3] }; + + positions[i + halfIx] = { p.x, p.y, length }; + normals[i + halfIx] = normals[i]; + uvs[i + halfIx] = { 1.0f, 0.0f }; + colors[i + halfIx] = { glcolor[0], glcolor[1], glcolor[2], glcolor[3] }; + } + CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); return retval; } -/* A cone with proper normals and texture coords */ core::smart_refctd_ptr CGeometryCreator::createCone( - float radius, float length, uint32_t tesselation, - const video::SColor& colorTop, - const video::SColor& colorBottom, - float oblique, - IMeshManipulator* const meshManipulatorOverride -) const + float radius, float length, uint32_t tesselation, + const video::SColor& colorTop, + const video::SColor& colorBottom, + float oblique, CQuantNormalCache* const quantNormalCacheOverride) const { - const size_t vtxCnt = tesselation * 2; - auto vtxBuf = asset::ICPUBuffer::create({ vtxCnt * sizeof(ConeVertex) }); - ConeVertex* vertices = reinterpret_cast(vtxBuf->getPointer()); - ConeVertex* baseVertices = vertices; - ConeVertex* apexVertices = vertices + tesselation; + using namespace hlsl; - std::fill(vertices,vertices+vtxCnt, ConeVertex(core::vectorSIMDf(0.f),{},colorBottom)); - CQuantNormalCache* const quantNormalCache = (meshManipulatorOverride == nullptr) ? defaultMeshManipulator->getQuantNormalCache() : meshManipulatorOverride->getQuantNormalCache(); + CQuantNormalCache* const quantNormalCache = quantNormalCacheOverride == nullptr ? m_params.normalCache.get() : quantNormalCacheOverride; - const float step = (2.f*core::PI()) / tesselation; + const uint16_t vertexCount = 2 * static_cast(tesselation); + + auto retval = core::make_smart_refctd_ptr(); + retval->setIndexing(IPolygonGeometryBase::TriangleList()); + + // Create indices + using index_t = uint16_t; + { + constexpr uint32_t RowCount = 2u; + const auto IndexCount = 3 * tesselation; + const auto bytesize = sizeof(index_t) * IndexCount; + auto indices = ICPUBuffer::create({bytesize,IBuffer::EUF_INDEX_BUFFER_BIT}); + auto u = reinterpret_cast(indices->getPointer()); + const uint32_t firstIndexOfBaseVertices = 0; + const uint32_t firstIndexOfApexVertices = tesselation; + for (uint32_t i = 0; i < tesselation; i++) + { + u[i * 3] = firstIndexOfApexVertices + i; + u[(i * 3) + 1] = firstIndexOfBaseVertices + i; + u[(i * 3) + 2] = i == (tesselation - 1) ? firstIndexOfBaseVertices : firstIndexOfBaseVertices + i + 1; + } + + shapes::AABB<4,index_t> aabb; + aabb.minVx[0] = 0; + aabb.maxVx[0] = vertexCount - 1; + retval->setIndexView({ + .composed = { + .encodedDataRange = {.u16=aabb}, + .stride = sizeof(index_t), + .format = EF_R16_UINT, + .rangeFormat = IGeometryBase::EAABBFormat::U16 + }, + .src = {.offset=0,.size=bytesize,.buffer=std::move(indices)} + }); + } + + constexpr auto NormalCacheFormat = EF_R8G8B8_SNORM; + constexpr auto NormalFormat = EF_R8G8B8A8_SNORM; + + // Create vertex attributes with NONE usage because we have no clue how they'll be used + hlsl::float32_t3* positions; + hlsl::vector* normals; + hlsl::vector* colors; + { + { + constexpr auto AttrSize = sizeof(decltype(*positions)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + positions = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, float32_t> aabb; + aabb.maxVx = float32_t4(radius, radius, length, 0.0f); + aabb.minVx = float32_t4(-radius, -radius, 0.0f, 0.0f); + retval->setPositionView({ + .composed = { + .encodedDataRange = {.f32 = aabb}, + .stride = AttrSize, + .format = EF_R32G32B32_SFLOAT, + .rangeFormat = IGeometryBase::EAABBFormat::F32 + }, + .src = { + .offset=0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*normals)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + normals = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, int8_t> aabb; + aabb.maxVx = hlsl::vector(127,127,127,0); + aabb.minVx = -aabb.maxVx; + retval->setNormalView({ + .composed = { + .encodedDataRange = {.s8=aabb}, + .stride = AttrSize, + .format = NormalFormat, + .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff) + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*colors)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + colors = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, uint8_t> aabb; + aabb.minVx = hlsl::vector(0,0,0,0); + aabb.maxVx = hlsl::vector(255,255,0,0); + retval->getAuxAttributeViews()->push_back({ + .composed = { + .encodedDataRange = {.u8=aabb}, + .stride = AttrSize, + .format = EF_R8G8B8A8_UNORM, + .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + } + + uint8_t glcolor[4]; + colorBottom.toOpenGLColor(glcolor); + vector vertexBottomColor = { glcolor[0], glcolor[1], glcolor[2], glcolor[3] }; + std::fill_n(colors, vertexCount, vertexBottomColor); + + const float step = (2.f*core::PI()) / tesselation; const core::vectorSIMDf apexVertexCoords(oblique, length, 0.0f); - //vertex positions + const auto apexVertexBase_i = tesselation; + for (uint32_t i = 0u; i < tesselation; i++) { core::vectorSIMDf v(std::cos(i * step), 0.0f, std::sin(i * step), 0.0f); v *= radius; - memcpy(baseVertices[i].pos, v.pointer, sizeof(float) * 3); - memcpy(apexVertices[i].pos, apexVertexCoords.pointer, sizeof(float) * 3); - } + positions[i] = { v.x, v.y, v.z }; + positions[apexVertexBase_i + i] = { apexVertexCoords.x, apexVertexCoords.y, apexVertexCoords.z }; - //vertex normals - for (uint32_t i = 0; i < tesselation; i++) - { - const core::vectorSIMDf v0ToApex = apexVertexCoords - core::vectorSIMDf(vertices[i].pos[0], vertices[i].pos[1], vertices[i].pos[2]); + const auto simdPosition = core::vectorSIMDf(positions[i].x, positions[i].y, positions[i].z); + const core::vectorSIMDf v0ToApex = apexVertexCoords - simdPosition; uint32_t nextVertexIndex = i == (tesselation - 1) ? 0 : i + 1; - core::vectorSIMDf u1 = core::vectorSIMDf(baseVertices[nextVertexIndex].pos[0], baseVertices[nextVertexIndex].pos[1], baseVertices[nextVertexIndex].pos[2]); - u1 -= core::vectorSIMDf(baseVertices[i].pos[0], baseVertices[i].pos[1], baseVertices[i].pos[2]); + core::vectorSIMDf u1 = core::vectorSIMDf(positions[nextVertexIndex].x, positions[nextVertexIndex].y, positions[nextVertexIndex].z); + u1 -= simdPosition; float angleWeight = std::acos(core::dot(core::normalize(apexVertexCoords), core::normalize(u1)).x); u1 = core::normalize(core::cross(v0ToApex, u1)) * angleWeight; uint32_t prevVertexIndex = i == 0 ? (tesselation - 1) : i - 1; - core::vectorSIMDf u2 = core::vectorSIMDf(baseVertices[prevVertexIndex].pos[0], baseVertices[prevVertexIndex].pos[1], baseVertices[prevVertexIndex].pos[2]); - u2 -= core::vectorSIMDf(baseVertices[i].pos[0], baseVertices[i].pos[1], baseVertices[i].pos[2]); + core::vectorSIMDf u2 = core::vectorSIMDf(positions[prevVertexIndex].x, positions[prevVertexIndex].y, positions[prevVertexIndex].z); + u2 -= simdPosition; angleWeight = std::acos(core::dot(core::normalize(apexVertexCoords), core::normalize(u2)).x); u2 = core::normalize(core::cross(u2, v0ToApex)) * angleWeight; - baseVertices[i].normal = quantNormalCache->quantize(core::normalize(u1 + u2)); - apexVertices[i].normal = quantNormalCache->quantize(core::normalize(u1)); + + const auto baseNormal = quantNormalCache->quantize(core::normalize(u1 + u2)); + memcpy(normals + i, &baseNormal, sizeof(baseNormal)); + + const auto apexNormal = quantNormalCache->quantize(core::normalize(u1)); + memcpy(normals + apexVertexBase_i + i, &apexNormal, sizeof(apexNormal)); } - auto idxBuf = asset::ICPUBuffer::create({ 3u * tesselation * sizeof(uint16_t) }); - uint16_t* indices = (uint16_t*)idxBuf->getPointer(); + CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); + return retval; +} - const uint32_t firstIndexOfBaseVertices = 0; - const uint32_t firstIndexOfApexVertices = tesselation; - for (uint32_t i = 0; i < tesselation; i++) +core::smart_refctd_ptr CGeometryCreator::createArrow( + const uint32_t tesselationCylinder, + const uint32_t tesselationCone, + const float height, + const float cylinderHeight, + const float width0, + const float width1, + const video::SColor vtxColor0, + const video::SColor vtxColor1 +) const +{ + assert(height > cylinderHeight); + + using position_t = hlsl::float32_t3; + using normal_t = hlsl::vector; + using uv_t = hlsl::vector; + using color_t = hlsl::vector; + + auto cylinder = createCylinder(width0, cylinderHeight, tesselationCylinder, vtxColor0); + auto cone = createCone(width1, height-cylinderHeight, tesselationCone, vtxColor1, vtxColor1); + + auto cylinderPositions = reinterpret_cast(cylinder->getPositionView().src.buffer->getPointer()); + auto conePositions = reinterpret_cast(cone->getPositionView().src.buffer->getPointer()); + + const auto cylinderNormals = reinterpret_cast(cylinder->getNormalView().src.buffer->getPointer()); + const auto coneNormals = reinterpret_cast(cone->getNormalView().src.buffer->getPointer()); + + const auto cylinderUvs = reinterpret_cast(cylinder->getAuxAttributeViews()->front().src.buffer->getPointer()); + const auto coneUvs = reinterpret_cast(cone->getAuxAttributeViews()->front().src.buffer->getPointer()); + + const auto cylinderIndices = cylinder->getIndexView().src.buffer->getPointer(); + const auto coneIndices = cone->getIndexView().src.buffer->getPointer(); + + const auto cylinderVertexCount = cylinder->getPositionView().getElementCount(); + const auto coneVertexCount = cone->getPositionView().getElementCount(); + const auto newArrowVertexCount = cylinderVertexCount + coneVertexCount; + + const auto cylinderIndexCount = cylinder->getVertexReferenceCount(); + const auto coneIndexCount = cone->getVertexReferenceCount(); + const auto newArrowIndexCount = cylinderIndexCount + coneIndexCount; + + using namespace hlsl; + + auto retval = core::make_smart_refctd_ptr(); + retval->setIndexing(IPolygonGeometryBase::TriangleList()); + + // Create indices + using index_t = uint16_t; { - indices[i * 3] = firstIndexOfApexVertices + i; - indices[(i * 3) + 1] = firstIndexOfBaseVertices + i; - indices[(i * 3) + 2] = i == (tesselation - 1) ? firstIndexOfBaseVertices : firstIndexOfBaseVertices + i + 1; + const auto bytesize = sizeof(index_t) * newArrowIndexCount; + auto indices = ICPUBuffer::create({bytesize,IBuffer::EUF_INDEX_BUFFER_BIT}); + auto arrowIndices = reinterpret_cast(indices->getPointer()); + auto newConeIndices = (arrowIndices + cylinderIndexCount); + + memcpy(arrowIndices, cylinderIndices, sizeof(uint16_t) * cylinderIndexCount); + memcpy(newConeIndices, coneIndices, sizeof(uint16_t) * coneIndexCount); + + for (auto i = 0ull; i < coneIndexCount; ++i) + *(newConeIndices + i) += cylinderVertexCount; + + shapes::AABB<4,index_t> aabb; + aabb.minVx[0] = 0; + aabb.maxVx[0] = newArrowVertexCount - 1; + retval->setIndexView({ + .composed = { + .encodedDataRange = {.u16=aabb}, + .stride = sizeof(index_t), + .format = EF_R16_UINT, + .rangeFormat = IGeometryBase::EAABBFormat::U16 + }, + .src = {.offset=0,.size=bytesize,.buffer=std::move(indices)} + }); } - return_type cone; + constexpr auto NormalFormat = EF_R8G8B8A8_SNORM; - constexpr size_t vertexSize = sizeof(ConeVertex); - cone.inputParams = - { 0b111u,0b1u, + // Create vertex attributes with NONE usage because we have no clue how they'll be used + hlsl::float32_t3* positions; + hlsl::vector* normals; + hlsl::vector* colors; + hlsl::vector* uvs; + { + { + constexpr auto AttrSize = sizeof(decltype(*positions)); + auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); + positions = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, float32_t> aabb; + //TODO(kevyuu): Calculate arrow aabb + aabb.maxVx = hlsl::vector(127,127,127,0); + aabb.minVx = -aabb.maxVx; + retval->setPositionView({ + .composed = { + .encodedDataRange = {.f32 = aabb}, + .stride = AttrSize, + .format = EF_R32G32B32_SFLOAT, + .rangeFormat = IGeometryBase::EAABBFormat::F32 + }, + .src = { + .offset=0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*normals)); + auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); + normals = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, int8_t> aabb; + aabb.maxVx = hlsl::vector(127,127,127,0); + aabb.minVx = -aabb.maxVx; + retval->setNormalView({ + .composed = { + .encodedDataRange = {.s8=aabb}, + .stride = AttrSize, + .format = NormalFormat, + .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff) + } + }); + } { - {0u,EF_R32G32B32_SFLOAT,offsetof(ConeVertex,pos)}, - {0u,EF_R8G8B8A8_UNORM,offsetof(ConeVertex,color)}, - {0u,EF_A2B10G10R10_SNORM_PACK32,offsetof(ConeVertex,normal)} - }, - {vertexSize,SVertexInputBindingParams::EVIR_PER_VERTEX} - }; + constexpr auto AttrSize = sizeof(decltype(*uvs)); + auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); + uvs = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, uint8_t> aabb; + aabb.minVx = hlsl::vector(0,0,0,0); + aabb.maxVx = hlsl::vector(255,255,0,0); + retval->getAuxAttributeViews()->push_back({ + .composed = { + .encodedDataRange = {.u8=aabb}, + .stride = AttrSize, + .format = EF_R8G8_UNORM, + .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*colors)); + auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); + colors = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, uint8_t> aabb; + aabb.minVx = hlsl::vector(0,0,0,0); + aabb.maxVx = hlsl::vector(255,255,0,0); + retval->getAuxAttributeViews()->push_back({ + .composed = { + .encodedDataRange = {.u8=aabb}, + .stride = AttrSize, + .format = EF_R8G8B8A8_UNORM, + .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + } + + for (auto i = 0ull; i < coneVertexCount; ++i) + { + auto& conePosition = conePositions[i]; + core::vector3df_SIMD newPos(conePosition.x, conePosition.y, conePosition.z); + newPos.rotateYZByRAD(-1.5707963268); - vtxBuf->addUsageFlags(asset::IBuffer::EUF_VERTEX_BUFFER_BIT); - cone.bindings[0] = { 0, std::move(vtxBuf) }; - idxBuf->addUsageFlags(asset::IBuffer::EUF_INDEX_BUFFER_BIT); - cone.indexBuffer = { 0, std::move(idxBuf) }; - cone.indexCount = cone.indexBuffer.buffer->getSize() / sizeof(uint16_t); - cone.indexType = EIT_16BIT; + conePosition = {newPos.x, newPos.y, newPos.z}; + } - return cone; + uint8_t cylinderGlColor[4]; + vtxColor0.toOpenGLColor(cylinderGlColor); + + uint8_t coneGlColor[4]; + vtxColor1.toOpenGLColor(coneGlColor); + + for (auto z = 0ull; z < newArrowVertexCount; ++z) + { + if (z < cylinderVertexCount) + { + positions[z] = cylinderPositions[z]; + normals[z] = cylinderNormals[z]; + uvs[z] = cylinderUvs[z]; + colors[z] = { cylinderGlColor[0], cylinderGlColor[1], cylinderGlColor[2], cylinderGlColor[3] }; + } + else + { + const auto cone_i = z - cylinderVertexCount; + positions[z] = conePositions[cone_i]; + normals[z] = coneNormals[cone_i]; + uvs[z] = { 0, 0 }; + colors[z] = { coneGlColor[0], coneGlColor[1], coneGlColor[2], coneGlColor[3] }; + } + } + + CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); + return retval; } -#endif core::smart_refctd_ptr CGeometryCreator::createRectangle(const hlsl::float32_t2 size) const { From 2d8b7c4918fd8c93ba86e0a4f23b32fef2cb8468 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Wed, 25 Jun 2025 18:29:46 +0700 Subject: [PATCH 2/7] Implement getIndexType convenience function for IPolygonGeometry --- include/nbl/asset/IPolygonGeometry.h | 40 +++++++++++++++------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/include/nbl/asset/IPolygonGeometry.h b/include/nbl/asset/IPolygonGeometry.h index 4d021c178c..97a6cda7d0 100644 --- a/include/nbl/asset/IPolygonGeometry.h +++ b/include/nbl/asset/IPolygonGeometry.h @@ -203,6 +203,26 @@ class IPolygonGeometry : public IIndexableGeometry, public IPolygonG // For User defined semantics inline const core::vector& getAuxAttributeViews() const {return m_auxAttributeViews;} + inline E_INDEX_TYPE getIndexType() const + { + auto indexType = EIT_UNKNOWN; + // disallowed index format + if (base_t::m_indexView) + { + switch (base_t::m_indexView.composed.format) + { + case EF_R16_UINT: + indexType = EIT_16BIT; + break; + case EF_R32_UINT: [[fallthrough]]; + indexType = EIT_32BIT; + break; + default: + break; + } + } + return indexType; + } // Does not set the `transform` or `geometryFlags` fields, because it doesn't care about it. // Also won't set second set of vertex data, opacity mipmaps, etc. @@ -212,30 +232,12 @@ class IPolygonGeometry : public IIndexableGeometry, public IPolygonG // must be a triangle list, but don't want to compare pointers if (m_indexing && m_indexing->knownTopology()==EPT_TRIANGLE_LIST)// && m_indexing->degree() == TriangleList()->degree() && m_indexing->rate() == TriangleList->rate()) { - auto indexType = EIT_UNKNOWN; - // disallowed index format - if (base_t::m_indexView) - { - switch (base_t::m_indexView.composed.format) - { - case EF_R16_UINT: - indexType = EIT_16BIT; - break; - case EF_R32_UINT: [[fallthrough]]; - indexType = EIT_32BIT; - break; - default: - break; - } - if (indexType==EIT_UNKNOWN) - return retval; - } retval.vertexData[0] = base_t::m_positionView.src; retval.indexData = base_t::m_indexView.src; retval.maxVertex = base_t::m_positionView.getElementCount() - 1; retval.vertexStride = base_t::m_positionView.composed.getStride(); retval.vertexFormat = base_t::m_positionView.composed.format; - retval.indexType = indexType; + retval.indexType = getIndexType(); } return retval; } From cdcaae9008dbda95bf5e7241fd3da13415f411db Mon Sep 17 00:00:00 2001 From: kevyuu Date: Sat, 28 Jun 2025 21:51:50 +0700 Subject: [PATCH 3/7] Implement createIcosphere --- src/nbl/asset/utils/CGeometryCreator.cpp | 140 +++++++++++++++++------ 1 file changed, 106 insertions(+), 34 deletions(-) diff --git a/src/nbl/asset/utils/CGeometryCreator.cpp b/src/nbl/asset/utils/CGeometryCreator.cpp index c25a222a53..775d2e2061 100644 --- a/src/nbl/asset/utils/CGeometryCreator.cpp +++ b/src/nbl/asset/utils/CGeometryCreator.cpp @@ -1211,7 +1211,6 @@ core::smart_refctd_ptr CGeometryCreator::createDisk(const f return retval; } -#if 0 /* Helpful Icosphere class implementation used to compute and create icopshere's vertices and indecies. @@ -1224,6 +1223,8 @@ core::smart_refctd_ptr CGeometryCreator::createDisk(const f class Icosphere { public: + using index_t = unsigned int; + Icosphere(float radius = 1.0f, int subdivision = 1, bool smooth = false) : radius(radius), subdivision(subdivision), smooth(smooth), interleavedStride(32) { if (smooth) @@ -1234,27 +1235,27 @@ class Icosphere ~Icosphere() {} - unsigned int getVertexCount() const { return (unsigned int)vertices.size() / 3; } + unsigned int getPositionCount() const { return (unsigned int)vertices.size() / 3; } unsigned int getNormalCount() const { return (unsigned int)normals.size() / 3; } unsigned int getTexCoordCount() const { return (unsigned int)texCoords.size() / 2; } unsigned int getIndexCount() const { return (unsigned int)indices.size(); } unsigned int getLineIndexCount() const { return (unsigned int)lineIndices.size(); } unsigned int getTriangleCount() const { return getIndexCount() / 3; } - unsigned int getVertexSize() const { return (unsigned int)vertices.size() * sizeof(float); } // # of bytes + unsigned int getPositionSize() const { return (unsigned int)vertices.size() * sizeof(float); } // # of bytes unsigned int getNormalSize() const { return (unsigned int)normals.size() * sizeof(float); } unsigned int getTexCoordSize() const { return (unsigned int)texCoords.size() * sizeof(float); } - unsigned int getIndexSize() const { return (unsigned int)indices.size() * sizeof(unsigned int); } + unsigned int getIndexSize() const { return (unsigned int)indices.size() * sizeof(index_t); } unsigned int getLineIndexSize() const { return (unsigned int)lineIndices.size() * sizeof(unsigned int); } - const float* getVertices() const { return vertices.data(); } + const float* getPositions() const { return vertices.data(); } const float* getNormals() const { return normals.data(); } const float* getTexCoords() const { return texCoords.data(); } const unsigned int* getIndices() const { return indices.data(); } const unsigned int* getLineIndices() const { return lineIndices.data(); } // for interleaved vertices: V/N/T - unsigned int getInterleavedVertexCount() const { return getVertexCount(); } // # of vertices + unsigned int getInterleavedVertexCount() const { return getPositionCount(); } // # of vertices unsigned int getInterleavedVertexSize() const { return (unsigned int)interleavedVertices.size() * sizeof(float); } // # of bytes int getInterleavedStride() const { return interleavedStride; } // should be 32 bytes const float* getInterleavedVertices() const { return interleavedVertices.data(); } @@ -2178,38 +2179,109 @@ class Icosphere core::smart_refctd_ptr CGeometryCreator::createIcoSphere(float radius, uint32_t subdivision, bool smooth) const { - Icosphere IcosphereData(radius, subdivision, smooth); - - return_type icosphereGeometry; - constexpr size_t vertexSize = sizeof(IcosphereVertex); + Icosphere icosphere(radius, subdivision, smooth); + + auto retval = core::make_smart_refctd_ptr(); + retval->setIndexing(IPolygonGeometryBase::TriangleList()); + + using namespace hlsl; + + // Create indices + { + auto indexBuffer = asset::ICPUBuffer::create({ icosphere.getIndexSize() }); + memcpy(indexBuffer->getPointer(), icosphere.getIndices(), indexBuffer->getSize()); + + shapes::AABB<4,Icosphere::index_t> aabb; + aabb.minVx[0] = 0; + aabb.maxVx[0] = icosphere.getPositionCount() - 1; + + static_assert(sizeof(Icosphere::index_t) == 2 || sizeof(Icosphere::index_t) == 4); + const auto isIndex16Bit = sizeof(Icosphere::index_t) == 2; + + retval->setIndexView({ + .composed = { + .encodedDataRange = {.u32=aabb}, + .stride = sizeof(Icosphere::index_t), + .format = isIndex16Bit ? EF_R16_UINT : EF_R32_UINT, + .rangeFormat = isIndex16Bit? IGeometryBase::EAABBFormat::U16 : IGeometryBase::EAABBFormat::U32 + }, + .src = {.offset=0,.size=icosphere.getIndexSize(),.buffer = std::move(indexBuffer)} + }); + } - icosphereGeometry.inputParams = - { 0b111u,0b1u, + { { - {0u, EF_R32G32B32_SFLOAT, offsetof(IcosphereVertex,pos)}, - {0u, EF_R32G32B32_SFLOAT, offsetof(IcosphereVertex,normals)}, - {0u, EF_R32G32_SFLOAT, offsetof(IcosphereVertex,uv)} - }, - {vertexSize,SVertexInputBindingParams::EVIR_PER_VERTEX} - }; - - auto vertexBuffer = asset::ICPUBuffer::create({ IcosphereData.getInterleavedVertexSize() }); - auto indexBuffer = asset::ICPUBuffer::create({ IcosphereData.getIndexSize() }); - - memcpy(vertexBuffer->getPointer(), IcosphereData.getInterleavedVertices(), vertexBuffer->getSize()); - memcpy(indexBuffer->getPointer(), IcosphereData.getIndices(), indexBuffer->getSize()); - - vertexBuffer->addUsageFlags(asset::IBuffer::EUF_VERTEX_BUFFER_BIT); - icosphereGeometry.bindings[0] = { 0, std::move(vertexBuffer) }; - indexBuffer->addUsageFlags(asset::IBuffer::EUF_INDEX_BUFFER_BIT); - icosphereGeometry.indexBuffer = { 0, std::move(indexBuffer) }; - icosphereGeometry.indexCount = IcosphereData.getIndexCount(); - icosphereGeometry.indexType = EIT_32BIT; - - return icosphereGeometry; + using position_t = float32_t3; + constexpr auto AttrSize = sizeof(position_t); + auto buff = ICPUBuffer::create({ icosphere.getPositionCount() * AttrSize, IBuffer::EUF_NONE }); + const auto positions = reinterpret_cast(buff->getPointer()); + memcpy(positions, icosphere.getPositions(), icosphere.getPositionSize()); + shapes::AABB<4, float32_t> aabb; + aabb.maxVx = float32_t4(radius, radius, radius, 0.f); + aabb.minVx = -aabb.maxVx; + retval->setPositionView({ + .composed = { + .encodedDataRange = {.f32 = aabb}, + .stride = AttrSize, + .format = EF_R32G32B32_SFLOAT, + .rangeFormat = IGeometryBase::EAABBFormat::F32 + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + using normal_t = float32_t3; + constexpr auto AttrSize = sizeof(normal_t); + auto buff = ICPUBuffer::create({icosphere.getNormalSize(), IBuffer::EUF_NONE}); + const auto normals = reinterpret_cast(buff->getPointer()); + memcpy(normals, icosphere.getNormals(), icosphere.getNormalSize()); + shapes::AABB<4,float32_t> aabb; + aabb.maxVx = float32_t4(1, 1, 1, 0.f); + aabb.minVx = -aabb.maxVx; + retval->setNormalView({ + .composed = { + .encodedDataRange = {.f32 = aabb}, + .stride = AttrSize, + .format = EF_R32G32B32_SFLOAT, + .rangeFormat = IGeometryBase::EAABBFormat::F32 + }, + .src = {.offset = 0,.size = buff->getSize(),.buffer = std::move(buff)}, + }); + } + { + using uv_t = uint32_t; + constexpr auto AttrSize = sizeof(uv_t); + auto buff = ICPUBuffer::create({AttrSize * icosphere.getTexCoordCount(), IBuffer::EUF_NONE}); + const auto uvs = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, uint16_t> aabb; + aabb.minVx = uint16_t4(0,0,0,0); + aabb.maxVx = uint16_t4(0xFFFF,0xFFFF,0,0); + retval->getAuxAttributeViews()->push_back({ + .composed = { + .encodedDataRange = {.u16=aabb}, + .stride = AttrSize, + .format = EF_R16G16_UNORM, + .rangeFormat = IGeometryBase::EAABBFormat::U16_NORM + }, + .src = {.offset=0,.size=buff->getSize(),.buffer=std::move(buff)} + }); + for (auto uv_i = 0u; uv_i < icosphere.getTexCoordCount(); uv_i++) + { + const auto texCoords = icosphere.getTexCoords(); + const auto f32_uv = float32_t2{ texCoords[2 * uv_i], texCoords[(2 * uv_i) + 1] }; + uvs[uv_i] = packUnorm2x16(f32_uv); + } + } + } + + CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); + return retval; } -#endif } // end namespace nbl::asset From 2e063d73bc98248fa874187bb306729a2f06485b Mon Sep 17 00:00:00 2001 From: kevyuu Date: Sat, 28 Jun 2025 21:52:18 +0700 Subject: [PATCH 4/7] Remove color parameter from create --- include/nbl/asset/utils/CGeometryCreator.h | 7 +- src/nbl/asset/utils/CGeometryCreator.cpp | 124 +-------------------- 2 files changed, 6 insertions(+), 125 deletions(-) diff --git a/include/nbl/asset/utils/CGeometryCreator.h b/include/nbl/asset/utils/CGeometryCreator.h index 87d7a0ef5e..ca6fff1790 100644 --- a/include/nbl/asset/utils/CGeometryCreator.h +++ b/include/nbl/asset/utils/CGeometryCreator.h @@ -61,8 +61,7 @@ class NBL_API2 CGeometryCreator final : public core::IReferenceCounted core::smart_refctd_ptr createArrow(const uint32_t tesselationCylinder = 4, const uint32_t tesselationCone = 8, const float height = 1.f, const float cylinderHeight = 0.6f, const float widthCylinder = 0.05f, - const float widthCone = 0.3f, const video::SColor colorCylinder = 0xFFFFFFFF, - const video::SColor colorCone = 0xFFFFFFFF) const; + const float widthCone = 0.3f) const; //! Create a sphere mesh. @@ -87,7 +86,7 @@ class NBL_API2 CGeometryCreator final : public core::IReferenceCounted */ core::smart_refctd_ptr createCylinder(float radius, float length, uint32_t tesselation, - const video::SColor& color=video::SColor(0xffffffff), CQuantNormalCache* const quantNormalCacheOverride=nullptr) const; + CQuantNormalCache* const quantNormalCacheOverride=nullptr) const; //! Create a cone mesh. /** @@ -100,8 +99,6 @@ class NBL_API2 CGeometryCreator final : public core::IReferenceCounted \return Generated mesh. */ core::smart_refctd_ptr createCone(float radius, float length, uint32_t tesselation, - const video::SColor& colorTop=video::SColor(0xffffffff), - const video::SColor& colorBottom=video::SColor(0xffffffff), float oblique=0.f, CQuantNormalCache* const quantNormalCacheOverride=nullptr) const; core::smart_refctd_ptr createRectangle(const hlsl::float32_t2 size={0.5f,0.5f}) const; diff --git a/src/nbl/asset/utils/CGeometryCreator.cpp b/src/nbl/asset/utils/CGeometryCreator.cpp index 775d2e2061..c012df8826 100644 --- a/src/nbl/asset/utils/CGeometryCreator.cpp +++ b/src/nbl/asset/utils/CGeometryCreator.cpp @@ -295,7 +295,6 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float hlsl::float32_t3* positions; hlsl::vector* normals; hlsl::vector* uvs; - hlsl::vector* colors; { { constexpr auto AttrSize = sizeof(decltype(*positions)); @@ -360,36 +359,10 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float } }); } - { - constexpr auto AttrSize = sizeof(decltype(*colors)); - auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); - colors = reinterpret_cast(buff->getPointer()); - shapes::AABB<4, uint8_t> aabb; - aabb.minVx = hlsl::vector(0,0,0,0); - aabb.maxVx = hlsl::vector(255,255,0,0); - retval->getAuxAttributeViews()->push_back({ - .composed = { - .encodedDataRange = {.u8=aabb}, - .stride = AttrSize, - .format = EF_R8G8B8A8_UNORM, - .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM - }, - .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff), - } - }); - } } // fill vertices { - for (size_t i = 0; i < vertexCount; i++) - { - colors[i] = { 255,255,255,255 }; - } - // calculate the angle which separates all points in a circle const float AngleX = 2 * core::PI() / polyCountX; const float AngleY = core::PI() / polyCountY; @@ -470,7 +443,7 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float core::smart_refctd_ptr CGeometryCreator::createCylinder( float radius, float length, - uint32_t tesselation, const video::SColor& color, CQuantNormalCache* const quantNormalCacheOverride) const + uint32_t tesselation, CQuantNormalCache* const quantNormalCacheOverride) const { using namespace hlsl; @@ -521,7 +494,6 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( hlsl::float32_t3* positions; hlsl::vector* normals; hlsl::vector* uvs; - hlsl::vector* colors; { { constexpr auto AttrSize = sizeof(decltype(*positions)); @@ -586,32 +558,8 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( } }); } - { - constexpr auto AttrSize = sizeof(decltype(*colors)); - auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); - colors = reinterpret_cast(buff->getPointer()); - shapes::AABB<4, uint8_t> aabb; - aabb.minVx = hlsl::vector(0,0,0,0); - aabb.maxVx = hlsl::vector(255,255,0,0); - retval->getAuxAttributeViews()->push_back({ - .composed = { - .encodedDataRange = {.u8=aabb}, - .stride = AttrSize, - .format = EF_R8G8B8A8_UNORM, - .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM - }, - .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff), - } - }); - } } - uint8_t glcolor[4]; - color.toOpenGLColor(glcolor); - const float tesselationRec = core::reciprocal_approxim(static_cast(tesselation)); const float step = 2.f * core::PI() * tesselationRec; for (uint32_t i = 0u; i < tesselation; ++i) @@ -624,12 +572,10 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( positions[i] = { p.x, p.y, p.z }; memcpy(normals + i, &n, sizeof(n)); uvs[i] = { f_i * tesselationRec, 0.0 }; - colors[i] = { glcolor[0], glcolor[1], glcolor[2], glcolor[3] }; positions[i + halfIx] = { p.x, p.y, length }; normals[i + halfIx] = normals[i]; uvs[i + halfIx] = { 1.0f, 0.0f }; - colors[i + halfIx] = { glcolor[0], glcolor[1], glcolor[2], glcolor[3] }; } CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); @@ -638,8 +584,6 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( core::smart_refctd_ptr CGeometryCreator::createCone( float radius, float length, uint32_t tesselation, - const video::SColor& colorTop, - const video::SColor& colorBottom, float oblique, CQuantNormalCache* const quantNormalCacheOverride) const { @@ -689,7 +633,6 @@ core::smart_refctd_ptr CGeometryCreator::createCone( // Create vertex attributes with NONE usage because we have no clue how they'll be used hlsl::float32_t3* positions; hlsl::vector* normals; - hlsl::vector* colors; { { constexpr auto AttrSize = sizeof(decltype(*positions)); @@ -733,34 +676,8 @@ core::smart_refctd_ptr CGeometryCreator::createCone( } }); } - { - constexpr auto AttrSize = sizeof(decltype(*colors)); - auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); - colors = reinterpret_cast(buff->getPointer()); - shapes::AABB<4, uint8_t> aabb; - aabb.minVx = hlsl::vector(0,0,0,0); - aabb.maxVx = hlsl::vector(255,255,0,0); - retval->getAuxAttributeViews()->push_back({ - .composed = { - .encodedDataRange = {.u8=aabb}, - .stride = AttrSize, - .format = EF_R8G8B8A8_UNORM, - .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM - }, - .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff), - } - }); - } } - uint8_t glcolor[4]; - colorBottom.toOpenGLColor(glcolor); - vector vertexBottomColor = { glcolor[0], glcolor[1], glcolor[2], glcolor[3] }; - std::fill_n(colors, vertexCount, vertexBottomColor); - const float step = (2.f*core::PI()) / tesselation; const core::vectorSIMDf apexVertexCoords(oblique, length, 0.0f); @@ -808,9 +725,7 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( const float height, const float cylinderHeight, const float width0, - const float width1, - const video::SColor vtxColor0, - const video::SColor vtxColor1 + const float width1 ) const { assert(height > cylinderHeight); @@ -818,10 +733,9 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( using position_t = hlsl::float32_t3; using normal_t = hlsl::vector; using uv_t = hlsl::vector; - using color_t = hlsl::vector; - auto cylinder = createCylinder(width0, cylinderHeight, tesselationCylinder, vtxColor0); - auto cone = createCone(width1, height-cylinderHeight, tesselationCone, vtxColor1, vtxColor1); + auto cylinder = createCylinder(width0, cylinderHeight, tesselationCylinder); + auto cone = createCone(width1, height-cylinderHeight, tesselationCone); auto cylinderPositions = reinterpret_cast(cylinder->getPositionView().src.buffer->getPointer()); auto conePositions = reinterpret_cast(cone->getPositionView().src.buffer->getPointer()); @@ -881,7 +795,6 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( // Create vertex attributes with NONE usage because we have no clue how they'll be used hlsl::float32_t3* positions; hlsl::vector* normals; - hlsl::vector* colors; hlsl::vector* uvs; { { @@ -948,27 +861,6 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( } }); } - { - constexpr auto AttrSize = sizeof(decltype(*colors)); - auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); - colors = reinterpret_cast(buff->getPointer()); - shapes::AABB<4, uint8_t> aabb; - aabb.minVx = hlsl::vector(0,0,0,0); - aabb.maxVx = hlsl::vector(255,255,0,0); - retval->getAuxAttributeViews()->push_back({ - .composed = { - .encodedDataRange = {.u8=aabb}, - .stride = AttrSize, - .format = EF_R8G8B8A8_UNORM, - .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM - }, - .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff), - } - }); - } } for (auto i = 0ull; i < coneVertexCount; ++i) @@ -980,12 +872,6 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( conePosition = {newPos.x, newPos.y, newPos.z}; } - uint8_t cylinderGlColor[4]; - vtxColor0.toOpenGLColor(cylinderGlColor); - - uint8_t coneGlColor[4]; - vtxColor1.toOpenGLColor(coneGlColor); - for (auto z = 0ull; z < newArrowVertexCount; ++z) { if (z < cylinderVertexCount) @@ -993,7 +879,6 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( positions[z] = cylinderPositions[z]; normals[z] = cylinderNormals[z]; uvs[z] = cylinderUvs[z]; - colors[z] = { cylinderGlColor[0], cylinderGlColor[1], cylinderGlColor[2], cylinderGlColor[3] }; } else { @@ -1001,7 +886,6 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( positions[z] = conePositions[cone_i]; normals[z] = coneNormals[cone_i]; uvs[z] = { 0, 0 }; - colors[z] = { coneGlColor[0], coneGlColor[1], coneGlColor[2], coneGlColor[3] }; } } From f0b50642ad95492ba1490ce5884c0d2774edf311 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Sat, 28 Jun 2025 21:57:27 +0700 Subject: [PATCH 5/7] Fix indentation --- src/nbl/asset/utils/CGeometryCreator.cpp | 430 +++++++++++------------ 1 file changed, 215 insertions(+), 215 deletions(-) diff --git a/src/nbl/asset/utils/CGeometryCreator.cpp b/src/nbl/asset/utils/CGeometryCreator.cpp index c012df8826..88e93e4d2c 100644 --- a/src/nbl/asset/utils/CGeometryCreator.cpp +++ b/src/nbl/asset/utils/CGeometryCreator.cpp @@ -204,7 +204,7 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float polyCountY = 2; const uint32_t polyCountXPitch = polyCountX + 1; // get to same vertex on next level - const size_t vertexCount = (polyCountXPitch * polyCountY) + 2; + const size_t vertexCount = (polyCountXPitch * polyCountY) + 2; auto retval = core::make_smart_refctd_ptr(); retval->setIndexing(IPolygonGeometryBase::TriangleList()); @@ -212,11 +212,11 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float // Create indices using index_t = uint32_t; { - const auto indexCount = (polyCountX * polyCountY) * 6; + const auto indexCount = (polyCountX * polyCountY) * 6; const auto bytesize = sizeof(index_t) * indexCount; auto indices = ICPUBuffer::create({bytesize,IBuffer::EUF_INDEX_BUFFER_BIT}); auto indexPtr = reinterpret_cast(indices->getPointer()); - uint32_t level = 0; + uint32_t level = 0; size_t indexAddIx = 0; for (uint32_t p1 = 0; p1 < polyCountY - 1; ++p1) { @@ -293,7 +293,7 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float // Create vertex attributes with NONE usage because we have no clue how they'll be used hlsl::float32_t3* positions; - hlsl::vector* normals; + hlsl::vector* normals; hlsl::vector* uvs; { { @@ -311,9 +311,9 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float .rangeFormat = IGeometryBase::EAABBFormat::F32 }, .src = { - .offset=0, - .size = buff->getSize(), - .buffer = std::move(buff), + .offset=0, + .size = buff->getSize(), + .buffer = std::move(buff), } }); } @@ -332,9 +332,9 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM }, .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff) + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff) } }); } @@ -353,9 +353,9 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM }, .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff), + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), } }); } @@ -373,68 +373,68 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float double ay = 0;//AngleY / 2; auto vertex_i = 0; - for (uint32_t y = 0; y < polyCountY; ++y) - { - ay += AngleY; - const double sinay = sin(ay); - axz = 0; + for (uint32_t y = 0; y < polyCountY; ++y) + { + ay += AngleY; + const double sinay = sin(ay); + axz = 0; - // calculate the necessary vertices without the doubled one + // calculate the necessary vertices without the doubled one const auto old_vertex_i = vertex_i; - for (uint32_t xz = 0; xz < polyCountX; ++xz) - { - // calculate points position - - float32_t3 pos(static_cast(cos(axz) * sinay), - static_cast(cos(ay)), - static_cast(sin(axz) * sinay)); - // for spheres the normal is the position - core::vectorSIMDf normal(&pos.x); - normal.makeSafe3D(); - const auto quantizedNormal = quantNormalCache->quantize(normal); - pos *= radius; - - // calculate texture coordinates via sphere mapping - // tu is the same on each level, so only calculate once - float tu = 0.5f; - //if (y==0) - //{ - if (normal.Y != -1.0f && normal.Y != 1.0f) - tu = static_cast(acos(core::clamp(normal.X / sinay, -1.0, 1.0)) * 0.5 * core::RECIPROCAL_PI()); - if (normal.Z < 0.0f) - tu = 1 - tu; - //} - //else - //tu = ((float*)(tmpMem+(i-polyCountXPitch)*vertexSize))[4]; + for (uint32_t xz = 0; xz < polyCountX; ++xz) + { + // calculate points position + + float32_t3 pos(static_cast(cos(axz) * sinay), + static_cast(cos(ay)), + static_cast(sin(axz) * sinay)); + // for spheres the normal is the position + core::vectorSIMDf normal(&pos.x); + normal.makeSafe3D(); + const auto quantizedNormal = quantNormalCache->quantize(normal); + pos *= radius; + + // calculate texture coordinates via sphere mapping + // tu is the same on each level, so only calculate once + float tu = 0.5f; + //if (y==0) + //{ + if (normal.Y != -1.0f && normal.Y != 1.0f) + tu = static_cast(acos(core::clamp(normal.X / sinay, -1.0, 1.0)) * 0.5 * core::RECIPROCAL_PI()); + if (normal.Z < 0.0f) + tu = 1 - tu; + //} + //else + //tu = ((float*)(tmpMem+(i-polyCountXPitch)*vertexSize))[4]; positions[vertex_i] = pos; uvs[vertex_i] = { packSnorm(tu), packSnorm(static_cast(ay * core::RECIPROCAL_PI())) }; memcpy(normals + vertex_i, &quantizedNormal, sizeof(quantizedNormal)); vertex_i++; - axz += AngleX; - } - // This is the doubled vertex on the initial position + axz += AngleX; + } + // This is the doubled vertex on the initial position - positions[vertex_i] = positions[old_vertex_i]; + positions[vertex_i] = positions[old_vertex_i]; uvs[vertex_i] = { 127, uvs[old_vertex_i].y }; normals[vertex_i] = normals[old_vertex_i]; vertex_i++; - } + } // the vertex at the top of the sphere positions[vertex_i] = { 0.f, radius, 0.f }; uvs[vertex_i] = { 0, 63}; const auto quantizedTopNormal = quantNormalCache->quantize(core::vectorSIMDf(0.f, 1.f, 0.f)); - memcpy(normals + vertex_i, &quantizedTopNormal, sizeof(quantizedTopNormal)); + memcpy(normals + vertex_i, &quantizedTopNormal, sizeof(quantizedTopNormal)); // the vertex at the bottom of the sphere vertex_i++; positions[vertex_i] = { 0.f, -radius, 0.f }; uvs[vertex_i] = { 63, 127}; const auto quantizedBottomNormal = quantNormalCache->quantize(core::vectorSIMDf(0.f, -1.f, 0.f)); - memcpy(normals + vertex_i, &quantizedBottomNormal, sizeof(quantizedBottomNormal)); + memcpy(normals + vertex_i, &quantizedBottomNormal, sizeof(quantizedBottomNormal)); } CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); @@ -449,8 +449,8 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( CQuantNormalCache* const quantNormalCache = quantNormalCacheOverride == nullptr ? m_params.normalCache.get() : quantNormalCacheOverride; - const uint16_t halfIx = static_cast(tesselation); - const uint16_t vertexCount = 2 * static_cast(tesselation); + const uint16_t halfIx = static_cast(tesselation); + const uint16_t vertexCount = 2 * static_cast(tesselation); auto retval = core::make_smart_refctd_ptr(); retval->setIndexing(IPolygonGeometryBase::TriangleList()); @@ -458,20 +458,20 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( // Create indices using index_t = uint16_t; { - constexpr uint32_t RowCount = 2u; - const auto IndexCount = RowCount * 3 * tesselation; + constexpr uint32_t RowCount = 2u; + const auto IndexCount = RowCount * 3 * tesselation; const auto bytesize = sizeof(index_t) * IndexCount; auto indices = ICPUBuffer::create({bytesize,IBuffer::EUF_INDEX_BUFFER_BIT}); auto u = reinterpret_cast(indices->getPointer()); - for (uint16_t i = 0u, j = 0u; i < halfIx; ++i) - { - u[j++] = i; - u[j++] = (i + 1u) != halfIx ? (i + 1u):0u; - u[j++] = i + halfIx; - u[j++] = i + halfIx; - u[j++] = (i + 1u)!= halfIx ? (i + 1u):0u; - u[j++] = (i + 1u)!= halfIx ? (i + 1u + halfIx) : halfIx; - } + for (uint16_t i = 0u, j = 0u; i < halfIx; ++i) + { + u[j++] = i; + u[j++] = (i + 1u) != halfIx ? (i + 1u):0u; + u[j++] = i + halfIx; + u[j++] = i + halfIx; + u[j++] = (i + 1u)!= halfIx ? (i + 1u):0u; + u[j++] = (i + 1u)!= halfIx ? (i + 1u + halfIx) : halfIx; + } shapes::AABB<4,index_t> aabb; aabb.minVx[0] = 0; @@ -492,7 +492,7 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( // Create vertex attributes with NONE usage because we have no clue how they'll be used hlsl::float32_t3* positions; - hlsl::vector* normals; + hlsl::vector* normals; hlsl::vector* uvs; { { @@ -510,9 +510,9 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( .rangeFormat = IGeometryBase::EAABBFormat::F32 }, .src = { - .offset=0, - .size = buff->getSize(), - .buffer = std::move(buff), + .offset=0, + .size = buff->getSize(), + .buffer = std::move(buff), } }); } @@ -531,9 +531,9 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM }, .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff) + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff) } }); } @@ -552,46 +552,46 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM }, .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff), + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), } }); } } - const float tesselationRec = core::reciprocal_approxim(static_cast(tesselation)); - const float step = 2.f * core::PI() * tesselationRec; - for (uint32_t i = 0u; i < tesselation; ++i) - { + const float tesselationRec = core::reciprocal_approxim(static_cast(tesselation)); + const float step = 2.f * core::PI() * tesselationRec; + for (uint32_t i = 0u; i < tesselation; ++i) + { const auto f_i = static_cast(i); - core::vectorSIMDf p(std::cos(f_i * step), std::sin(f_i * step), 0.f); - p *= radius; - const auto n = quantNormalCache->quantize(core::normalize(p)); + core::vectorSIMDf p(std::cos(f_i * step), std::sin(f_i * step), 0.f); + p *= radius; + const auto n = quantNormalCache->quantize(core::normalize(p)); - positions[i] = { p.x, p.y, p.z }; + positions[i] = { p.x, p.y, p.z }; memcpy(normals + i, &n, sizeof(n)); uvs[i] = { f_i * tesselationRec, 0.0 }; - positions[i + halfIx] = { p.x, p.y, length }; - normals[i + halfIx] = normals[i]; - uvs[i + halfIx] = { 1.0f, 0.0f }; - } + positions[i + halfIx] = { p.x, p.y, length }; + normals[i + halfIx] = normals[i]; + uvs[i + halfIx] = { 1.0f, 0.0f }; + } CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); return retval; } core::smart_refctd_ptr CGeometryCreator::createCone( - float radius, float length, uint32_t tesselation, - float oblique, CQuantNormalCache* const quantNormalCacheOverride) const + float radius, float length, uint32_t tesselation, + float oblique, CQuantNormalCache* const quantNormalCacheOverride) const { using namespace hlsl; CQuantNormalCache* const quantNormalCache = quantNormalCacheOverride == nullptr ? m_params.normalCache.get() : quantNormalCacheOverride; - const uint16_t vertexCount = 2 * static_cast(tesselation); + const uint16_t vertexCount = 2 * static_cast(tesselation); auto retval = core::make_smart_refctd_ptr(); retval->setIndexing(IPolygonGeometryBase::TriangleList()); @@ -599,19 +599,19 @@ core::smart_refctd_ptr CGeometryCreator::createCone( // Create indices using index_t = uint16_t; { - constexpr uint32_t RowCount = 2u; - const auto IndexCount = 3 * tesselation; + constexpr uint32_t RowCount = 2u; + const auto IndexCount = 3 * tesselation; const auto bytesize = sizeof(index_t) * IndexCount; auto indices = ICPUBuffer::create({bytesize,IBuffer::EUF_INDEX_BUFFER_BIT}); auto u = reinterpret_cast(indices->getPointer()); - const uint32_t firstIndexOfBaseVertices = 0; - const uint32_t firstIndexOfApexVertices = tesselation; - for (uint32_t i = 0; i < tesselation; i++) - { - u[i * 3] = firstIndexOfApexVertices + i; - u[(i * 3) + 1] = firstIndexOfBaseVertices + i; - u[(i * 3) + 2] = i == (tesselation - 1) ? firstIndexOfBaseVertices : firstIndexOfBaseVertices + i + 1; - } + const uint32_t firstIndexOfBaseVertices = 0; + const uint32_t firstIndexOfApexVertices = tesselation; + for (uint32_t i = 0; i < tesselation; i++) + { + u[i * 3] = firstIndexOfApexVertices + i; + u[(i * 3) + 1] = firstIndexOfBaseVertices + i; + u[(i * 3) + 2] = i == (tesselation - 1) ? firstIndexOfBaseVertices : firstIndexOfBaseVertices + i + 1; + } shapes::AABB<4,index_t> aabb; aabb.minVx[0] = 0; @@ -632,53 +632,53 @@ core::smart_refctd_ptr CGeometryCreator::createCone( // Create vertex attributes with NONE usage because we have no clue how they'll be used hlsl::float32_t3* positions; - hlsl::vector* normals; - { - { - constexpr auto AttrSize = sizeof(decltype(*positions)); - auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); - positions = reinterpret_cast(buff->getPointer()); - shapes::AABB<4, float32_t> aabb; - aabb.maxVx = float32_t4(radius, radius, length, 0.0f); - aabb.minVx = float32_t4(-radius, -radius, 0.0f, 0.0f); - retval->setPositionView({ - .composed = { - .encodedDataRange = {.f32 = aabb}, - .stride = AttrSize, - .format = EF_R32G32B32_SFLOAT, - .rangeFormat = IGeometryBase::EAABBFormat::F32 - }, - .src = { - .offset=0, - .size = buff->getSize(), - .buffer = std::move(buff), - } - }); - } - { - constexpr auto AttrSize = sizeof(decltype(*normals)); - auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); - normals = reinterpret_cast(buff->getPointer()); - shapes::AABB<4, int8_t> aabb; - aabb.maxVx = hlsl::vector(127,127,127,0); - aabb.minVx = -aabb.maxVx; - retval->setNormalView({ - .composed = { - .encodedDataRange = {.s8=aabb}, - .stride = AttrSize, - .format = NormalFormat, - .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM - }, - .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff) - } - }); - } - } - - const float step = (2.f*core::PI()) / tesselation; + hlsl::vector* normals; + { + { + constexpr auto AttrSize = sizeof(decltype(*positions)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + positions = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, float32_t> aabb; + aabb.maxVx = float32_t4(radius, radius, length, 0.0f); + aabb.minVx = float32_t4(-radius, -radius, 0.0f, 0.0f); + retval->setPositionView({ + .composed = { + .encodedDataRange = {.f32 = aabb}, + .stride = AttrSize, + .format = EF_R32G32B32_SFLOAT, + .rangeFormat = IGeometryBase::EAABBFormat::F32 + }, + .src = { + .offset=0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*normals)); + auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); + normals = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, int8_t> aabb; + aabb.maxVx = hlsl::vector(127,127,127,0); + aabb.minVx = -aabb.maxVx; + retval->setNormalView({ + .composed = { + .encodedDataRange = {.s8=aabb}, + .stride = AttrSize, + .format = NormalFormat, + .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff) + } + }); + } + } + + const float step = (2.f*core::PI()) / tesselation; const core::vectorSIMDf apexVertexCoords(oblique, length, 0.0f); @@ -728,14 +728,14 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( const float width1 ) const { - assert(height > cylinderHeight); + assert(height > cylinderHeight); using position_t = hlsl::float32_t3; using normal_t = hlsl::vector; using uv_t = hlsl::vector; - auto cylinder = createCylinder(width0, cylinderHeight, tesselationCylinder); - auto cone = createCone(width1, height-cylinderHeight, tesselationCone); + auto cylinder = createCylinder(width0, cylinderHeight, tesselationCylinder); + auto cone = createCone(width1, height-cylinderHeight, tesselationCone); auto cylinderPositions = reinterpret_cast(cylinder->getPositionView().src.buffer->getPointer()); auto conePositions = reinterpret_cast(cone->getPositionView().src.buffer->getPointer()); @@ -794,52 +794,52 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( // Create vertex attributes with NONE usage because we have no clue how they'll be used hlsl::float32_t3* positions; - hlsl::vector* normals; + hlsl::vector* normals; hlsl::vector* uvs; - { - { - constexpr auto AttrSize = sizeof(decltype(*positions)); - auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); - positions = reinterpret_cast(buff->getPointer()); - shapes::AABB<4, float32_t> aabb; + { + { + constexpr auto AttrSize = sizeof(decltype(*positions)); + auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); + positions = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, float32_t> aabb; //TODO(kevyuu): Calculate arrow aabb - aabb.maxVx = hlsl::vector(127,127,127,0); - aabb.minVx = -aabb.maxVx; - retval->setPositionView({ - .composed = { - .encodedDataRange = {.f32 = aabb}, - .stride = AttrSize, - .format = EF_R32G32B32_SFLOAT, - .rangeFormat = IGeometryBase::EAABBFormat::F32 - }, - .src = { - .offset=0, - .size = buff->getSize(), - .buffer = std::move(buff), - } - }); - } - { - constexpr auto AttrSize = sizeof(decltype(*normals)); - auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); - normals = reinterpret_cast(buff->getPointer()); - shapes::AABB<4, int8_t> aabb; - aabb.maxVx = hlsl::vector(127,127,127,0); - aabb.minVx = -aabb.maxVx; - retval->setNormalView({ - .composed = { - .encodedDataRange = {.s8=aabb}, - .stride = AttrSize, - .format = NormalFormat, - .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM - }, - .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff) - } - }); - } + aabb.maxVx = hlsl::vector(127,127,127,0); + aabb.minVx = -aabb.maxVx; + retval->setPositionView({ + .composed = { + .encodedDataRange = {.f32 = aabb}, + .stride = AttrSize, + .format = EF_R32G32B32_SFLOAT, + .rangeFormat = IGeometryBase::EAABBFormat::F32 + }, + .src = { + .offset=0, + .size = buff->getSize(), + .buffer = std::move(buff), + } + }); + } + { + constexpr auto AttrSize = sizeof(decltype(*normals)); + auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); + normals = reinterpret_cast(buff->getPointer()); + shapes::AABB<4, int8_t> aabb; + aabb.maxVx = hlsl::vector(127,127,127,0); + aabb.minVx = -aabb.maxVx; + retval->setNormalView({ + .composed = { + .encodedDataRange = {.s8=aabb}, + .stride = AttrSize, + .format = NormalFormat, + .rangeFormat = IGeometryBase::EAABBFormat::S8_NORM + }, + .src = { + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff) + } + }); + } { constexpr auto AttrSize = sizeof(decltype(*uvs)); auto buff = ICPUBuffer::create({{AttrSize * newArrowVertexCount,IBuffer::EUF_NONE}}); @@ -855,21 +855,21 @@ core::smart_refctd_ptr CGeometryCreator::createArrow( .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM }, .src = { - .offset = 0, - .size = buff->getSize(), - .buffer = std::move(buff), + .offset = 0, + .size = buff->getSize(), + .buffer = std::move(buff), } }); } - } - + } + for (auto i = 0ull; i < coneVertexCount; ++i) { auto& conePosition = conePositions[i]; core::vector3df_SIMD newPos(conePosition.x, conePosition.y, conePosition.z); newPos.rotateYZByRAD(-1.5707963268); - conePosition = {newPos.x, newPos.y, newPos.z}; + conePosition = {newPos.x, newPos.y, newPos.z}; } for (auto z = 0ull; z < newArrowVertexCount; ++z) @@ -1100,8 +1100,8 @@ core::smart_refctd_ptr CGeometryCreator::createDisk(const f and create icopshere's vertices and indecies. Polyhedron subdividing icosahedron (20 tris) by N-times iteration - The icosphere with N=1 (default) has 80 triangles by subdividing a triangle - of icosahedron into 4 triangles. If N=0, it is identical to icosahedron. + The icosphere with N=1 (default) has 80 triangles by subdividing a triangle + of icosahedron into 4 triangles. If N=0, it is identical to icosahedron. */ class Icosphere @@ -1240,14 +1240,14 @@ class Icosphere texture coordinate is shared or no. If it is on the line segments, it is also non-shared point - 00 01 02 03 04 - /\ /\ /\ /\ /\ - / \/ \/ \/ \/ \ + 00 01 02 03 04 + /\ /\ /\ /\ /\ + / \/ \/ \/ \/ \ 05 06 07 08 09 \ - \ 10 11 12 13 14 + \ 10 11 12 13 14 \ /\ /\ /\ /\ / \/ \/ \/ \/ \/ - 15 16 17 18 19 + 15 16 17 18 19 */ static inline bool isSharedTexCoord(const float t[2]) @@ -1813,7 +1813,7 @@ class Icosphere v1 / \ newV1 *---* newV3 - / \ / \ + / \ / \ v2---*---v3 newV2 */ @@ -1979,8 +1979,8 @@ class Icosphere add 7 sub edge lines per triangle to array using 6 indices (CCW) i1 / : (i1, i2) - i2---i6 : (i2, i6) - / \ / : (i2, i3), (i2, i4), (i6, i4) + i2---i6 : (i2, i6) + / \ / : (i2, i3), (i2, i4), (i6, i4) i3---i4---i5 : (i3, i4), (i4, i5) */ @@ -2073,8 +2073,8 @@ core::smart_refctd_ptr CGeometryCreator::createIcoSphere(fl // Create indices { - auto indexBuffer = asset::ICPUBuffer::create({ icosphere.getIndexSize() }); - memcpy(indexBuffer->getPointer(), icosphere.getIndices(), indexBuffer->getSize()); + auto indexBuffer = asset::ICPUBuffer::create({ icosphere.getIndexSize() }); + memcpy(indexBuffer->getPointer(), icosphere.getIndices(), indexBuffer->getSize()); shapes::AABB<4,Icosphere::index_t> aabb; aabb.minVx[0] = 0; @@ -2118,7 +2118,7 @@ core::smart_refctd_ptr CGeometryCreator::createIcoSphere(fl } }); } - { + { using normal_t = float32_t3; constexpr auto AttrSize = sizeof(normal_t); auto buff = ICPUBuffer::create({icosphere.getNormalSize(), IBuffer::EUF_NONE}); @@ -2136,8 +2136,8 @@ core::smart_refctd_ptr CGeometryCreator::createIcoSphere(fl }, .src = {.offset = 0,.size = buff->getSize(),.buffer = std::move(buff)}, }); - } - { + } + { using uv_t = uint32_t; constexpr auto AttrSize = sizeof(uv_t); auto buff = ICPUBuffer::create({AttrSize * icosphere.getTexCoordCount(), IBuffer::EUF_NONE}); @@ -2160,7 +2160,7 @@ core::smart_refctd_ptr CGeometryCreator::createIcoSphere(fl const auto f32_uv = float32_t2{ texCoords[2 * uv_i], texCoords[(2 * uv_i) + 1] }; uvs[uv_i] = packUnorm2x16(f32_uv); } - } + } } CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); From 68a689cbbaefb3210a5715940fae0d82f38f47b7 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Sun, 29 Jun 2025 15:21:20 +0700 Subject: [PATCH 6/7] Fix normal and uv type --- src/nbl/asset/utils/CGeometryCreator.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nbl/asset/utils/CGeometryCreator.cpp b/src/nbl/asset/utils/CGeometryCreator.cpp index 88e93e4d2c..0a5dd5920e 100644 --- a/src/nbl/asset/utils/CGeometryCreator.cpp +++ b/src/nbl/asset/utils/CGeometryCreator.cpp @@ -210,8 +210,8 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float retval->setIndexing(IPolygonGeometryBase::TriangleList()); // Create indices - using index_t = uint32_t; { + using index_t = uint32_t; const auto indexCount = (polyCountX * polyCountY) * 6; const auto bytesize = sizeof(index_t) * indexCount; auto indices = ICPUBuffer::create({bytesize,IBuffer::EUF_INDEX_BUFFER_BIT}); @@ -293,8 +293,8 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float // Create vertex attributes with NONE usage because we have no clue how they'll be used hlsl::float32_t3* positions; - hlsl::vector* normals; - hlsl::vector* uvs; + hlsl::vector* normals; + hlsl::vector* uvs; { { constexpr auto AttrSize = sizeof(decltype(*positions)); @@ -342,12 +342,12 @@ core::smart_refctd_ptr CGeometryCreator::createSphere(float constexpr auto AttrSize = sizeof(decltype(*uvs)); auto buff = ICPUBuffer::create({{AttrSize * vertexCount,IBuffer::EUF_NONE}}); uvs = reinterpret_cast(buff->getPointer()); - shapes::AABB<4, uint8_t> aabb; + shapes::AABB<4, uint16_t> aabb; aabb.minVx = hlsl::vector(0,0,0,0); aabb.maxVx = hlsl::vector(255,255,0,0); retval->getAuxAttributeViews()->push_back({ .composed = { - .encodedDataRange = {.u8=aabb}, + .encodedDataRange = {.u16=aabb}, .stride = AttrSize, .format = EF_R8G8_UNORM, .rangeFormat = IGeometryBase::EAABBFormat::U8_NORM @@ -492,8 +492,8 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( // Create vertex attributes with NONE usage because we have no clue how they'll be used hlsl::float32_t3* positions; - hlsl::vector* normals; - hlsl::vector* uvs; + hlsl::vector* normals; + hlsl::vector* uvs; { { constexpr auto AttrSize = sizeof(decltype(*positions)); @@ -632,7 +632,7 @@ core::smart_refctd_ptr CGeometryCreator::createCone( // Create vertex attributes with NONE usage because we have no clue how they'll be used hlsl::float32_t3* positions; - hlsl::vector* normals; + hlsl::vector* normals; { { constexpr auto AttrSize = sizeof(decltype(*positions)); From ca7f1822540a71b4ddfa8ce5d4b38d5bd481a3c1 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Sun, 29 Jun 2025 15:21:51 +0700 Subject: [PATCH 7/7] Return nullptr if vertexCount overflow --- src/nbl/asset/utils/CGeometryCreator.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/nbl/asset/utils/CGeometryCreator.cpp b/src/nbl/asset/utils/CGeometryCreator.cpp index 0a5dd5920e..fcd31041c4 100644 --- a/src/nbl/asset/utils/CGeometryCreator.cpp +++ b/src/nbl/asset/utils/CGeometryCreator.cpp @@ -449,8 +449,11 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( CQuantNormalCache* const quantNormalCache = quantNormalCacheOverride == nullptr ? m_params.normalCache.get() : quantNormalCacheOverride; - const uint16_t halfIx = static_cast(tesselation); - const uint16_t vertexCount = 2 * static_cast(tesselation); + const auto halfIx = static_cast(tesselation); + const uint32_t u32_vertexCount = 2 * tesselation; + if (u32_vertexCount > std::numeric_limits::max()) + return nullptr; + const auto vertexCount = static_cast(u32_vertexCount); auto retval = core::make_smart_refctd_ptr(); retval->setIndexing(IPolygonGeometryBase::TriangleList()); @@ -571,11 +574,11 @@ core::smart_refctd_ptr CGeometryCreator::createCylinder( positions[i] = { p.x, p.y, p.z }; memcpy(normals + i, &n, sizeof(n)); - uvs[i] = { f_i * tesselationRec, 0.0 }; + uvs[i] = { packSnorm(f_i * tesselationRec), packSnorm(0.0) }; positions[i + halfIx] = { p.x, p.y, length }; normals[i + halfIx] = normals[i]; - uvs[i + halfIx] = { 1.0f, 0.0f }; + uvs[i + halfIx] = { packSnorm(1.0f), packSnorm(0.0f) }; } CPolygonGeometryManipulator::recomputeContentHashes(retval.get()); @@ -591,7 +594,10 @@ core::smart_refctd_ptr CGeometryCreator::createCone( CQuantNormalCache* const quantNormalCache = quantNormalCacheOverride == nullptr ? m_params.normalCache.get() : quantNormalCacheOverride; - const uint16_t vertexCount = 2 * static_cast(tesselation); + const uint32_t u32_vertexCount = 2 * tesselation; + if (u32_vertexCount > std::numeric_limits::max()) + return nullptr; + const auto vertexCount = static_cast(u32_vertexCount); auto retval = core::make_smart_refctd_ptr(); retval->setIndexing(IPolygonGeometryBase::TriangleList());