From 138d32663b60a5b125ac60c8b10331ea25db5f04 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Thu, 17 Jul 2025 16:21:59 +0700 Subject: [PATCH 1/7] Fix compute aabb implementation --- .../asset/utils/CPolygonGeometryManipulator.h | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/include/nbl/asset/utils/CPolygonGeometryManipulator.h b/include/nbl/asset/utils/CPolygonGeometryManipulator.h index 3aa3c25304..72d283202d 100644 --- a/include/nbl/asset/utils/CPolygonGeometryManipulator.h +++ b/include/nbl/asset/utils/CPolygonGeometryManipulator.h @@ -61,20 +61,48 @@ class NBL_API2 CPolygonGeometryManipulator } // - static inline IGeometryBase::SAABBStorage computeAABB(const ICPUPolygonGeometry* geo) - { - if (!geo || !geo->getPositionView() || geo->getPositionView().composed.rangeFormat>=IGeometryBase::EAABBFormat::Count) - return {}; - // the AABB shall be the same format as the Position View's range Format - IGeometryBase::SAABBStorage retval; - //if (geo->getIndexView() || geo->isSkinned()) - { - // TODO: kevinyu - } - //else - retval = geo->getPositionView().composed.encodedDataRange; - return retval; - } + static inline IGeometryBase::SAABBStorage computeAABB(const ICPUPolygonGeometry* geo) + { + if (!geo || !geo->getPositionView() || geo->getPositionView().composed.rangeFormat>=IGeometryBase::EAABBFormat::Count) + return {}; + // the AABB shall be the same format as the Position View's range Format + if (geo->getIndexView() || geo->isSkinned()) + { + auto addToAABB = [&](auto& aabb)->void + { + using aabb_t = std::remove_reference_t; + for (auto i = 0; i != geo->getIndexView().getElementCount(); i++) + { + uint32_t vertex_i; + const auto indexBuffer = geo->getIndexView().getPointer(); + switch (geo->getIndexType()) + { + case EIT_16BIT: + vertex_i = reinterpret_cast(indexBuffer)[i]; + break; + case EIT_32BIT: + vertex_i = reinterpret_cast(indexBuffer)[i]; + break; + default: + assert(false); + break; + } + typename aabb_t::point_t pt; + geo->getPositionView().decodeElement(vertex_i, pt); + aabb.addPoint(pt); + } + }; + IGeometryBase::SDataViewBase tmp = geo->getPositionView().composed; + tmp.resetRange(); + tmp.visitRange(addToAABB); + return tmp.encodedDataRange; + } + else + { + return geo->getPositionView().composed.encodedDataRange; + } + } + static inline void recomputeAABB(const ICPUPolygonGeometry* geo) { if (geo->isMutable()) From 08992739bfb01a045dd56492cca6a853239bc4a6 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Mon, 28 Jul 2025 18:25:28 +0700 Subject: [PATCH 2/7] Implement jointNode exclusion --- .../asset/utils/CPolygonGeometryManipulator.h | 100 +++++++++++------- 1 file changed, 59 insertions(+), 41 deletions(-) diff --git a/include/nbl/asset/utils/CPolygonGeometryManipulator.h b/include/nbl/asset/utils/CPolygonGeometryManipulator.h index 72d283202d..5a1f58611e 100644 --- a/include/nbl/asset/utils/CPolygonGeometryManipulator.h +++ b/include/nbl/asset/utils/CPolygonGeometryManipulator.h @@ -61,47 +61,65 @@ class NBL_API2 CPolygonGeometryManipulator } // - static inline IGeometryBase::SAABBStorage computeAABB(const ICPUPolygonGeometry* geo) - { - if (!geo || !geo->getPositionView() || geo->getPositionView().composed.rangeFormat>=IGeometryBase::EAABBFormat::Count) - return {}; - // the AABB shall be the same format as the Position View's range Format - if (geo->getIndexView() || geo->isSkinned()) - { - auto addToAABB = [&](auto& aabb)->void - { - using aabb_t = std::remove_reference_t; - for (auto i = 0; i != geo->getIndexView().getElementCount(); i++) - { - uint32_t vertex_i; - const auto indexBuffer = geo->getIndexView().getPointer(); - switch (geo->getIndexType()) - { - case EIT_16BIT: - vertex_i = reinterpret_cast(indexBuffer)[i]; - break; - case EIT_32BIT: - vertex_i = reinterpret_cast(indexBuffer)[i]; - break; - default: - assert(false); - break; - } - typename aabb_t::point_t pt; - geo->getPositionView().decodeElement(vertex_i, pt); - aabb.addPoint(pt); - } - }; - IGeometryBase::SDataViewBase tmp = geo->getPositionView().composed; - tmp.resetRange(); - tmp.visitRange(addToAABB); - return tmp.encodedDataRange; - } - else - { - return geo->getPositionView().composed.encodedDataRange; - } - } + static inline IGeometryBase::SAABBStorage computeAABB(const ICPUPolygonGeometry* geo) + { + if (!geo || !geo->getPositionView() || geo->getPositionView().composed.rangeFormat>=IGeometryBase::EAABBFormat::Count) + return {}; + // the AABB shall be the same format as the Position View's range Format + if (geo->getIndexView() || geo->isSkinned()) + { + std::unordered_set jointNodeIndexes = {}; + if (geo->isSkinned()) + { + for (const auto& jointWeight : geo->getJointWeightViews()) + { + for (auto vertex_i = 0u; vertex_i < jointWeight.indices.getElementCount(); vertex_i++) + { + hlsl::vector index; + hlsl::vector weight; + jointWeight.indices.decodeElement(vertex_i, index); + jointWeight.weights.decodeElement(vertex_i, weight); + if (weight.x != 0.f) + jointNodeIndexes.insert(index.x); + } + } + } + + auto addToAABB = [&](auto& aabb)->void + { + using aabb_t = std::remove_reference_t; + if (geo->getIndexView()) + { + for (auto index_i = 0u; index_i != geo->getIndexView().getElementCount(); index_i++) + { + hlsl::vector vertex_i; + geo->getIndexView().decodeElement(index_i, vertex_i); + if (geo->isSkinned() && jointNodeIndexes.contains(vertex_i.x)) continue; + typename aabb_t::point_t pt; + geo->getPositionView().decodeElement(vertex_i.x, pt); + aabb.addPoint(pt); + } + } else + { + for (auto vertex_i = 0u; vertex_i != geo->getPositionView().getElementCount(); vertex_i++) + { + if (geo->isSkinned() && jointNodeIndexes.contains(vertex_i)) continue; + typename aabb_t::point_t pt; + geo->getPositionView().decodeElement(vertex_i, pt); + aabb.addPoint(pt); + } + } + }; + IGeometryBase::SDataViewBase tmp = geo->getPositionView().composed; + tmp.resetRange(); + tmp.visitRange(addToAABB); + return tmp.encodedDataRange; + } + else + { + return geo->getPositionView().composed.encodedDataRange; + } + } static inline void recomputeAABB(const ICPUPolygonGeometry* geo) { From f34bf491446950e550b0e4bf92d903a04a02fbe7 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Tue, 19 Aug 2025 13:50:02 +0700 Subject: [PATCH 3/7] Small fix --- .../asset/utils/CPolygonGeometryManipulator.h | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/include/nbl/asset/utils/CPolygonGeometryManipulator.h b/include/nbl/asset/utils/CPolygonGeometryManipulator.h index 5a1f58611e..1a2c661a86 100644 --- a/include/nbl/asset/utils/CPolygonGeometryManipulator.h +++ b/include/nbl/asset/utils/CPolygonGeometryManipulator.h @@ -68,22 +68,20 @@ class NBL_API2 CPolygonGeometryManipulator // the AABB shall be the same format as the Position View's range Format if (geo->getIndexView() || geo->isSkinned()) { - std::unordered_set jointNodeIndexes = {}; - if (geo->isSkinned()) + auto isVertexSkinned = [](const ICPUPolygonGeometry* geo, uint64_t vertex_i) { - for (const auto& jointWeight : geo->getJointWeightViews()) + if (!geo->isSkinned()) return false; + const auto& jointWeightView = geo->getJointWeightViews()[vertex_i]; + for (auto weight_i = 0u; weight_i < jointWeightView.weights.getElementCount(); weight_i++) { - for (auto vertex_i = 0u; vertex_i < jointWeight.indices.getElementCount(); vertex_i++) - { - hlsl::vector index; - hlsl::vector weight; - jointWeight.indices.decodeElement(vertex_i, index); - jointWeight.weights.decodeElement(vertex_i, weight); - if (weight.x != 0.f) - jointNodeIndexes.insert(index.x); - } + hlsl::vector weight; + jointWeightView.weights.decodeElement(vertex_i, weight); + auto hasWeight = false; + if (weight.x != 0.f) hasWeight = true; + if (hasWeight) return true; } - } + return false; + }; auto addToAABB = [&](auto& aabb)->void { @@ -94,7 +92,7 @@ class NBL_API2 CPolygonGeometryManipulator { hlsl::vector vertex_i; geo->getIndexView().decodeElement(index_i, vertex_i); - if (geo->isSkinned() && jointNodeIndexes.contains(vertex_i.x)) continue; + if (isVertexSkinned(geo, vertex_i.x)) continue; typename aabb_t::point_t pt; geo->getPositionView().decodeElement(vertex_i.x, pt); aabb.addPoint(pt); @@ -103,7 +101,7 @@ class NBL_API2 CPolygonGeometryManipulator { for (auto vertex_i = 0u; vertex_i != geo->getPositionView().getElementCount(); vertex_i++) { - if (geo->isSkinned() && jointNodeIndexes.contains(vertex_i)) continue; + if (isVertexSkinned(geo, vertex_i)) continue; typename aabb_t::point_t pt; geo->getPositionView().decodeElement(vertex_i, pt); aabb.addPoint(pt); From 1c7d6406be09eef31879cc679c704dd958210651 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Tue, 19 Aug 2025 15:20:50 +0700 Subject: [PATCH 4/7] Fix logic --- include/nbl/asset/IPolygonGeometry.h | 2 ++ .../asset/utils/CPolygonGeometryManipulator.h | 17 +++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/nbl/asset/IPolygonGeometry.h b/include/nbl/asset/IPolygonGeometry.h index f21e7f7233..c14c1870b0 100644 --- a/include/nbl/asset/IPolygonGeometry.h +++ b/include/nbl/asset/IPolygonGeometry.h @@ -189,6 +189,8 @@ class IPolygonGeometry : public IIndexableGeometry, public IPolygonG // SoA instead of AoS, first component is the first bone influece, etc. struct SJointWeight { + static const size_t JOINT_COUNT_PER_VERTEX = 4; + // one thing this doesn't check is whether every vertex has a weight and index inline operator bool() const {return indices && isIntegerFormat(indices.composed.format) && weights && weights.composed.isFormatted() && indices.getElementCount()==weights.getElementCount();} diff --git a/include/nbl/asset/utils/CPolygonGeometryManipulator.h b/include/nbl/asset/utils/CPolygonGeometryManipulator.h index 1a2c661a86..fbdb451160 100644 --- a/include/nbl/asset/utils/CPolygonGeometryManipulator.h +++ b/include/nbl/asset/utils/CPolygonGeometryManipulator.h @@ -65,20 +65,21 @@ class NBL_API2 CPolygonGeometryManipulator { if (!geo || !geo->getPositionView() || geo->getPositionView().composed.rangeFormat>=IGeometryBase::EAABBFormat::Count) return {}; - // the AABB shall be the same format as the Position View's range Format + if (geo->getIndexView() || geo->isSkinned()) { auto isVertexSkinned = [](const ICPUPolygonGeometry* geo, uint64_t vertex_i) { if (!geo->isSkinned()) return false; - const auto& jointWeightView = geo->getJointWeightViews()[vertex_i]; - for (auto weight_i = 0u; weight_i < jointWeightView.weights.getElementCount(); weight_i++) + constexpr auto jointCountPerVertex = ICPUPolygonGeometry::SJointWeight::JOINT_COUNT_PER_VERTEX; + for (auto& weightView : geo->getJointWeightViews()) { - hlsl::vector weight; - jointWeightView.weights.decodeElement(vertex_i, weight); - auto hasWeight = false; - if (weight.x != 0.f) hasWeight = true; - if (hasWeight) return true; + for (auto weight_i = 0u; weight_i < jointCountPerVertex; weight_i++) + { + hlsl::vector weight; + weightView.weights.decodeElement(jointCountPerVertex * vertex_i + weight_i, weight); + if (weight.x != 0.f) return true; + } } return false; }; From a5af142831a666d46e0fbeab83706126258a0bc1 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Wed, 20 Aug 2025 12:51:23 +0700 Subject: [PATCH 5/7] Fix logic --- .../asset/utils/CPolygonGeometryManipulator.h | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/include/nbl/asset/utils/CPolygonGeometryManipulator.h b/include/nbl/asset/utils/CPolygonGeometryManipulator.h index fbdb451160..dfedb413b5 100644 --- a/include/nbl/asset/utils/CPolygonGeometryManipulator.h +++ b/include/nbl/asset/utils/CPolygonGeometryManipulator.h @@ -72,14 +72,20 @@ class NBL_API2 CPolygonGeometryManipulator { if (!geo->isSkinned()) return false; constexpr auto jointCountPerVertex = ICPUPolygonGeometry::SJointWeight::JOINT_COUNT_PER_VERTEX; - for (auto& weightView : geo->getJointWeightViews()) + const auto jointViewCount = geo->getJointWeightViews().size(); + for (auto weightView_i = 0u; weightView_i < jointViewCount; weightView_i++) { - for (auto weight_i = 0u; weight_i < jointCountPerVertex; weight_i++) - { - hlsl::vector weight; - weightView.weights.decodeElement(jointCountPerVertex * vertex_i + weight_i, weight); - if (weight.x != 0.f) return true; - } + const auto& weightView = geo->getJointWeightViews()[weightView_i]; + hlsl::float32_t4 weight; + weightView.weights.decodeElement(vertex_i, weight); + if (weightView_i == jointViewCount - 1) + { + for (auto channel_i = 0; channel_i < getFormatChannelCount(weightView.weights.composed.format); channel_i++) + if (weight[channel_i] > 0.f) + return true; + } + else if (hlsl::any(lessThan(hlsl::promote(0.f), weight))) + return true; } return false; }; From 976aeac742377749920f60990991191213f5e592 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Wed, 20 Aug 2025 18:46:19 +0700 Subject: [PATCH 6/7] Remove JOINT_COUNT_PER_VERTEX --- include/nbl/asset/IPolygonGeometry.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/nbl/asset/IPolygonGeometry.h b/include/nbl/asset/IPolygonGeometry.h index c14c1870b0..f21e7f7233 100644 --- a/include/nbl/asset/IPolygonGeometry.h +++ b/include/nbl/asset/IPolygonGeometry.h @@ -189,8 +189,6 @@ class IPolygonGeometry : public IIndexableGeometry, public IPolygonG // SoA instead of AoS, first component is the first bone influece, etc. struct SJointWeight { - static const size_t JOINT_COUNT_PER_VERTEX = 4; - // one thing this doesn't check is whether every vertex has a weight and index inline operator bool() const {return indices && isIntegerFormat(indices.composed.format) && weights && weights.composed.isFormatted() && indices.getElementCount()==weights.getElementCount();} From 7723c2f16c55fcaf83fa76de35773e66897e78d8 Mon Sep 17 00:00:00 2001 From: kevyuu Date: Wed, 20 Aug 2025 18:46:49 +0700 Subject: [PATCH 7/7] Don't assume only last channel have less than 4 component --- .../nbl/asset/utils/CPolygonGeometryManipulator.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/include/nbl/asset/utils/CPolygonGeometryManipulator.h b/include/nbl/asset/utils/CPolygonGeometryManipulator.h index dfedb413b5..6ee4250938 100644 --- a/include/nbl/asset/utils/CPolygonGeometryManipulator.h +++ b/include/nbl/asset/utils/CPolygonGeometryManipulator.h @@ -68,23 +68,17 @@ class NBL_API2 CPolygonGeometryManipulator if (geo->getIndexView() || geo->isSkinned()) { - auto isVertexSkinned = [](const ICPUPolygonGeometry* geo, uint64_t vertex_i) + const auto jointViewCount = geo->getJointWeightViews().size(); + auto isVertexSkinned = [&jointViewCount](const ICPUPolygonGeometry* geo, uint64_t vertex_i) { if (!geo->isSkinned()) return false; - constexpr auto jointCountPerVertex = ICPUPolygonGeometry::SJointWeight::JOINT_COUNT_PER_VERTEX; - const auto jointViewCount = geo->getJointWeightViews().size(); for (auto weightView_i = 0u; weightView_i < jointViewCount; weightView_i++) { const auto& weightView = geo->getJointWeightViews()[weightView_i]; hlsl::float32_t4 weight; weightView.weights.decodeElement(vertex_i, weight); - if (weightView_i == jointViewCount - 1) - { - for (auto channel_i = 0; channel_i < getFormatChannelCount(weightView.weights.composed.format); channel_i++) - if (weight[channel_i] > 0.f) - return true; - } - else if (hlsl::any(lessThan(hlsl::promote(0.f), weight))) + for (auto channel_i = 0; channel_i < getFormatChannelCount(weightView.weights.composed.format); channel_i++) + if (weight[channel_i] > 0.f) return true; } return false;