From de578feef0eb8a1452c738a46457819f95e22910 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 16 Sep 2024 19:07:46 +0100 Subject: [PATCH 01/17] Cloned the existing LineSegmentIntersector as PolytopeIntersector to provide a basis for full implementation of polytope intersector. --- include/vsg/utils/PolytopeIntersector.h | 74 ++++++ src/vsg/utils/PolytopeIntersector.cpp | 308 ++++++++++++++++++++++++ 2 files changed, 382 insertions(+) create mode 100644 include/vsg/utils/PolytopeIntersector.h create mode 100644 src/vsg/utils/PolytopeIntersector.cpp diff --git a/include/vsg/utils/PolytopeIntersector.h b/include/vsg/utils/PolytopeIntersector.h new file mode 100644 index 0000000000..fe6dc9a001 --- /dev/null +++ b/include/vsg/utils/PolytopeIntersector.h @@ -0,0 +1,74 @@ +#pragma once + +/* + +Copyright(c) 2020 Robert Osfield + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + */ + +#include +#include +#include + +namespace vsg +{ + + /// PolytopeIntersector is an Intersector subclass that provides support for computing intersections between a line segment and geometry in the scene graph. + class VSG_DECLSPEC PolytopeIntersector : public Inherit + { + public: + PolytopeIntersector(const dvec3& s, const dvec3& e, ref_ptr initialArrayData = {}); + PolytopeIntersector(const Camera& camera, int32_t x, int32_t y, ref_ptr initialArrayData = {}); + + class VSG_DECLSPEC Intersection : public Inherit + { + public: + Intersection() {} + Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, double in_ratio, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex); + + dvec3 localIntersection; + dvec3 worldIntersection; + double ratio = 0.0; + + dmat4 localToWorld; + NodePath nodePath; + DataList arrays; + IndexRatios indexRatios; + uint32_t instanceIndex = 0; + + // return true if Intersection is valid + operator bool() const { return !nodePath.empty(); } + }; + + using Intersections = std::vector>; + Intersections intersections; + + ref_ptr add(const dvec3& coord, double ratio, const IndexRatios& indexRatios, uint32_t instanceIndex); + + void pushTransform(const Transform& transform) override; + void popTransform() override; + + /// check for intersection with sphere + bool intersects(const dsphere& bs) override; + + bool intersectDraw(uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) override; + bool intersectDrawIndexed(uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) override; + + protected: + struct LineSegment + { + dvec3 start; + dvec3 end; + }; + + std::vector _lineSegmentStack; + }; + VSG_type_name(vsg::PolytopeIntersector); + +} // namespace vsg diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp new file mode 100644 index 0000000000..7127d8f470 --- /dev/null +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -0,0 +1,308 @@ +/* + +Copyright(c) 2020 Robert Osfield + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + */ + +#include +#include +#include + +using namespace vsg; + +template +struct TriangleIntersector +{ + using value_type = V; + using vec_type = t_vec3; + + dvec3 start; + dvec3 end; + uint32_t instanceIndex = 0; + + vec_type _d; + value_type _length; + value_type _inverse_length; + + vec_type _d_invX; + vec_type _d_invY; + vec_type _d_invZ; + + PolytopeIntersector& intersector; + ref_ptr vertices; + + TriangleIntersector(PolytopeIntersector& in_intersector, const dvec3& in_start, const dvec3& in_end, ref_ptr in_vertices) : + start(in_start), + end(in_end), + intersector(in_intersector), + vertices(in_vertices) + { + + _d = end - start; + _length = length(_d); + _inverse_length = (_length != 0.0) ? 1.0 / _length : 0.0; + _d *= _inverse_length; + + _d_invX = _d.x != 0.0 ? _d / _d.x : vec_type(0.0, 0.0, 0.0); + _d_invY = _d.y != 0.0 ? _d / _d.y : vec_type(0.0, 0.0, 0.0); + _d_invZ = _d.z != 0.0 ? _d / _d.z : vec_type(0.0, 0.0, 0.0); + } + + /// intersect with a single triangle + bool intersect(uint32_t i0, uint32_t i1, uint32_t i2) + { + const vec3& v0 = vertices->at(i0); + const vec3& v1 = vertices->at(i1); + const vec3& v2 = vertices->at(i2); + + vec_type T = vec_type(start) - vec_type(v0); + vec_type E2 = vec_type(v2) - vec_type(v0); + vec_type E1 = vec_type(v1) - vec_type(v0); + + vec_type P = cross(_d, E2); + + value_type det = dot(P, E1); + + value_type r, r0, r1, r2; + + const value_type epsilon = 1e-10; + if (det > epsilon) + { + value_type u = dot(P, T); + if (u < 0.0 || u > det) return false; + + vec_type Q = cross(T, E1); + value_type v = dot(Q, _d); + if (v < 0.0 || v > det) return false; + + if ((u + v) > det) return false; + + value_type inv_det = 1.0 / det; + value_type t = dot(Q, E2) * inv_det; + if (t < 0.0 || t > _length) return false; + + u *= inv_det; + v *= inv_det; + + r0 = 1.0 - u - v; + r1 = u; + r2 = v; + r = t * _inverse_length; + } + else if (det < -epsilon) + { + value_type u = dot(P, T); + if (u > 0.0 || u < det) return false; + + vec_type Q = cross(T, E1); + value_type v = dot(Q, _d); + if (v > 0.0 || v < det) return false; + + if ((u + v) < det) return false; + + value_type inv_det = 1.0 / det; + value_type t = dot(Q, E2) * inv_det; + if (t < 0.0 || t > _length) return false; + + u *= inv_det; + v *= inv_det; + + r0 = 1.0 - u - v; + r1 = u; + r2 = v; + r = t * _inverse_length; + } + else + { + return false; + } + + dvec3 intersection = dvec3(dvec3(v0) * double(r0) + dvec3(v1) * double(r1) + dvec3(v2) * double(r2)); + intersector.add(intersection, double(r), {{i0, r0}, {i1, r1}, {i2, r2}}, instanceIndex); + + return true; + } +}; + +PolytopeIntersector::PolytopeIntersector(const dvec3& s, const dvec3& e, ref_ptr initialArrayData) : + Inherit(initialArrayData) +{ + _lineSegmentStack.push_back(LineSegment{s, e}); +} + +PolytopeIntersector::PolytopeIntersector(const Camera& camera, int32_t x, int32_t y, ref_ptr initialArrayData) : + Inherit(initialArrayData) +{ + auto viewport = camera.getViewport(); + + vsg::vec2 ndc(0.0f, 0.0f); + if ((viewport.width > 0) && (viewport.height > 0)) + { + ndc.set((static_cast(x) - viewport.x) / viewport.width, (static_cast(y) - viewport.y) / viewport.height); + } + + auto projectionMatrix = camera.projectionMatrix->transform(); + auto viewMatrix = camera.viewMatrix->transform(); + + bool reverse_depth = (projectionMatrix(2, 2) > 0.0); + + vsg::dvec3 ndc_near(ndc.x * 2.0 - 1.0, ndc.y * 2.0 - 1.0, reverse_depth ? viewport.maxDepth : viewport.minDepth); + vsg::dvec3 ndc_far(ndc.x * 2.0 - 1.0, ndc.y * 2.0 - 1.0, reverse_depth ? viewport.minDepth : viewport.maxDepth); + + auto inv_projectionMatrix = vsg::inverse(projectionMatrix); + vsg::dvec3 eye_near = inv_projectionMatrix * ndc_near; + vsg::dvec3 eye_far = inv_projectionMatrix * ndc_far; + _lineSegmentStack.push_back(LineSegment{eye_near, eye_far}); + + dmat4 eyeToWorld = inverse(viewMatrix); + localToWorldStack().push_back(viewMatrix); + worldToLocalStack().push_back(eyeToWorld); + _lineSegmentStack.push_back(LineSegment{eyeToWorld * eye_near, eyeToWorld * eye_far}); +} + +PolytopeIntersector::Intersection::Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, double in_ratio, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex) : + localIntersection(in_localIntersection), + worldIntersection(in_worldIntersection), + ratio(in_ratio), + localToWorld(in_localToWorld), + nodePath(in_nodePath), + arrays(in_arrays), + indexRatios(in_indexRatios), + instanceIndex(in_instanceIndex) +{ +} + +ref_ptr PolytopeIntersector::add(const dvec3& coord, double ratio, const IndexRatios& indexRatios, uint32_t instanceIndex) +{ + ref_ptr intersection; + + auto localToWorld = computeTransform(_nodePath); + intersection = Intersection::create(coord, localToWorld * coord, ratio, localToWorld, _nodePath, arrayStateStack.back()->arrays, indexRatios, instanceIndex); + intersections.emplace_back(intersection); + + return intersection; +} + +void PolytopeIntersector::pushTransform(const Transform& transform) +{ + auto& l2wStack = localToWorldStack(); + auto& w2lStack = worldToLocalStack(); + + dmat4 localToWorld = l2wStack.empty() ? transform.transform(dmat4{}) : transform.transform(l2wStack.back()); + dmat4 worldToLocal = inverse(localToWorld); + + l2wStack.push_back(localToWorld); + w2lStack.push_back(worldToLocal); + + const auto& worldLineSegment = _lineSegmentStack.front(); + _lineSegmentStack.push_back(LineSegment{worldToLocal * worldLineSegment.start, worldToLocal * worldLineSegment.end}); +} + +void PolytopeIntersector::popTransform() +{ + _lineSegmentStack.pop_back(); + localToWorldStack().pop_back(); + worldToLocalStack().pop_back(); +} + +bool PolytopeIntersector::intersects(const dsphere& bs) +{ + //debug("intersects( center = ", bs.center, ", radius = ", bs.radius, ")"); + if (!bs.valid()) return false; + + const auto& lineSegment = _lineSegmentStack.back(); + const dvec3& start = lineSegment.start; + const dvec3& end = lineSegment.end; + + dvec3 sm = start - bs.center; + double c = length2(sm) - bs.radius * bs.radius; + if (c < 0.0) return true; + + dvec3 se = end - start; + double a = length2(se); + double b = dot(sm, se) * 2.0; + double d = b * b - 4.0 * a * c; + + if (d < 0.0) return false; + + d = sqrt(d); + + double div = 1.0 / (2.0 * a); + + double r1 = (-b - d) * div; + double r2 = (-b + d) * div; + + if (r1 <= 0.0 && r2 <= 0.0) return false; + if (r1 >= 1.0 && r2 >= 1.0) return false; + + // passed all the rejection tests so line must intersect bounding sphere, return true. + return true; +} + +bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) +{ + auto& arrayState = *arrayStateStack.back(); + if (arrayState.topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || vertexCount < 3) return false; + + const auto& ls = _lineSegmentStack.back(); + + size_t previous_size = intersections.size(); + uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; + for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) + { + TriangleIntersector triIntersector(*this, ls.start, ls.end, arrayState.vertexArray(instanceIndex)); + if (!triIntersector.vertices) return false; + + uint32_t endVertex = int((firstVertex + vertexCount) / 3.0f) * 3; + + for (uint32_t i = firstVertex; i < endVertex; i += 3) + { + triIntersector.intersect(i, i + 1, i + 2); + } + } + + return intersections.size() != previous_size; +} + +bool PolytopeIntersector::intersectDrawIndexed(uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) +{ + auto& arrayState = *arrayStateStack.back(); + if (arrayState.topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || indexCount < 3) return false; + + const auto& ls = _lineSegmentStack.back(); + + size_t previous_size = intersections.size(); + uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; + for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) + { + TriangleIntersector triIntersector(*this, ls.start, ls.end, arrayState.vertexArray(instanceIndex)); + if (!triIntersector.vertices) continue; + + triIntersector.instanceIndex = instanceIndex; + + uint32_t endIndex = int((firstIndex + indexCount) / 3.0f) * 3; + + if (ushort_indices) + { + for (uint32_t i = firstIndex; i < endIndex; i += 3) + { + triIntersector.intersect(ushort_indices->at(i), ushort_indices->at(i + 1), ushort_indices->at(i + 2)); + } + } + else if (uint_indices) + { + for (uint32_t i = firstIndex; i < endIndex; i += 3) + { + triIntersector.intersect(uint_indices->at(i), uint_indices->at(i + 1), uint_indices->at(i + 2)); + } + } + } + + return intersections.size() != previous_size; +} From 60d0117a5aea7aacd6b5fd51639387f5d0af8608 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 23 Sep 2024 18:29:28 +0100 Subject: [PATCH 02/17] Ran build_all_h --- include/vsg/all.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/vsg/all.h b/include/vsg/all.h index 16b24a6e3b..723100f9f7 100644 --- a/include/vsg/all.h +++ b/include/vsg/all.h @@ -179,6 +179,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include +#include #include #include #include @@ -290,6 +291,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include +#include #include #include #include From b2012240cd09d0ca49cb2af1cff4f537bc7d5981 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 23 Sep 2024 18:41:19 +0100 Subject: [PATCH 03/17] Added build of vsg::PolytopeIntersector --- include/vsg/utils/PolytopeIntersector.h | 2 +- src/vsg/CMakeLists.txt | 1 + src/vsg/utils/PolytopeIntersector.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/vsg/utils/PolytopeIntersector.h b/include/vsg/utils/PolytopeIntersector.h index fe6dc9a001..0471eda3db 100644 --- a/include/vsg/utils/PolytopeIntersector.h +++ b/include/vsg/utils/PolytopeIntersector.h @@ -2,7 +2,7 @@ /* -Copyright(c) 2020 Robert Osfield +Copyright(c) 2024 Robert Osfield Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/src/vsg/CMakeLists.txt b/src/vsg/CMakeLists.txt index a9c18d6e6e..63fe899e9e 100644 --- a/src/vsg/CMakeLists.txt +++ b/src/vsg/CMakeLists.txt @@ -251,6 +251,7 @@ set(SOURCES utils/Instrumentation.cpp utils/GpuAnnotation.cpp utils/LineSegmentIntersector.cpp + utils/PolytopeIntersector.cpp utils/LoadPagedLOD.cpp utils/FindDynamicObjects.cpp utils/PropagateDynamicObjects.cpp diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 7127d8f470..761735af9c 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -1,6 +1,6 @@ /* -Copyright(c) 2020 Robert Osfield +Copyright(c) 2024 Robert Osfield Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From 0d768224d463dd3ab9bb2a073d28d76df93ebbe8 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 24 Sep 2024 13:20:25 +0100 Subject: [PATCH 04/17] Updated constructors to use more appropriate polytope related constructors. --- include/vsg/utils/PolytopeIntersector.h | 14 ++-- src/vsg/utils/PolytopeIntersector.cpp | 102 ++++++++++++++++++------ 2 files changed, 83 insertions(+), 33 deletions(-) diff --git a/include/vsg/utils/PolytopeIntersector.h b/include/vsg/utils/PolytopeIntersector.h index 0471eda3db..a37a7b737d 100644 --- a/include/vsg/utils/PolytopeIntersector.h +++ b/include/vsg/utils/PolytopeIntersector.h @@ -19,12 +19,15 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI namespace vsg { + using Polytope = std::vector; + /// PolytopeIntersector is an Intersector subclass that provides support for computing intersections between a line segment and geometry in the scene graph. class VSG_DECLSPEC PolytopeIntersector : public Inherit { public: - PolytopeIntersector(const dvec3& s, const dvec3& e, ref_ptr initialArrayData = {}); - PolytopeIntersector(const Camera& camera, int32_t x, int32_t y, ref_ptr initialArrayData = {}); + PolytopeIntersector(const Polytope& in_polytope, ref_ptr initialArrayData = {}); + PolytopeIntersector(const Camera& camera, double xMin, double yMin, double xMax, double yMax, ref_ptr initialArrayData = {}); + class VSG_DECLSPEC Intersection : public Inherit { @@ -61,13 +64,8 @@ namespace vsg bool intersectDrawIndexed(uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) override; protected: - struct LineSegment - { - dvec3 start; - dvec3 end; - }; - std::vector _lineSegmentStack; + std::vector _polytopeStack; }; VSG_type_name(vsg::PolytopeIntersector); diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 761735af9c..155fad18a5 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -130,21 +130,33 @@ struct TriangleIntersector } }; -PolytopeIntersector::PolytopeIntersector(const dvec3& s, const dvec3& e, ref_ptr initialArrayData) : +PolytopeIntersector::PolytopeIntersector(const Polytope& in_polytope, ref_ptr initialArrayData) : Inherit(initialArrayData) { - _lineSegmentStack.push_back(LineSegment{s, e}); + _polytopeStack.push_back(in_polytope); } -PolytopeIntersector::PolytopeIntersector(const Camera& camera, int32_t x, int32_t y, ref_ptr initialArrayData) : +PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, double yMin, double xMax, double yMax, ref_ptr initialArrayData) : Inherit(initialArrayData) { auto viewport = camera.getViewport(); - vsg::vec2 ndc(0.0f, 0.0f); - if ((viewport.width > 0) && (viewport.height > 0)) + double ndc_xMin = xMin; + double ndc_xMax = xMax; + double ndc_yMin = yMin; + double ndc_yMax = yMax; + + info("PolytopeIntersector::PolytopeIntersector(camera, ", xMin, ", ", yMin, ", ", xMax, ", ", yMax, ")"); + + if (viewport.width > 0) + { + ndc_xMin = (ndc_xMin - static_cast(viewport.x)) / static_cast(viewport.width); + ndc_xMax = (ndc_xMax - static_cast(viewport.x)) / static_cast(viewport.width); + } + if (viewport.height > 0) { - ndc.set((static_cast(x) - viewport.x) / viewport.width, (static_cast(y) - viewport.y) / viewport.height); + ndc_yMin = (ndc_yMin - static_cast(viewport.y)) / static_cast(viewport.height); + ndc_yMax = (ndc_yMax - static_cast(viewport.y)) / static_cast(viewport.height); } auto projectionMatrix = camera.projectionMatrix->transform(); @@ -152,18 +164,37 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, int32_t x, int32_ bool reverse_depth = (projectionMatrix(2, 2) > 0.0); - vsg::dvec3 ndc_near(ndc.x * 2.0 - 1.0, ndc.y * 2.0 - 1.0, reverse_depth ? viewport.maxDepth : viewport.minDepth); - vsg::dvec3 ndc_far(ndc.x * 2.0 - 1.0, ndc.y * 2.0 - 1.0, reverse_depth ? viewport.minDepth : viewport.maxDepth); - auto inv_projectionMatrix = vsg::inverse(projectionMatrix); - vsg::dvec3 eye_near = inv_projectionMatrix * ndc_near; - vsg::dvec3 eye_far = inv_projectionMatrix * ndc_far; - _lineSegmentStack.push_back(LineSegment{eye_near, eye_far}); + Polytope clipspace; + clipspace.push_back(dplane(1.0, 0.0, 0.0, -xMin)); + clipspace.push_back(dplane(-1.0, 0.0, 0.0, xMax)); + clipspace.push_back(dplane(0.0, 1.0, 0.0, -yMin)); + clipspace.push_back(dplane(0.0, -1.0, 0.0, -yMax)); + + if (reverse_depth) + { + clipspace.push_back(dplane(0.0, 0.0, 1.0, -viewport.maxDepth)); + clipspace.push_back(dplane(0.0, 0.0, -1.0, viewport.minDepth)); + } + else + { + clipspace.push_back(dplane(0.0, 0.0, 1.0, -viewport.maxDepth)); + clipspace.push_back(dplane(0.0, 0.0, -1.0, viewport.minDepth)); + } + + Polytope eyespace; + for(auto& pl : clipspace) + { + eyespace.push_back(pl * projectionMatrix); + } + + Polytope worldspace; + for(auto& pl : worldspace) + { + eyespace.push_back(pl * viewMatrix); + } - dmat4 eyeToWorld = inverse(viewMatrix); - localToWorldStack().push_back(viewMatrix); - worldToLocalStack().push_back(eyeToWorld); - _lineSegmentStack.push_back(LineSegment{eyeToWorld * eye_near, eyeToWorld * eye_far}); + _polytopeStack.push_back(worldspace); } PolytopeIntersector::Intersection::Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, double in_ratio, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex) : @@ -191,6 +222,8 @@ ref_ptr PolytopeIntersector::add(const dvec3& void PolytopeIntersector::pushTransform(const Transform& transform) { + vsg::info("PolytopeIntersector::pushTransform(", transform.className(), ")"); + auto& l2wStack = localToWorldStack(); auto& w2lStack = worldToLocalStack(); @@ -200,13 +233,23 @@ void PolytopeIntersector::pushTransform(const Transform& transform) l2wStack.push_back(localToWorld); w2lStack.push_back(worldToLocal); - const auto& worldLineSegment = _lineSegmentStack.front(); - _lineSegmentStack.push_back(LineSegment{worldToLocal * worldLineSegment.start, worldToLocal * worldLineSegment.end}); + const auto& worldspace = _polytopeStack.front(); + + Polytope localspace; + for(auto& pl : worldspace) + { + localspace.push_back(pl * localToWorld); + } + + _polytopeStack.push_back(localspace); + } void PolytopeIntersector::popTransform() { - _lineSegmentStack.pop_back(); + vsg::info("PolytopeIntersector::popTransform()"); + + _polytopeStack.pop_back(); localToWorldStack().pop_back(); worldToLocalStack().pop_back(); } @@ -216,7 +259,8 @@ bool PolytopeIntersector::intersects(const dsphere& bs) //debug("intersects( center = ", bs.center, ", radius = ", bs.radius, ")"); if (!bs.valid()) return false; - const auto& lineSegment = _lineSegmentStack.back(); + +#if 0 const dvec3& start = lineSegment.start; const dvec3& end = lineSegment.end; @@ -240,19 +284,22 @@ bool PolytopeIntersector::intersects(const dsphere& bs) if (r1 <= 0.0 && r2 <= 0.0) return false; if (r1 >= 1.0 && r2 >= 1.0) return false; - +#else + info("PolytopeIntersector::intersects(const dsphere& bs) todo."); +#endif // passed all the rejection tests so line must intersect bounding sphere, return true. return true; } bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) { + size_t previous_size = intersections.size(); +#if 0 auto& arrayState = *arrayStateStack.back(); if (arrayState.topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || vertexCount < 3) return false; const auto& ls = _lineSegmentStack.back(); - size_t previous_size = intersections.size(); uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) { @@ -266,18 +313,20 @@ bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCou triIntersector.intersect(i, i + 1, i + 2); } } - +#else + info("PolytopeIntersector::intersectDraw(", firstVertex, ", ", vertexCount, ", ", firstInstance, ", ", instanceCount,")) todo."); +#endif return intersections.size() != previous_size; } bool PolytopeIntersector::intersectDrawIndexed(uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) { + size_t previous_size = intersections.size(); +#if 0 auto& arrayState = *arrayStateStack.back(); if (arrayState.topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || indexCount < 3) return false; - const auto& ls = _lineSegmentStack.back(); - size_t previous_size = intersections.size(); uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) { @@ -303,6 +352,9 @@ bool PolytopeIntersector::intersectDrawIndexed(uint32_t firstIndex, uint32_t ind } } } +#else + info("PolytopeIntersector::intersectDrawIndexed(", firstIndex, ", ", indexCount, ", ", firstInstance, ", ", instanceCount,")) todo."); +#endif return intersections.size() != previous_size; } From f9f6baa332155e105b630c4e9bf04e6f27ea7703 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 25 Sep 2024 12:35:46 +0100 Subject: [PATCH 05/17] Set up intial polyope for picking usage case --- include/vsg/utils/PolytopeIntersector.h | 2 + src/vsg/utils/PolytopeIntersector.cpp | 75 ++++++++++++++++--------- 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/include/vsg/utils/PolytopeIntersector.h b/include/vsg/utils/PolytopeIntersector.h index a37a7b737d..c33d2d205e 100644 --- a/include/vsg/utils/PolytopeIntersector.h +++ b/include/vsg/utils/PolytopeIntersector.h @@ -13,6 +13,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ #include +#include #include #include @@ -69,4 +70,5 @@ namespace vsg }; VSG_type_name(vsg::PolytopeIntersector); + } // namespace vsg diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 155fad18a5..71494da305 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -11,11 +11,30 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ #include +#include #include #include +#include + using namespace vsg; +namespace vsg +{ + +std::ostream& operator<<(std::ostream& output, const vsg::Polytope& polytope) +{ + output<<"Polytope "<<&polytope<<" {"< struct TriangleIntersector { @@ -141,35 +160,31 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub { auto viewport = camera.getViewport(); - double ndc_xMin = xMin; - double ndc_xMax = xMax; - double ndc_yMin = yMin; - double ndc_yMax = yMax; + info("\nPolytopeIntersector::PolytopeIntersector(camera, ", xMin, ", ", yMin, ", ", xMax, ", ", yMax, ")"); - info("PolytopeIntersector::PolytopeIntersector(camera, ", xMin, ", ", yMin, ", ", xMax, ", ", yMax, ")"); + double ndc_xMin = (viewport.width > 0) ? (2.0 * (xMin - static_cast(viewport.x)) / static_cast(viewport.width) - 1.0) : xMin; + double ndc_xMax = (viewport.width > 0) ? (2.0 * (xMax - static_cast(viewport.x)) / static_cast(viewport.width) - 1.0) : xMax; - if (viewport.width > 0) - { - ndc_xMin = (ndc_xMin - static_cast(viewport.x)) / static_cast(viewport.width); - ndc_xMax = (ndc_xMax - static_cast(viewport.x)) / static_cast(viewport.width); - } - if (viewport.height > 0) - { - ndc_yMin = (ndc_yMin - static_cast(viewport.y)) / static_cast(viewport.height); - ndc_yMax = (ndc_yMax - static_cast(viewport.y)) / static_cast(viewport.height); - } + double ndc_yMin = (viewport.height > 0) ? (1.0 - 2.0 * (yMax - static_cast(viewport.y)) / static_cast(viewport.height)) : yMin; + double ndc_yMax = (viewport.height > 0) ? (1.0 - 2.0 * (yMin - static_cast(viewport.y)) / static_cast(viewport.height)) : yMax; + + info("ndc_xMin ", ndc_xMin); + info("ndc_xMax ", ndc_xMax); + info("ndc_yMin ", ndc_yMin); + info("ndc_yMax ", ndc_yMax); auto projectionMatrix = camera.projectionMatrix->transform(); + auto inverse_projectionMatrix = camera.projectionMatrix->inverse(); auto viewMatrix = camera.viewMatrix->transform(); + auto inverse_viewMatrix = camera.viewMatrix->inverse(); bool reverse_depth = (projectionMatrix(2, 2) > 0.0); - - Polytope clipspace; - clipspace.push_back(dplane(1.0, 0.0, 0.0, -xMin)); - clipspace.push_back(dplane(-1.0, 0.0, 0.0, xMax)); - clipspace.push_back(dplane(0.0, 1.0, 0.0, -yMin)); - clipspace.push_back(dplane(0.0, -1.0, 0.0, -yMax)); + vsg::Polytope clipspace; + clipspace.push_back(dplane(1.0, 0.0, 0.0, -ndc_xMin)); + clipspace.push_back(dplane(-1.0, 0.0, 0.0, ndc_xMax)); + clipspace.push_back(dplane(0.0, 1.0, 0.0, -ndc_yMin)); + clipspace.push_back(dplane(0.0, -1.0, 0.0, ndc_yMax)); if (reverse_depth) { @@ -178,23 +193,28 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub } else { - clipspace.push_back(dplane(0.0, 0.0, 1.0, -viewport.maxDepth)); - clipspace.push_back(dplane(0.0, 0.0, -1.0, viewport.minDepth)); + clipspace.push_back(dplane(0.0, 0.0, -1.0, viewport.maxDepth)); + clipspace.push_back(dplane(0.0, 0.0, 1.0, -viewport.minDepth)); } - Polytope eyespace; + vsg::Polytope eyespace; for(auto& pl : clipspace) { eyespace.push_back(pl * projectionMatrix); } - Polytope worldspace; - for(auto& pl : worldspace) + vsg::Polytope worldspace; + for(auto& pl : eyespace) { - eyespace.push_back(pl * viewMatrix); + worldspace.push_back(pl * viewMatrix); } _polytopeStack.push_back(worldspace); + + std::cout<<"Clip space : "< Date: Wed, 25 Sep 2024 15:25:24 +0100 Subject: [PATCH 06/17] Fixed CullNode bounding sphere radius. --- src/vsg/utils/Builder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vsg/utils/Builder.cpp b/src/vsg/utils/Builder.cpp index 7fb73c9680..fa42739c15 100644 --- a/src/vsg/utils/Builder.cpp +++ b/src/vsg/utils/Builder.cpp @@ -252,7 +252,7 @@ ref_ptr Builder::decorateAndCompileIfRequired(const GeometryInfo& info, co bound.add(v); } cullNode->bound.center = (bound.min + bound.max) * 0.5f; - cullNode->bound.radius = vsg::length(bound.max - bound.min) * 0.5 + vsg::length(info.dx + info.dy + info.dz); + cullNode->bound.radius = vsg::length(bound.max - bound.min) * 0.5 + vsg::length(info.dx + info.dy + info.dz) * 0.5; } else { @@ -263,7 +263,7 @@ ref_ptr Builder::decorateAndCompileIfRequired(const GeometryInfo& info, co else { cullNode->bound.center = info.position; - cullNode->bound.radius = vsg::length(info.dx + info.dy + info.dz); + cullNode->bound.radius = vsg::length(info.dx + info.dy + info.dz) * 0.5; } subgraph = cullNode; From 2083f50fddaf51e485b235b061b05915132dbc8d Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 25 Sep 2024 16:41:37 +0100 Subject: [PATCH 07/17] Refined polytope setup and adding CullNode support. --- src/vsg/utils/PolytopeIntersector.cpp | 74 ++++++++------------------- 1 file changed, 21 insertions(+), 53 deletions(-) diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 71494da305..53647d5856 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -162,40 +162,34 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub info("\nPolytopeIntersector::PolytopeIntersector(camera, ", xMin, ", ", yMin, ", ", xMax, ", ", yMax, ")"); + auto projectionMatrix = camera.projectionMatrix->transform(); + auto viewMatrix = camera.viewMatrix->transform(); + bool reverse_depth = (projectionMatrix(2, 2) > 0.0); + double ndc_xMin = (viewport.width > 0) ? (2.0 * (xMin - static_cast(viewport.x)) / static_cast(viewport.width) - 1.0) : xMin; double ndc_xMax = (viewport.width > 0) ? (2.0 * (xMax - static_cast(viewport.x)) / static_cast(viewport.width) - 1.0) : xMax; - double ndc_yMin = (viewport.height > 0) ? (1.0 - 2.0 * (yMax - static_cast(viewport.y)) / static_cast(viewport.height)) : yMin; - double ndc_yMax = (viewport.height > 0) ? (1.0 - 2.0 * (yMin - static_cast(viewport.y)) / static_cast(viewport.height)) : yMax; + double ndc_yMin = (viewport.height > 0) ? (2.0 * (yMin - static_cast(viewport.y)) / static_cast(viewport.height) - 1.0) : yMin; + double ndc_yMax = (viewport.height > 0) ? (2.0 * (yMax - static_cast(viewport.y)) / static_cast(viewport.height) - 1.0) : yMax; + + double ndc_near = reverse_depth ? viewport.maxDepth : viewport.minDepth; + double ndc_far = reverse_depth ? viewport.minDepth : viewport.maxDepth; info("ndc_xMin ", ndc_xMin); info("ndc_xMax ", ndc_xMax); info("ndc_yMin ", ndc_yMin); info("ndc_yMax ", ndc_yMax); - - auto projectionMatrix = camera.projectionMatrix->transform(); - auto inverse_projectionMatrix = camera.projectionMatrix->inverse(); - auto viewMatrix = camera.viewMatrix->transform(); - auto inverse_viewMatrix = camera.viewMatrix->inverse(); - - bool reverse_depth = (projectionMatrix(2, 2) > 0.0); + info("ndc_near ", ndc_near); + info("ndc_far ", ndc_far); vsg::Polytope clipspace; - clipspace.push_back(dplane(1.0, 0.0, 0.0, -ndc_xMin)); - clipspace.push_back(dplane(-1.0, 0.0, 0.0, ndc_xMax)); - clipspace.push_back(dplane(0.0, 1.0, 0.0, -ndc_yMin)); - clipspace.push_back(dplane(0.0, -1.0, 0.0, ndc_yMax)); + clipspace.push_back(dplane(1.0, 0.0, 0.0, -ndc_xMin)); // left + clipspace.push_back(dplane(-1.0, 0.0, 0.0, ndc_xMax)); // right + clipspace.push_back(dplane(0.0, 1.0, 0.0, -ndc_yMin)); // bottom + clipspace.push_back(dplane(0.0, -1.0, 0.0, ndc_yMax)); // top + clipspace.push_back(dplane(0.0, 0.0, -1.0, ndc_near)); // near + clipspace.push_back(dplane(0.0, 0.0, 1.0, ndc_far)); // far - if (reverse_depth) - { - clipspace.push_back(dplane(0.0, 0.0, 1.0, -viewport.maxDepth)); - clipspace.push_back(dplane(0.0, 0.0, -1.0, viewport.minDepth)); - } - else - { - clipspace.push_back(dplane(0.0, 0.0, -1.0, viewport.maxDepth)); - clipspace.push_back(dplane(0.0, 0.0, 1.0, -viewport.minDepth)); - } vsg::Polytope eyespace; for(auto& pl : clipspace) @@ -242,7 +236,7 @@ ref_ptr PolytopeIntersector::add(const dvec3& void PolytopeIntersector::pushTransform(const Transform& transform) { - vsg::info("PolytopeIntersector::pushTransform(", transform.className(), ")"); + vsg::info("\nPolytopeIntersector::pushTransform(", transform.className(), ")"); auto& l2wStack = localToWorldStack(); @@ -263,7 +257,6 @@ void PolytopeIntersector::pushTransform(const Transform& transform) } _polytopeStack.push_back(localspace); - } void PolytopeIntersector::popTransform() @@ -280,36 +273,11 @@ bool PolytopeIntersector::intersects(const dsphere& bs) //debug("intersects( center = ", bs.center, ", radius = ", bs.radius, ")"); if (!bs.valid()) return false; + const auto& polytope = _polytopeStack.back(); -#if 0 - const dvec3& start = lineSegment.start; - const dvec3& end = lineSegment.end; - - dvec3 sm = start - bs.center; - double c = length2(sm) - bs.radius * bs.radius; - if (c < 0.0) return true; - - dvec3 se = end - start; - double a = length2(se); - double b = dot(sm, se) * 2.0; - double d = b * b - 4.0 * a * c; + info("PolytopeIntersector::intersects(const dsphere& bs = ", bs.center, ", ", bs.radius, ") : result = ", vsg::intersect(polytope, bs)); - if (d < 0.0) return false; - - d = sqrt(d); - - double div = 1.0 / (2.0 * a); - - double r1 = (-b - d) * div; - double r2 = (-b + d) * div; - - if (r1 <= 0.0 && r2 <= 0.0) return false; - if (r1 >= 1.0 && r2 >= 1.0) return false; -#else - info("PolytopeIntersector::intersects(const dsphere& bs) todo."); -#endif - // passed all the rejection tests so line must intersect bounding sphere, return true. - return true; + return vsg::intersect(polytope, bs); } bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) From 7f03329874048b952ed7390ca3effb6727bc3971 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 25 Sep 2024 17:52:19 +0100 Subject: [PATCH 08/17] Initial vertex in polytope test --- include/vsg/maths/plane.h | 19 ++++ src/vsg/utils/PolytopeIntersector.cpp | 139 ++++++++------------------ 2 files changed, 60 insertions(+), 98 deletions(-) diff --git a/include/vsg/maths/plane.h b/include/vsg/maths/plane.h index d7a622457a..da3522e968 100644 --- a/include/vsg/maths/plane.h +++ b/include/vsg/maths/plane.h @@ -168,6 +168,25 @@ namespace vsg { return intersect(polytope.begin(), polytope.end(), s); } + + /** return true if bounding sphere wholly or partially intersects with convex polytope defined by a list of planes with normals pointing inwards towards center of the polytope. */ + template + constexpr bool inside(PlaneItr first, PlaneItr last, const t_vec3& v, T epsilon = 1e-10) + { + const auto negative_epsilon = -epsilon; + for (auto itr = first; itr != last; ++itr) + { + if (distance(*itr, v) < negative_epsilon) return false; + } + return true; + } + + /** return true if bounding sphere wholly or partially intersects with convex polytope defined by a list of planes with normals pointing inwards towards center of the polytope. */ + template + constexpr bool inside(const Polytope& polytope, const t_vec3& v, T epsilon = 1e-10) + { + return inside(polytope.begin(), polytope.end(), v, epsilon); + } } // namespace vsg #if defined(__clang__) diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 53647d5856..4615a1c346 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -36,116 +36,59 @@ std::ostream& operator<<(std::ostream& output, const vsg::Polytope& polytope) } template -struct TriangleIntersector +struct PrimtiveIntersector { using value_type = V; using vec_type = t_vec3; - dvec3 start; - dvec3 end; uint32_t instanceIndex = 0; - vec_type _d; - value_type _length; - value_type _inverse_length; - - vec_type _d_invX; - vec_type _d_invY; - vec_type _d_invZ; - PolytopeIntersector& intersector; + const Polytope& polytope; ref_ptr vertices; - TriangleIntersector(PolytopeIntersector& in_intersector, const dvec3& in_start, const dvec3& in_end, ref_ptr in_vertices) : - start(in_start), - end(in_end), + PrimtiveIntersector(PolytopeIntersector& in_intersector, const Polytope& in_polytope, ref_ptr in_vertices) : intersector(in_intersector), + polytope(in_polytope), vertices(in_vertices) { - - _d = end - start; - _length = length(_d); - _inverse_length = (_length != 0.0) ? 1.0 / _length : 0.0; - _d *= _inverse_length; - - _d_invX = _d.x != 0.0 ? _d / _d.x : vec_type(0.0, 0.0, 0.0); - _d_invY = _d.y != 0.0 ? _d / _d.y : vec_type(0.0, 0.0, 0.0); - _d_invZ = _d.z != 0.0 ? _d / _d.z : vec_type(0.0, 0.0, 0.0); } /// intersect with a single triangle bool intersect(uint32_t i0, uint32_t i1, uint32_t i2) { - const vec3& v0 = vertices->at(i0); - const vec3& v1 = vertices->at(i1); - const vec3& v2 = vertices->at(i2); - - vec_type T = vec_type(start) - vec_type(v0); - vec_type E2 = vec_type(v2) - vec_type(v0); - vec_type E1 = vec_type(v1) - vec_type(v0); + const dvec3 v0(vertices->at(i0)); + const dvec3 v1(vertices->at(i1)); + const dvec3 v2(vertices->at(i2)); - vec_type P = cross(_d, E2); - - value_type det = dot(P, E1); - - value_type r, r0, r1, r2; - - const value_type epsilon = 1e-10; - if (det > epsilon) - { - value_type u = dot(P, T); - if (u < 0.0 || u > det) return false; + //info("PrimtiveIntersector::intersect(", i0, ", ", i1, ", ", i2, ") v0 = ", v0, ", v1 = ", v1, " v2 = ", v2); - vec_type Q = cross(T, E1); - value_type v = dot(Q, _d); - if (v < 0.0 || v > det) return false; + if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1) || vsg::inside(polytope, v2)) return true; - if ((u + v) > det) return false; - - value_type inv_det = 1.0 / det; - value_type t = dot(Q, E2) * inv_det; - if (t < 0.0 || t > _length) return false; - - u *= inv_det; - v *= inv_det; - - r0 = 1.0 - u - v; - r1 = u; - r2 = v; - r = t * _inverse_length; - } - else if (det < -epsilon) - { - value_type u = dot(P, T); - if (u > 0.0 || u < det) return false; + return false; + } - vec_type Q = cross(T, E1); - value_type v = dot(Q, _d); - if (v > 0.0 || v < det) return false; + /// intersect with a single line segment + bool intersect(uint32_t i0, uint32_t i1) + { + const dvec3 v0(vertices->at(i0)); + const dvec3 v1(vertices->at(i1)); - if ((u + v) < det) return false; + //info("PrimtiveIntersector::intersect(", i0, ", ", i1, ") v0 = ", v0, ", v1 = ", v1); - value_type inv_det = 1.0 / det; - value_type t = dot(Q, E2) * inv_det; - if (t < 0.0 || t > _length) return false; + if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1)) return true; - u *= inv_det; - v *= inv_det; + return false; + } - r0 = 1.0 - u - v; - r1 = u; - r2 = v; - r = t * _inverse_length; - } - else - { - return false; - } + /// intersect with a single line segment + bool intersect(uint32_t i0) + { + const dvec3 v0(vertices->at(i0)); - dvec3 intersection = dvec3(dvec3(v0) * double(r0) + dvec3(v1) * double(r1) + dvec3(v2) * double(r2)); - intersector.add(intersection, double(r), {{i0, r0}, {i1, r1}, {i2, r2}}, instanceIndex); + //info("PrimtiveIntersector::intersect(", i0, ") v0 = ", v0); - return true; + return vsg::inside(polytope, v0); } }; @@ -282,44 +225,47 @@ bool PolytopeIntersector::intersects(const dsphere& bs) bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) { + info("PolytopeIntersector::intersectDraw(", firstVertex, ", ", vertexCount, ", ", firstInstance, ", ", instanceCount,")) todo."); + size_t previous_size = intersections.size(); -#if 0 + auto& arrayState = *arrayStateStack.back(); if (arrayState.topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || vertexCount < 3) return false; - const auto& ls = _lineSegmentStack.back(); + const auto& polytope = _polytopeStack.back(); uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) { - TriangleIntersector triIntersector(*this, ls.start, ls.end, arrayState.vertexArray(instanceIndex)); + PrimtiveIntersector triIntersector(*this, polytope, arrayState.vertexArray(instanceIndex)); if (!triIntersector.vertices) return false; uint32_t endVertex = int((firstVertex + vertexCount) / 3.0f) * 3; for (uint32_t i = firstVertex; i < endVertex; i += 3) { - triIntersector.intersect(i, i + 1, i + 2); + if (triIntersector.intersect(i, i + 1, i + 2)) info("intersection!"); } } -#else - info("PolytopeIntersector::intersectDraw(", firstVertex, ", ", vertexCount, ", ", firstInstance, ", ", instanceCount,")) todo."); -#endif + return intersections.size() != previous_size; } bool PolytopeIntersector::intersectDrawIndexed(uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) { + info("PolytopeIntersector::intersectDrawIndexed(", firstIndex, ", ", indexCount, ", ", firstInstance, ", ", instanceCount,")) todo."); + size_t previous_size = intersections.size(); -#if 0 + auto& arrayState = *arrayStateStack.back(); if (arrayState.topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || indexCount < 3) return false; - const auto& ls = _lineSegmentStack.back(); + + const auto& polytope = _polytopeStack.back(); uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) { - TriangleIntersector triIntersector(*this, ls.start, ls.end, arrayState.vertexArray(instanceIndex)); + PrimtiveIntersector triIntersector(*this, polytope, arrayState.vertexArray(instanceIndex)); if (!triIntersector.vertices) continue; triIntersector.instanceIndex = instanceIndex; @@ -330,20 +276,17 @@ bool PolytopeIntersector::intersectDrawIndexed(uint32_t firstIndex, uint32_t ind { for (uint32_t i = firstIndex; i < endIndex; i += 3) { - triIntersector.intersect(ushort_indices->at(i), ushort_indices->at(i + 1), ushort_indices->at(i + 2)); + if (triIntersector.intersect(ushort_indices->at(i), ushort_indices->at(i + 1), ushort_indices->at(i + 2))) info("intersection!"); } } else if (uint_indices) { for (uint32_t i = firstIndex; i < endIndex; i += 3) { - triIntersector.intersect(uint_indices->at(i), uint_indices->at(i + 1), uint_indices->at(i + 2)); + if (triIntersector.intersect(uint_indices->at(i), uint_indices->at(i + 1), uint_indices->at(i + 2))) info("intersection!"); } } } -#else - info("PolytopeIntersector::intersectDrawIndexed(", firstIndex, ", ", indexCount, ", ", firstInstance, ", ", instanceCount,")) todo."); -#endif return intersections.size() != previous_size; } From 790cfeb76f36ba3443103b45dcbec6494e9d2312 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 27 Sep 2024 14:56:52 +0100 Subject: [PATCH 09/17] Restructured how PolytopeIntersector handles primitives using a template PrimitiveFunctor class. --- include/vsg/utils/PrimitiveFunctor.h | 103 +++++++++++++++++++++++ src/vsg/utils/PolytopeIntersector.cpp | 116 +++++++++----------------- 2 files changed, 141 insertions(+), 78 deletions(-) create mode 100644 include/vsg/utils/PrimitiveFunctor.h diff --git a/include/vsg/utils/PrimitiveFunctor.h b/include/vsg/utils/PrimitiveFunctor.h new file mode 100644 index 0000000000..055b80edc4 --- /dev/null +++ b/include/vsg/utils/PrimitiveFunctor.h @@ -0,0 +1,103 @@ +#pragma once + +/* + +Copyright(c) 2024 Robert Osfield + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + */ + +#include + +namespace vsg +{ + + /** template helper class that decomposed draw(..) and drawIndexed(..) calls into individual points, lines or triangles.*/ + template + struct PrimitiveFunctor : public T + { + template + PrimitiveFunctor(Args&&... args) : + T(std::forward(args)...) {} + + void draw(VkPrimitiveTopology topology, uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) + { + uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; + for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) + { + T::instance(instanceIndex); + + switch(topology) + { + case(VK_PRIMITIVE_TOPOLOGY_POINT_LIST): + case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST): + case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP): + break; + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST): + { + uint32_t primtiveCount = vertexCount / 3; + uint32_t endVertex = firstVertex + primtiveCount * 3; + for (uint32_t i = firstVertex; i < endVertex; i += 3) + { + T::triangle(i, i + 1, i + 2); + } + break; + } + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP): + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN): + case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY): + case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY): + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY): + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY): + case(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST): + default: + break; + } + } + } + + template + void drawIndexed(VkPrimitiveTopology topology, IndexArray indices, uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) + { + uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; + for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) + { + T::instance(instanceIndex); + + switch(topology) + { + case(VK_PRIMITIVE_TOPOLOGY_POINT_LIST): + case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST): + case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP): + break; + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST): + { + uint32_t primtiveCount = indexCount / 3; + uint32_t endIndex = firstIndex + primtiveCount * 3; + for (uint32_t i = firstIndex; i < endIndex; i += 3) + { + T::triangle(indices->at(i), indices->at(i + 1), indices->at(i + 2)); + } + break; + } + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP): + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN): + case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY): + case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY): + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY): + case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY): + case(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST): + default: + break; + } + } + } + }; + + +} // namespace vsg diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 4615a1c346..a9fff87ab4 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -13,6 +13,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include +#include #include #include @@ -33,65 +34,63 @@ std::ostream& operator<<(std::ostream& output, const vsg::Polytope& polytope) return output; } -} - -template -struct PrimtiveIntersector +struct PolytopePrimitiveIntersection { - using value_type = V; - using vec_type = t_vec3; - - uint32_t instanceIndex = 0; - - PolytopeIntersector& intersector; + PolytopeIntersector& polyopeIntersector; + ArrayState& arrayState; const Polytope& polytope; ref_ptr vertices; - PrimtiveIntersector(PolytopeIntersector& in_intersector, const Polytope& in_polytope, ref_ptr in_vertices) : - intersector(in_intersector), - polytope(in_polytope), - vertices(in_vertices) + PolytopePrimitiveIntersection(PolytopeIntersector& in_polyopeIntersector, ArrayState& in_arrayState, const Polytope& in_polytope) : + polyopeIntersector(in_polyopeIntersector), + arrayState(in_arrayState), + polytope(in_polytope) {} + + void instance(uint32_t index) { + info("PolytopePrimitiveIntersection::instance(", index, ")"); + + vertices = arrayState.vertexArray(index); } - /// intersect with a single triangle - bool intersect(uint32_t i0, uint32_t i1, uint32_t i2) + void triangle(uint32_t i0, uint32_t i1, uint32_t i2) { + info("PolytopePrimitiveIntersection::triangle(", i0, ", ", i1, ", ", i2, ")"); const dvec3 v0(vertices->at(i0)); const dvec3 v1(vertices->at(i1)); const dvec3 v2(vertices->at(i2)); - //info("PrimtiveIntersector::intersect(", i0, ", ", i1, ", ", i2, ") v0 = ", v0, ", v1 = ", v1, " v2 = ", v2); - - if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1) || vsg::inside(polytope, v2)) return true; - - return false; + if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1) || vsg::inside(polytope, v2)) + { + info(" inside(", i0, ", ", i1, ", ", i2, ") v0 = ", v0, ", v1 = ", v1, " v2 = ", v2); + } } - /// intersect with a single line segment - bool intersect(uint32_t i0, uint32_t i1) + void line(uint32_t i0, uint32_t i1) { + info("PolytopePrimitiveIntersection::line(", i0, ", ", i1, ")"); const dvec3 v0(vertices->at(i0)); const dvec3 v1(vertices->at(i1)); - //info("PrimtiveIntersector::intersect(", i0, ", ", i1, ") v0 = ", v0, ", v1 = ", v1); - - if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1)) return true; - - return false; + if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1)) + { + info(" inside(", i0, ", ", i1, ") v0 = ", v0, ", v1 = ", v1); + } } - /// intersect with a single line segment - bool intersect(uint32_t i0) + void point(uint32_t i0) { + info("PolytopePrimitiveIntersection::point(", i0, ")"); const dvec3 v0(vertices->at(i0)); - - //info("PrimtiveIntersector::intersect(", i0, ") v0 = ", v0); - - return vsg::inside(polytope, v0); + if (vsg::inside(polytope, v0)) + { + info(" inside(", i0, ") v0 = ", v0); + } } }; +} + PolytopeIntersector::PolytopeIntersector(const Polytope& in_polytope, ref_ptr initialArrayData) : Inherit(initialArrayData) { @@ -230,23 +229,9 @@ bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCou size_t previous_size = intersections.size(); auto& arrayState = *arrayStateStack.back(); - if (arrayState.topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || vertexCount < 3) return false; - const auto& polytope = _polytopeStack.back(); - - uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; - for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) - { - PrimtiveIntersector triIntersector(*this, polytope, arrayState.vertexArray(instanceIndex)); - if (!triIntersector.vertices) return false; - - uint32_t endVertex = int((firstVertex + vertexCount) / 3.0f) * 3; - - for (uint32_t i = firstVertex; i < endVertex; i += 3) - { - if (triIntersector.intersect(i, i + 1, i + 2)) info("intersection!"); - } - } + vsg::PrimitiveFunctor printPrimitives(*this, arrayState, _polytopeStack.back()); + if (ushort_indices) printPrimitives.draw(arrayState.topology, firstVertex, vertexCount, firstInstance, instanceCount); return intersections.size() != previous_size; } @@ -258,35 +243,10 @@ bool PolytopeIntersector::intersectDrawIndexed(uint32_t firstIndex, uint32_t ind size_t previous_size = intersections.size(); auto& arrayState = *arrayStateStack.back(); - if (arrayState.topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || indexCount < 3) return false; - - const auto& polytope = _polytopeStack.back(); - uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; - for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) - { - PrimtiveIntersector triIntersector(*this, polytope, arrayState.vertexArray(instanceIndex)); - if (!triIntersector.vertices) continue; - - triIntersector.instanceIndex = instanceIndex; - - uint32_t endIndex = int((firstIndex + indexCount) / 3.0f) * 3; - - if (ushort_indices) - { - for (uint32_t i = firstIndex; i < endIndex; i += 3) - { - if (triIntersector.intersect(ushort_indices->at(i), ushort_indices->at(i + 1), ushort_indices->at(i + 2))) info("intersection!"); - } - } - else if (uint_indices) - { - for (uint32_t i = firstIndex; i < endIndex; i += 3) - { - if (triIntersector.intersect(uint_indices->at(i), uint_indices->at(i + 1), uint_indices->at(i + 2))) info("intersection!"); - } - } - } + vsg::PrimitiveFunctor printPrimtives(*this, arrayState, _polytopeStack.back()); + if (ushort_indices) printPrimtives.drawIndexed(arrayState.topology, ushort_indices, firstIndex, indexCount, firstInstance, instanceCount); + else if (uint_indices) printPrimtives.drawIndexed(arrayState.topology, uint_indices, firstIndex, indexCount, firstInstance, instanceCount); return intersections.size() != previous_size; } From ca2f7b60989c4ed60de266c17c703f1113b132b8 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 27 Sep 2024 16:32:53 +0100 Subject: [PATCH 10/17] Added support for points, lines, line strips, triangle strips and triangle fans --- include/vsg/utils/PrimitiveFunctor.h | 87 ++++++++++++++++++++++++++- src/vsg/utils/PolytopeIntersector.cpp | 3 +- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/include/vsg/utils/PrimitiveFunctor.h b/include/vsg/utils/PrimitiveFunctor.h index 055b80edc4..a02f466741 100644 --- a/include/vsg/utils/PrimitiveFunctor.h +++ b/include/vsg/utils/PrimitiveFunctor.h @@ -13,6 +13,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ #include +#include namespace vsg { @@ -30,14 +31,38 @@ namespace vsg uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) { - T::instance(instanceIndex); + if (!T::instance(instanceIndex)) continue; switch(topology) { case(VK_PRIMITIVE_TOPOLOGY_POINT_LIST): + { + uint32_t endVertex = firstVertex + vertexCount; + for (uint32_t i = firstVertex; i < endVertex; ++i) + { + T::point(i); + } + break; + } case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST): + { + uint32_t primitiveCount = vertexCount / 2; + uint32_t endVertex = firstVertex + primitiveCount * 2; + for (uint32_t i = firstVertex; i < endVertex; i += 2) + { + T::line(i, i+1); + } + break; + } case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP): + { + uint32_t endVertex = firstVertex + ((vertexCount >= 2) ? (vertexCount-1) : 0); + for (uint32_t i = firstVertex; i < endVertex; ++i) + { + T::line(i, i+1); + } break; + } case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST): { uint32_t primtiveCount = vertexCount / 3; @@ -49,13 +74,30 @@ namespace vsg break; } case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP): + { + uint32_t endVertex = firstVertex + ((vertexCount >= 3) ? (vertexCount-2) : 0); + for (uint32_t i = firstVertex; i < endVertex; ++i) + { + T::triangle(i, i+1, i+2); // do we need to reverse the i+1 and i+2 order on odd triangles? + } + break; + } case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN): + { + uint32_t endVertex = firstVertex + ((vertexCount >= 3) ? (vertexCount-2) : 0); + for (uint32_t i = firstVertex+1; i < endVertex; ++i) + { + T::triangle(firstVertex, i+1, i+2); + } + break; + } case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY): case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY): case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY): case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY): case(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST): default: + warn("PrimitiveFunctor::draw(topology = ", topology, ", ...) not implemented."); break; } } @@ -67,14 +109,38 @@ namespace vsg uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) { - T::instance(instanceIndex); + if (!T::instance(instanceIndex)) continue; switch(topology) { case(VK_PRIMITIVE_TOPOLOGY_POINT_LIST): + { + uint32_t endIndex = firstIndex + indexCount; + for (uint32_t i = firstIndex; i < endIndex; ++i) + { + T::point(indices->at(i)); + } + break; + } case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST): + { + uint32_t primtiveCount = indexCount / 2; + uint32_t endIndex = firstIndex + primtiveCount * 2; + for (uint32_t i = firstIndex; i < endIndex; i += 2) + { + T::line(indices->at(i), indices->at(i + 1)); + } + break; + } case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP): + { + uint32_t endIndex= firstIndex + ((indexCount >= 2) ? (indexCount-1) : 0); + for (uint32_t i = firstIndex; i < endIndex; ++i) + { + T::line(indices->at(i), indices->at(i + 1)); + } break; + } case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST): { uint32_t primtiveCount = indexCount / 3; @@ -86,13 +152,30 @@ namespace vsg break; } case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP): + { + uint32_t endIndex = firstIndex + ((indexCount >= 3) ? (indexCount-2) : 0); + for (uint32_t i = firstIndex; i < endIndex; ++i) + { + T::triangle(indices->at(i), indices->at(i+1), indices->at(i+2)); // do we need to reverse the i+1 and i+2 order on odd triangles? + } + break; + } case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN): + { + uint32_t endIndex = firstIndex + ((indexCount >= 3) ? (indexCount-2) : 0); + for (uint32_t i = firstIndex+1; i < endIndex; ++i) + { + T::triangle(indices->at(firstIndex), indices->at(i+1), indices->at(i+2)); + } + break; + } case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY): case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY): case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY): case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY): case(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST): default: + warn("PrimitiveFunctor::drawIndexed(topology = ", topology, ", ...) not implemented."); break; } } diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index a9fff87ab4..e56f70a52e 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -46,11 +46,12 @@ struct PolytopePrimitiveIntersection arrayState(in_arrayState), polytope(in_polytope) {} - void instance(uint32_t index) + bool instance(uint32_t index) { info("PolytopePrimitiveIntersection::instance(", index, ")"); vertices = arrayState.vertexArray(index); + return vertices.valid(); } void triangle(uint32_t i0, uint32_t i1, uint32_t i2) From 322aebd5ffff15b18c9aae62c37be72093fa0659 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 27 Sep 2024 17:28:11 +0100 Subject: [PATCH 11/17] Ran clang-format --- include/vsg/utils/PolytopeIntersector.h | 3 - include/vsg/utils/PrimitiveFunctor.h | 209 ++++++++++++------------ src/vsg/utils/PolytopeIntersector.cpp | 133 ++++++++------- 3 files changed, 167 insertions(+), 178 deletions(-) diff --git a/include/vsg/utils/PolytopeIntersector.h b/include/vsg/utils/PolytopeIntersector.h index c33d2d205e..fa73c9104f 100644 --- a/include/vsg/utils/PolytopeIntersector.h +++ b/include/vsg/utils/PolytopeIntersector.h @@ -29,7 +29,6 @@ namespace vsg PolytopeIntersector(const Polytope& in_polytope, ref_ptr initialArrayData = {}); PolytopeIntersector(const Camera& camera, double xMin, double yMin, double xMax, double yMax, ref_ptr initialArrayData = {}); - class VSG_DECLSPEC Intersection : public Inherit { public: @@ -65,10 +64,8 @@ namespace vsg bool intersectDrawIndexed(uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) override; protected: - std::vector _polytopeStack; }; VSG_type_name(vsg::PolytopeIntersector); - } // namespace vsg diff --git a/include/vsg/utils/PrimitiveFunctor.h b/include/vsg/utils/PrimitiveFunctor.h index a02f466741..7cc0c96d98 100644 --- a/include/vsg/utils/PrimitiveFunctor.h +++ b/include/vsg/utils/PrimitiveFunctor.h @@ -12,8 +12,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ -#include #include +#include namespace vsg { @@ -33,72 +33,69 @@ namespace vsg { if (!T::instance(instanceIndex)) continue; - switch(topology) + switch (topology) { - case(VK_PRIMITIVE_TOPOLOGY_POINT_LIST): + case (VK_PRIMITIVE_TOPOLOGY_POINT_LIST): { + uint32_t endVertex = firstVertex + vertexCount; + for (uint32_t i = firstVertex; i < endVertex; ++i) { - uint32_t endVertex = firstVertex + vertexCount; - for (uint32_t i = firstVertex; i < endVertex; ++i) - { - T::point(i); - } - break; + T::point(i); } - case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_LINE_LIST): { + // primitive restart not yet supported. + uint32_t primitiveCount = vertexCount / 2; + uint32_t endVertex = firstVertex + primitiveCount * 2; + for (uint32_t i = firstVertex; i < endVertex; i += 2) { - uint32_t primitiveCount = vertexCount / 2; - uint32_t endVertex = firstVertex + primitiveCount * 2; - for (uint32_t i = firstVertex; i < endVertex; i += 2) - { - T::line(i, i+1); - } - break; + T::line(i, i + 1); } - case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_LINE_STRIP): { + uint32_t endVertex = firstVertex + ((vertexCount >= 2) ? (vertexCount - 1) : 0); + for (uint32_t i = firstVertex; i < endVertex; ++i) { - uint32_t endVertex = firstVertex + ((vertexCount >= 2) ? (vertexCount-1) : 0); - for (uint32_t i = firstVertex; i < endVertex; ++i) - { - T::line(i, i+1); - } - break; + T::line(i, i + 1); } - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST): { + uint32_t primtiveCount = vertexCount / 3; + uint32_t endVertex = firstVertex + primtiveCount * 3; + for (uint32_t i = firstVertex; i < endVertex; i += 3) { - uint32_t primtiveCount = vertexCount / 3; - uint32_t endVertex = firstVertex + primtiveCount * 3; - for (uint32_t i = firstVertex; i < endVertex; i += 3) - { - T::triangle(i, i + 1, i + 2); - } - break; + T::triangle(i, i + 1, i + 2); } - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP): { + // primitive restart not yet supported. + uint32_t endVertex = firstVertex + ((vertexCount >= 3) ? (vertexCount - 2) : 0); + for (uint32_t i = firstVertex; i < endVertex; ++i) { - uint32_t endVertex = firstVertex + ((vertexCount >= 3) ? (vertexCount-2) : 0); - for (uint32_t i = firstVertex; i < endVertex; ++i) - { - T::triangle(i, i+1, i+2); // do we need to reverse the i+1 and i+2 order on odd triangles? - } - break; + T::triangle(i, i + 1, i + 2); // do we need to reverse the i+1 and i+2 order on odd triangles? } - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN): { + // primitive restart not yet supported. + uint32_t endVertex = firstVertex + ((vertexCount >= 3) ? (vertexCount - 2) : 0); + for (uint32_t i = firstVertex + 1; i < endVertex; ++i) { - uint32_t endVertex = firstVertex + ((vertexCount >= 3) ? (vertexCount-2) : 0); - for (uint32_t i = firstVertex+1; i < endVertex; ++i) - { - T::triangle(firstVertex, i+1, i+2); - } - break; + T::triangle(firstVertex, i + 1, i + 2); } - case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY): - case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY): - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY): - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY): - case(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST): - default: - warn("PrimitiveFunctor::draw(topology = ", topology, ", ...) not implemented."); - break; + break; + } + case (VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY): + case (VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY): + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY): + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY): + case (VK_PRIMITIVE_TOPOLOGY_PATCH_LIST): + default: + warn("PrimitiveFunctor::draw(topology = ", topology, ", ...) not implemented."); + break; } } } @@ -111,76 +108,72 @@ namespace vsg { if (!T::instance(instanceIndex)) continue; - switch(topology) + switch (topology) { - case(VK_PRIMITIVE_TOPOLOGY_POINT_LIST): + case (VK_PRIMITIVE_TOPOLOGY_POINT_LIST): { + uint32_t endIndex = firstIndex + indexCount; + for (uint32_t i = firstIndex; i < endIndex; ++i) { - uint32_t endIndex = firstIndex + indexCount; - for (uint32_t i = firstIndex; i < endIndex; ++i) - { - T::point(indices->at(i)); - } - break; + T::point(indices->at(i)); } - case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_LINE_LIST): { + uint32_t primtiveCount = indexCount / 2; + uint32_t endIndex = firstIndex + primtiveCount * 2; + for (uint32_t i = firstIndex; i < endIndex; i += 2) { - uint32_t primtiveCount = indexCount / 2; - uint32_t endIndex = firstIndex + primtiveCount * 2; - for (uint32_t i = firstIndex; i < endIndex; i += 2) - { - T::line(indices->at(i), indices->at(i + 1)); - } - break; + T::line(indices->at(i), indices->at(i + 1)); } - case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_LINE_STRIP): { + // primitive restart not yet supported. + uint32_t endIndex = firstIndex + ((indexCount >= 2) ? (indexCount - 1) : 0); + for (uint32_t i = firstIndex; i < endIndex; ++i) { - uint32_t endIndex= firstIndex + ((indexCount >= 2) ? (indexCount-1) : 0); - for (uint32_t i = firstIndex; i < endIndex; ++i) - { - T::line(indices->at(i), indices->at(i + 1)); - } - break; + T::line(indices->at(i), indices->at(i + 1)); } - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST): { + uint32_t primtiveCount = indexCount / 3; + uint32_t endIndex = firstIndex + primtiveCount * 3; + for (uint32_t i = firstIndex; i < endIndex; i += 3) { - uint32_t primtiveCount = indexCount / 3; - uint32_t endIndex = firstIndex + primtiveCount * 3; - for (uint32_t i = firstIndex; i < endIndex; i += 3) - { - T::triangle(indices->at(i), indices->at(i + 1), indices->at(i + 2)); - } - break; + T::triangle(indices->at(i), indices->at(i + 1), indices->at(i + 2)); } - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP): { + // primitive restart not yet supported. + uint32_t endIndex = firstIndex + ((indexCount >= 3) ? (indexCount - 2) : 0); + for (uint32_t i = firstIndex; i < endIndex; ++i) { - uint32_t endIndex = firstIndex + ((indexCount >= 3) ? (indexCount-2) : 0); - for (uint32_t i = firstIndex; i < endIndex; ++i) - { - T::triangle(indices->at(i), indices->at(i+1), indices->at(i+2)); // do we need to reverse the i+1 and i+2 order on odd triangles? - } - break; + T::triangle(indices->at(i), indices->at(i + 1), indices->at(i + 2)); // do we need to reverse the i+1 and i+2 order on odd triangles? } - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN): + break; + } + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN): { + // primitive restart not yet supported. + uint32_t endIndex = firstIndex + ((indexCount >= 3) ? (indexCount - 2) : 0); + for (uint32_t i = firstIndex + 1; i < endIndex; ++i) { - uint32_t endIndex = firstIndex + ((indexCount >= 3) ? (indexCount-2) : 0); - for (uint32_t i = firstIndex+1; i < endIndex; ++i) - { - T::triangle(indices->at(firstIndex), indices->at(i+1), indices->at(i+2)); - } - break; + T::triangle(indices->at(firstIndex), indices->at(i + 1), indices->at(i + 2)); } - case(VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY): - case(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY): - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY): - case(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY): - case(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST): - default: - warn("PrimitiveFunctor::drawIndexed(topology = ", topology, ", ...) not implemented."); - break; + break; + } + case (VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY): + case (VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY): + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY): + case (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY): + case (VK_PRIMITIVE_TOPOLOGY_PATCH_LIST): + default: + warn("PrimitiveFunctor::drawIndexed(topology = ", topology, ", ...) not implemented."); + break; } } } }; - } // namespace vsg diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index e56f70a52e..52e1deebf8 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -13,8 +13,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include -#include #include +#include #include @@ -23,74 +23,74 @@ using namespace vsg; namespace vsg { -std::ostream& operator<<(std::ostream& output, const vsg::Polytope& polytope) -{ - output<<"Polytope "<<&polytope<<" {"< vertices; - - PolytopePrimitiveIntersection(PolytopeIntersector& in_polyopeIntersector, ArrayState& in_arrayState, const Polytope& in_polytope) : - polyopeIntersector(in_polyopeIntersector), - arrayState(in_arrayState), - polytope(in_polytope) {} - - bool instance(uint32_t index) + struct PolytopePrimitiveIntersection { - info("PolytopePrimitiveIntersection::instance(", index, ")"); + PolytopeIntersector& polyopeIntersector; + ArrayState& arrayState; + const Polytope& polytope; + ref_ptr vertices; - vertices = arrayState.vertexArray(index); - return vertices.valid(); - } - - void triangle(uint32_t i0, uint32_t i1, uint32_t i2) - { - info("PolytopePrimitiveIntersection::triangle(", i0, ", ", i1, ", ", i2, ")"); - const dvec3 v0(vertices->at(i0)); - const dvec3 v1(vertices->at(i1)); - const dvec3 v2(vertices->at(i2)); + PolytopePrimitiveIntersection(PolytopeIntersector& in_polyopeIntersector, ArrayState& in_arrayState, const Polytope& in_polytope) : + polyopeIntersector(in_polyopeIntersector), + arrayState(in_arrayState), + polytope(in_polytope) {} - if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1) || vsg::inside(polytope, v2)) + bool instance(uint32_t index) { - info(" inside(", i0, ", ", i1, ", ", i2, ") v0 = ", v0, ", v1 = ", v1, " v2 = ", v2); + info("PolytopePrimitiveIntersection::instance(", index, ")"); + + vertices = arrayState.vertexArray(index); + return vertices.valid(); } - } - void line(uint32_t i0, uint32_t i1) - { - info("PolytopePrimitiveIntersection::line(", i0, ", ", i1, ")"); - const dvec3 v0(vertices->at(i0)); - const dvec3 v1(vertices->at(i1)); + void triangle(uint32_t i0, uint32_t i1, uint32_t i2) + { + info("PolytopePrimitiveIntersection::triangle(", i0, ", ", i1, ", ", i2, ")"); + const dvec3 v0(vertices->at(i0)); + const dvec3 v1(vertices->at(i1)); + const dvec3 v2(vertices->at(i2)); + + if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1) || vsg::inside(polytope, v2)) + { + info(" inside(", i0, ", ", i1, ", ", i2, ") v0 = ", v0, ", v1 = ", v1, " v2 = ", v2); + } + } - if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1)) + void line(uint32_t i0, uint32_t i1) { - info(" inside(", i0, ", ", i1, ") v0 = ", v0, ", v1 = ", v1); + info("PolytopePrimitiveIntersection::line(", i0, ", ", i1, ")"); + const dvec3 v0(vertices->at(i0)); + const dvec3 v1(vertices->at(i1)); + + if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1)) + { + info(" inside(", i0, ", ", i1, ") v0 = ", v0, ", v1 = ", v1); + } } - } - void point(uint32_t i0) - { - info("PolytopePrimitiveIntersection::point(", i0, ")"); - const dvec3 v0(vertices->at(i0)); - if (vsg::inside(polytope, v0)) + void point(uint32_t i0) { - info(" inside(", i0, ") v0 = ", v0); + info("PolytopePrimitiveIntersection::point(", i0, ")"); + const dvec3 v0(vertices->at(i0)); + if (vsg::inside(polytope, v0)) + { + info(" inside(", i0, ") v0 = ", v0); + } } - } -}; + }; -} +} // namespace vsg PolytopeIntersector::PolytopeIntersector(const Polytope& in_polytope, ref_ptr initialArrayData) : Inherit(initialArrayData) @@ -131,27 +131,25 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub clipspace.push_back(dplane(0.0, 1.0, 0.0, -ndc_yMin)); // bottom clipspace.push_back(dplane(0.0, -1.0, 0.0, ndc_yMax)); // top clipspace.push_back(dplane(0.0, 0.0, -1.0, ndc_near)); // near - clipspace.push_back(dplane(0.0, 0.0, 1.0, ndc_far)); // far - + clipspace.push_back(dplane(0.0, 0.0, 1.0, ndc_far)); // far vsg::Polytope eyespace; - for(auto& pl : clipspace) + for (auto& pl : clipspace) { eyespace.push_back(pl * projectionMatrix); } vsg::Polytope worldspace; - for(auto& pl : eyespace) + for (auto& pl : eyespace) { worldspace.push_back(pl * viewMatrix); } _polytopeStack.push_back(worldspace); - std::cout<<"Clip space : "< printPrimtives(*this, arrayState, _polytopeStack.back()); - if (ushort_indices) printPrimtives.drawIndexed(arrayState.topology, ushort_indices, firstIndex, indexCount, firstInstance, instanceCount); - else if (uint_indices) printPrimtives.drawIndexed(arrayState.topology, uint_indices, firstIndex, indexCount, firstInstance, instanceCount); + if (ushort_indices) + printPrimtives.drawIndexed(arrayState.topology, ushort_indices, firstIndex, indexCount, firstInstance, instanceCount); + else if (uint_indices) + printPrimtives.drawIndexed(arrayState.topology, uint_indices, firstIndex, indexCount, firstInstance, instanceCount); return intersections.size() != previous_size; } From 4ce82e3678e7bb671bc35129c501e651da52f3ed Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 27 Sep 2024 17:28:34 +0100 Subject: [PATCH 12/17] Ran build_all_h --- include/vsg/all.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/vsg/all.h b/include/vsg/all.h index 723100f9f7..4f2fd080d6 100644 --- a/include/vsg/all.h +++ b/include/vsg/all.h @@ -292,6 +292,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include +#include #include #include #include From 3d45ae3cda0dfedec4e9e0ca0ec1f7b916f0f372 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 29 Sep 2024 13:56:11 +0100 Subject: [PATCH 13/17] Implemented support for lines intersection with polytope. --- include/vsg/utils/PolytopeIntersector.h | 5 +- include/vsg/utils/PrimitiveFunctor.h | 8 +-- src/vsg/utils/PolytopeIntersector.cpp | 76 ++++++++++++++++++------- 3 files changed, 60 insertions(+), 29 deletions(-) diff --git a/include/vsg/utils/PolytopeIntersector.h b/include/vsg/utils/PolytopeIntersector.h index fa73c9104f..18a2362dfb 100644 --- a/include/vsg/utils/PolytopeIntersector.h +++ b/include/vsg/utils/PolytopeIntersector.h @@ -33,11 +33,10 @@ namespace vsg { public: Intersection() {} - Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, double in_ratio, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex); + Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex); dvec3 localIntersection; dvec3 worldIntersection; - double ratio = 0.0; dmat4 localToWorld; NodePath nodePath; @@ -52,7 +51,7 @@ namespace vsg using Intersections = std::vector>; Intersections intersections; - ref_ptr add(const dvec3& coord, double ratio, const IndexRatios& indexRatios, uint32_t instanceIndex); + ref_ptr add(const dvec3& coord, const IndexRatios& indexRatios, uint32_t instanceIndex); void pushTransform(const Transform& transform) override; void popTransform() override; diff --git a/include/vsg/utils/PrimitiveFunctor.h b/include/vsg/utils/PrimitiveFunctor.h index 7cc0c96d98..4a504adff5 100644 --- a/include/vsg/utils/PrimitiveFunctor.h +++ b/include/vsg/utils/PrimitiveFunctor.h @@ -29,9 +29,9 @@ namespace vsg void draw(VkPrimitiveTopology topology, uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) { uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; - for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) + for (uint32_t inst = firstInstance; inst < lastIndex; ++inst) { - if (!T::instance(instanceIndex)) continue; + if (!T::instance(inst)) continue; switch (topology) { @@ -104,9 +104,9 @@ namespace vsg void drawIndexed(VkPrimitiveTopology topology, IndexArray indices, uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) { uint32_t lastIndex = instanceCount > 1 ? (firstInstance + instanceCount) : firstInstance + 1; - for (uint32_t instanceIndex = firstInstance; instanceIndex < lastIndex; ++instanceIndex) + for (uint32_t inst = firstInstance; inst < lastIndex; ++inst) { - if (!T::instance(instanceIndex)) continue; + if (!T::instance(inst)) continue; switch (topology) { diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 52e1deebf8..715c838344 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -36,56 +36,83 @@ namespace vsg struct PolytopePrimitiveIntersection { - PolytopeIntersector& polyopeIntersector; + PolytopeIntersector& intersector; ArrayState& arrayState; const Polytope& polytope; ref_ptr vertices; + uint32_t instanceIndex = 0; PolytopePrimitiveIntersection(PolytopeIntersector& in_polyopeIntersector, ArrayState& in_arrayState, const Polytope& in_polytope) : - polyopeIntersector(in_polyopeIntersector), + intersector(in_polyopeIntersector), arrayState(in_arrayState), polytope(in_polytope) {} bool instance(uint32_t index) { - info("PolytopePrimitiveIntersection::instance(", index, ")"); + //info("PolytopePrimitiveIntersection::instance(", index, ")"); vertices = arrayState.vertexArray(index); + instanceIndex = index; return vertices.valid(); } void triangle(uint32_t i0, uint32_t i1, uint32_t i2) { - info("PolytopePrimitiveIntersection::triangle(", i0, ", ", i1, ", ", i2, ")"); + //info("PolytopePrimitiveIntersection::triangle(", i0, ", ", i1, ", ", i2, ")"); const dvec3 v0(vertices->at(i0)); const dvec3 v1(vertices->at(i1)); const dvec3 v2(vertices->at(i2)); if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1) || vsg::inside(polytope, v2)) { - info(" inside(", i0, ", ", i1, ", ", i2, ") v0 = ", v0, ", v1 = ", v1, " v2 = ", v2); + dvec3 intersection = (v0 + v1 + v2)/3.0; + intersector.add(intersection, {{i0, 1.0}, {i1, 1.0}, {i2, 1.0}}, instanceIndex); + + //info(" inside(", i0, ", ", i1, ", ", i2, ") v0 = ", v0, ", v1 = ", v1, " v2 = ", v2); } } void line(uint32_t i0, uint32_t i1) { - info("PolytopePrimitiveIntersection::line(", i0, ", ", i1, ")"); - const dvec3 v0(vertices->at(i0)); - const dvec3 v1(vertices->at(i1)); +// info("PolytopePrimitiveIntersection::line(", i0, ", ", i1, ")"); + dvec3 v0(vertices->at(i0)); + dvec3 v1(vertices->at(i1)); - if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1)) + for(auto& pl : polytope) { - info(" inside(", i0, ", ", i1, ") v0 = ", v0, ", v1 = ", v1); + double d0 = distance(pl, v0); + double d1 = distance(pl, v1); + if (d0 < 0.0) + { + if (d1 < 0.0) return; // completely outside + + // v0 outside, v1 inside + double r = -d0 / (d1 - d0); + v0 = v0 * (1.0 - r) + v1 * r; + } + else if (d1 < 0.0) + { + // v0 inside, v2 outside + double r = -d1 / (d0 - d1); + v1 = v1 * (1.0 - r) + v0 * r; + } + else + { + // both inside + } } + dvec3 intersection = (v0 + v1)/2.0; + intersector.add(intersection, {{i0, 1.0}, {i1, 1.0}}, instanceIndex); } void point(uint32_t i0) { - info("PolytopePrimitiveIntersection::point(", i0, ")"); + //info("PolytopePrimitiveIntersection::point(", i0, ")"); const dvec3 v0(vertices->at(i0)); if (vsg::inside(polytope, v0)) { - info(" inside(", i0, ") v0 = ", v0); + intersector.add(v0, {{i0, 1.0}}, instanceIndex); + //info(" inside(", i0, ") v0 = ", v0); } } }; @@ -103,7 +130,7 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub { auto viewport = camera.getViewport(); - info("\nPolytopeIntersector::PolytopeIntersector(camera, ", xMin, ", ", yMin, ", ", xMax, ", ", yMax, ")"); + //info("\nPolytopeIntersector::PolytopeIntersector(camera, ", xMin, ", ", yMin, ", ", xMax, ", ", yMax, ")"); auto projectionMatrix = camera.projectionMatrix->transform(); auto viewMatrix = camera.viewMatrix->transform(); @@ -118,12 +145,14 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub double ndc_near = reverse_depth ? viewport.maxDepth : viewport.minDepth; double ndc_far = reverse_depth ? viewport.minDepth : viewport.maxDepth; +#if 0 info("ndc_xMin ", ndc_xMin); info("ndc_xMax ", ndc_xMax); info("ndc_yMin ", ndc_yMin); info("ndc_yMax ", ndc_yMax); info("ndc_near ", ndc_near); info("ndc_far ", ndc_far); +#endif vsg::Polytope clipspace; clipspace.push_back(dplane(1.0, 0.0, 0.0, -ndc_xMin)); // left @@ -147,15 +176,16 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub _polytopeStack.push_back(worldspace); +#if 0 std::cout << "Clip space : " << clipspace << std::endl; std::cout << "Eye space : " << eyespace << std::endl; std::cout << "World space : " << worldspace << std::endl; +#endif } -PolytopeIntersector::Intersection::Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, double in_ratio, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex) : +PolytopeIntersector::Intersection::Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex) : localIntersection(in_localIntersection), worldIntersection(in_worldIntersection), - ratio(in_ratio), localToWorld(in_localToWorld), nodePath(in_nodePath), arrays(in_arrays), @@ -164,20 +194,22 @@ PolytopeIntersector::Intersection::Intersection(const dvec3& in_localIntersectio { } -ref_ptr PolytopeIntersector::add(const dvec3& coord, double ratio, const IndexRatios& indexRatios, uint32_t instanceIndex) +ref_ptr PolytopeIntersector::add(const dvec3& coord, const IndexRatios& indexRatios, uint32_t instanceIndex) { ref_ptr intersection; auto localToWorld = computeTransform(_nodePath); - intersection = Intersection::create(coord, localToWorld * coord, ratio, localToWorld, _nodePath, arrayStateStack.back()->arrays, indexRatios, instanceIndex); + intersection = Intersection::create(coord, localToWorld * coord, localToWorld, _nodePath, arrayStateStack.back()->arrays, indexRatios, instanceIndex); intersections.emplace_back(intersection); + info("PolytopeIntersector::add(", coord, ", indexRatios.size() = ", indexRatios.size(),"...)"); + return intersection; } void PolytopeIntersector::pushTransform(const Transform& transform) { - vsg::info("\nPolytopeIntersector::pushTransform(", transform.className(), ")"); + // vsg::info("\nPolytopeIntersector::pushTransform(", transform.className(), ")"); auto& l2wStack = localToWorldStack(); auto& w2lStack = worldToLocalStack(); @@ -201,7 +233,7 @@ void PolytopeIntersector::pushTransform(const Transform& transform) void PolytopeIntersector::popTransform() { - vsg::info("PolytopeIntersector::popTransform()"); + //vsg::info("PolytopeIntersector::popTransform()"); _polytopeStack.pop_back(); localToWorldStack().pop_back(); @@ -215,14 +247,14 @@ bool PolytopeIntersector::intersects(const dsphere& bs) const auto& polytope = _polytopeStack.back(); - info("PolytopeIntersector::intersects(const dsphere& bs = ", bs.center, ", ", bs.radius, ") : result = ", vsg::intersect(polytope, bs)); + // info("PolytopeIntersector::intersects(const dsphere& bs = ", bs.center, ", ", bs.radius, ") : result = ", vsg::intersect(polytope, bs)); return vsg::intersect(polytope, bs); } bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) { - info("PolytopeIntersector::intersectDraw(", firstVertex, ", ", vertexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); + // info("PolytopeIntersector::intersectDraw(", firstVertex, ", ", vertexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); size_t previous_size = intersections.size(); @@ -236,7 +268,7 @@ bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCou bool PolytopeIntersector::intersectDrawIndexed(uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) { - info("PolytopeIntersector::intersectDrawIndexed(", firstIndex, ", ", indexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); + // info("PolytopeIntersector::intersectDrawIndexed(", firstIndex, ", ", indexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); size_t previous_size = intersections.size(); From 8ec4a0cadb17d20586f5ab901b5202759cca6210 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 30 Sep 2024 17:37:34 +0100 Subject: [PATCH 14/17] Implemented triangle in polytope test using successive clipping of a convex hull. --- src/vsg/utils/PolytopeIntersector.cpp | 131 +++++++++++++++++++------- 1 file changed, 98 insertions(+), 33 deletions(-) diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 715c838344..8607cd56bd 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -39,44 +39,124 @@ namespace vsg PolytopeIntersector& intersector; ArrayState& arrayState; const Polytope& polytope; - ref_ptr vertices; + ref_ptr sourceVertices; uint32_t instanceIndex = 0; + std::vector processedVertices; + std::vector processedDistances; + std::vector trimmedVertices; + std::vector trimmedDistances; + PolytopePrimitiveIntersection(PolytopeIntersector& in_polyopeIntersector, ArrayState& in_arrayState, const Polytope& in_polytope) : intersector(in_polyopeIntersector), arrayState(in_arrayState), - polytope(in_polytope) {} + polytope(in_polytope) + { + size_t maxNumOfProcessedVertices = 3 + polytope.size(); + processedVertices.reserve(maxNumOfProcessedVertices); + processedDistances.reserve(maxNumOfProcessedVertices); + trimmedVertices.reserve(maxNumOfProcessedVertices); + trimmedDistances.reserve(maxNumOfProcessedVertices); + } bool instance(uint32_t index) { //info("PolytopePrimitiveIntersection::instance(", index, ")"); - vertices = arrayState.vertexArray(index); + sourceVertices = arrayState.vertexArray(index); instanceIndex = index; - return vertices.valid(); + return sourceVertices.valid(); } void triangle(uint32_t i0, uint32_t i1, uint32_t i2) { - //info("PolytopePrimitiveIntersection::triangle(", i0, ", ", i1, ", ", i2, ")"); - const dvec3 v0(vertices->at(i0)); - const dvec3 v1(vertices->at(i1)); - const dvec3 v2(vertices->at(i2)); + //info("PolytopePrimitiveIntersection::triangle(", i0, ", ", i1, ", ", i2, ") polytope.size() = ", polytope.size()); + + // create a convex polygon from the 3 input vertices + processedVertices.resize(3); + processedVertices[0] = sourceVertices->at(i0); + processedVertices[1] = sourceVertices->at(i1); + processedVertices[2] = sourceVertices->at(i2); - if (vsg::inside(polytope, v0) || vsg::inside(polytope, v1) || vsg::inside(polytope, v2)) + // trim the convex polygon to each successive plane + for(auto& pl : polytope) { - dvec3 intersection = (v0 + v1 + v2)/3.0; - intersector.add(intersection, {{i0, 1.0}, {i1, 1.0}, {i2, 1.0}}, instanceIndex); + size_t numNegativeDistances = 0; + size_t numPositiveDistances = 0; + size_t numZeroDistances = 0; + processedDistances.resize(0); + for(auto& v :processedVertices) + { + double d = distance(pl, v); + processedDistances.push_back(d); + if (d < 0.0) ++numNegativeDistances; + else if (d > 0.0) ++numPositiveDistances; + else ++numZeroDistances; + } - //info(" inside(", i0, ", ", i1, ", ", i2, ") v0 = ", v0, ", v1 = ", v1, " v2 = ", v2); + if (numNegativeDistances > 0) + { + if (numPositiveDistances==0) + { + return; // wholly outside plane + } + for(size_t i=0; i= 0.0) + { + trimmedVertices.push_back(processedVertices[i]); + trimmedDistances.push_back(processedDistances[i]); + + if (processedDistances[ni] < 0.0) // i inside, ni outside + { + double r = processedDistances[i] / (processedDistances[i] - processedDistances[ni]); + dvec3 v = processedVertices[i] * (1.0 - r) + processedVertices[ni] * r; + + trimmedVertices.push_back(v); + trimmedDistances.push_back(0.0); + } + } + else if (processedDistances[ni] > 0.0) // i inside, ni outside + { + + double r = -processedDistances[i] / (processedDistances[ni] - processedDistances[i]); + dvec3 v = processedVertices[i] * (1.0 - r) + processedVertices[ni] * r; + + trimmedVertices.push_back(v); + trimmedDistances.push_back(0.0); + } + } + + // swap the newly trimmed with processed so they can be used in the new plane test + processedVertices.swap(trimmedVertices); + processedDistances.swap(trimmedDistances); + + trimmedVertices.clear(); + trimmedDistances.clear(); + + if (processedVertices.size()<2) + { + return; // no triangle remaining inside plan + } + } + } + + dvec3 intersection(0.0, 0.0, 0.0); + for(auto& v :processedVertices) + { + intersection += v; } + intersection /= static_cast(processedVertices.size()); + + intersector.add(intersection, {{i0, 1.0}, {i1, 1.0}, {i2, 1.0}}, instanceIndex); } void line(uint32_t i0, uint32_t i1) { // info("PolytopePrimitiveIntersection::line(", i0, ", ", i1, ")"); - dvec3 v0(vertices->at(i0)); - dvec3 v1(vertices->at(i1)); + dvec3 v0(sourceVertices->at(i0)); + dvec3 v1(sourceVertices->at(i1)); for(auto& pl : polytope) { @@ -108,7 +188,7 @@ namespace vsg void point(uint32_t i0) { //info("PolytopePrimitiveIntersection::point(", i0, ")"); - const dvec3 v0(vertices->at(i0)); + const dvec3 v0(sourceVertices->at(i0)); if (vsg::inside(polytope, v0)) { intersector.add(v0, {{i0, 1.0}}, instanceIndex); @@ -145,15 +225,6 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub double ndc_near = reverse_depth ? viewport.maxDepth : viewport.minDepth; double ndc_far = reverse_depth ? viewport.minDepth : viewport.maxDepth; -#if 0 - info("ndc_xMin ", ndc_xMin); - info("ndc_xMax ", ndc_xMax); - info("ndc_yMin ", ndc_yMin); - info("ndc_yMax ", ndc_yMax); - info("ndc_near ", ndc_near); - info("ndc_far ", ndc_far); -#endif - vsg::Polytope clipspace; clipspace.push_back(dplane(1.0, 0.0, 0.0, -ndc_xMin)); // left clipspace.push_back(dplane(-1.0, 0.0, 0.0, ndc_xMax)); // right @@ -175,12 +246,6 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub } _polytopeStack.push_back(worldspace); - -#if 0 - std::cout << "Clip space : " << clipspace << std::endl; - std::cout << "Eye space : " << eyespace << std::endl; - std::cout << "World space : " << worldspace << std::endl; -#endif } PolytopeIntersector::Intersection::Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex) : @@ -202,7 +267,7 @@ ref_ptr PolytopeIntersector::add(const dvec3& intersection = Intersection::create(coord, localToWorld * coord, localToWorld, _nodePath, arrayStateStack.back()->arrays, indexRatios, instanceIndex); intersections.emplace_back(intersection); - info("PolytopeIntersector::add(", coord, ", indexRatios.size() = ", indexRatios.size(),"...)"); + // info("PolytopeIntersector::add(", coord, ", indexRatios.size() = ", indexRatios.size(),"...)"); return intersection; } @@ -254,7 +319,7 @@ bool PolytopeIntersector::intersects(const dsphere& bs) bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) { - // info("PolytopeIntersector::intersectDraw(", firstVertex, ", ", vertexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); + //info("\nPolytopeIntersector::intersectDraw(", firstVertex, ", ", vertexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); size_t previous_size = intersections.size(); @@ -268,7 +333,7 @@ bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCou bool PolytopeIntersector::intersectDrawIndexed(uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) { - // info("PolytopeIntersector::intersectDrawIndexed(", firstIndex, ", ", indexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); + //info("\nPolytopeIntersector::intersectDrawIndexed(", firstIndex, ", ", indexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); size_t previous_size = intersections.size(); From ae7846b1d7dd13c19a761006594f1f19a3e37dd3 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 30 Sep 2024 18:05:54 +0100 Subject: [PATCH 15/17] Simplified the PolytopeIntersector::Intersection. --- include/vsg/utils/PolytopeIntersector.h | 6 +++--- src/vsg/utils/PolytopeIntersector.cpp | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/vsg/utils/PolytopeIntersector.h b/include/vsg/utils/PolytopeIntersector.h index 18a2362dfb..33c6c761ae 100644 --- a/include/vsg/utils/PolytopeIntersector.h +++ b/include/vsg/utils/PolytopeIntersector.h @@ -33,7 +33,7 @@ namespace vsg { public: Intersection() {} - Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex); + Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const std::vector& in_indexRatios, uint32_t in_instanceIndex); dvec3 localIntersection; dvec3 worldIntersection; @@ -41,7 +41,7 @@ namespace vsg dmat4 localToWorld; NodePath nodePath; DataList arrays; - IndexRatios indexRatios; + std::vector indices; uint32_t instanceIndex = 0; // return true if Intersection is valid @@ -51,7 +51,7 @@ namespace vsg using Intersections = std::vector>; Intersections intersections; - ref_ptr add(const dvec3& coord, const IndexRatios& indexRatios, uint32_t instanceIndex); + ref_ptr add(const dvec3& coord, const std::vector& indices, uint32_t instanceIndex); void pushTransform(const Transform& transform) override; void popTransform() override; diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 8607cd56bd..e720f2286f 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -149,7 +149,7 @@ namespace vsg } intersection /= static_cast(processedVertices.size()); - intersector.add(intersection, {{i0, 1.0}, {i1, 1.0}, {i2, 1.0}}, instanceIndex); + intersector.add(intersection, {i0, i1, i2}, instanceIndex); } void line(uint32_t i0, uint32_t i1) @@ -181,8 +181,8 @@ namespace vsg // both inside } } - dvec3 intersection = (v0 + v1)/2.0; - intersector.add(intersection, {{i0, 1.0}, {i1, 1.0}}, instanceIndex); + dvec3 intersection = (v0 + v1) * 0.5; + intersector.add(intersection, {i0, i1}, instanceIndex); } void point(uint32_t i0) @@ -191,7 +191,7 @@ namespace vsg const dvec3 v0(sourceVertices->at(i0)); if (vsg::inside(polytope, v0)) { - intersector.add(v0, {{i0, 1.0}}, instanceIndex); + intersector.add(v0, {i0}, instanceIndex); //info(" inside(", i0, ") v0 = ", v0); } } @@ -248,23 +248,23 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub _polytopeStack.push_back(worldspace); } -PolytopeIntersector::Intersection::Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const IndexRatios& in_indexRatios, uint32_t in_instanceIndex) : +PolytopeIntersector::Intersection::Intersection(const dvec3& in_localIntersection, const dvec3& in_worldIntersection, const dmat4& in_localToWorld, const NodePath& in_nodePath, const DataList& in_arrays, const std::vector& in_indices, uint32_t in_instanceIndex) : localIntersection(in_localIntersection), worldIntersection(in_worldIntersection), localToWorld(in_localToWorld), nodePath(in_nodePath), arrays(in_arrays), - indexRatios(in_indexRatios), + indices(in_indices), instanceIndex(in_instanceIndex) { } -ref_ptr PolytopeIntersector::add(const dvec3& coord, const IndexRatios& indexRatios, uint32_t instanceIndex) +ref_ptr PolytopeIntersector::add(const dvec3& coord, const std::vector& indices, uint32_t instanceIndex) { ref_ptr intersection; auto localToWorld = computeTransform(_nodePath); - intersection = Intersection::create(coord, localToWorld * coord, localToWorld, _nodePath, arrayStateStack.back()->arrays, indexRatios, instanceIndex); + intersection = Intersection::create(coord, localToWorld * coord, localToWorld, _nodePath, arrayStateStack.back()->arrays, indices, instanceIndex); intersections.emplace_back(intersection); // info("PolytopeIntersector::add(", coord, ", indexRatios.size() = ", indexRatios.size(),"...)"); From 193891c10fd7710ea2ce6f93e5f424aecc7a888d Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 30 Sep 2024 18:09:31 +0100 Subject: [PATCH 16/17] Ran clang-format --- src/vsg/utils/PolytopeIntersector.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index e720f2286f..f9944c8985 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -79,30 +79,33 @@ namespace vsg processedVertices[2] = sourceVertices->at(i2); // trim the convex polygon to each successive plane - for(auto& pl : polytope) + for (auto& pl : polytope) { size_t numNegativeDistances = 0; size_t numPositiveDistances = 0; size_t numZeroDistances = 0; processedDistances.resize(0); - for(auto& v :processedVertices) + for (auto& v : processedVertices) { double d = distance(pl, v); processedDistances.push_back(d); - if (d < 0.0) ++numNegativeDistances; - else if (d > 0.0) ++numPositiveDistances; - else ++numZeroDistances; + if (d < 0.0) + ++numNegativeDistances; + else if (d > 0.0) + ++numPositiveDistances; + else + ++numZeroDistances; } if (numNegativeDistances > 0) { - if (numPositiveDistances==0) + if (numPositiveDistances == 0) { return; // wholly outside plane } - for(size_t i=0; i= 0.0) { trimmedVertices.push_back(processedVertices[i]); @@ -135,7 +138,7 @@ namespace vsg trimmedVertices.clear(); trimmedDistances.clear(); - if (processedVertices.size()<2) + if (processedVertices.size() < 2) { return; // no triangle remaining inside plan } @@ -143,7 +146,7 @@ namespace vsg } dvec3 intersection(0.0, 0.0, 0.0); - for(auto& v :processedVertices) + for (auto& v : processedVertices) { intersection += v; } @@ -154,11 +157,11 @@ namespace vsg void line(uint32_t i0, uint32_t i1) { -// info("PolytopePrimitiveIntersection::line(", i0, ", ", i1, ")"); + // info("PolytopePrimitiveIntersection::line(", i0, ", ", i1, ")"); dvec3 v0(sourceVertices->at(i0)); dvec3 v1(sourceVertices->at(i1)); - for(auto& pl : polytope) + for (auto& pl : polytope) { double d0 = distance(pl, v0); double d1 = distance(pl, v1); From 08d1bc84fe17cab942a3993c853306ad30412d2a Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 30 Sep 2024 18:13:24 +0100 Subject: [PATCH 17/17] Removed debug code. --- src/vsg/utils/PolytopeIntersector.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index f9944c8985..287556811c 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -61,8 +61,6 @@ namespace vsg bool instance(uint32_t index) { - //info("PolytopePrimitiveIntersection::instance(", index, ")"); - sourceVertices = arrayState.vertexArray(index); instanceIndex = index; return sourceVertices.valid(); @@ -70,8 +68,6 @@ namespace vsg void triangle(uint32_t i0, uint32_t i1, uint32_t i2) { - //info("PolytopePrimitiveIntersection::triangle(", i0, ", ", i1, ", ", i2, ") polytope.size() = ", polytope.size()); - // create a convex polygon from the 3 input vertices processedVertices.resize(3); processedVertices[0] = sourceVertices->at(i0); @@ -157,7 +153,6 @@ namespace vsg void line(uint32_t i0, uint32_t i1) { - // info("PolytopePrimitiveIntersection::line(", i0, ", ", i1, ")"); dvec3 v0(sourceVertices->at(i0)); dvec3 v1(sourceVertices->at(i1)); @@ -179,10 +174,6 @@ namespace vsg double r = -d1 / (d0 - d1); v1 = v1 * (1.0 - r) + v0 * r; } - else - { - // both inside - } } dvec3 intersection = (v0 + v1) * 0.5; intersector.add(intersection, {i0, i1}, instanceIndex); @@ -190,12 +181,10 @@ namespace vsg void point(uint32_t i0) { - //info("PolytopePrimitiveIntersection::point(", i0, ")"); const dvec3 v0(sourceVertices->at(i0)); if (vsg::inside(polytope, v0)) { intersector.add(v0, {i0}, instanceIndex); - //info(" inside(", i0, ") v0 = ", v0); } } }; @@ -213,8 +202,6 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub { auto viewport = camera.getViewport(); - //info("\nPolytopeIntersector::PolytopeIntersector(camera, ", xMin, ", ", yMin, ", ", xMax, ", ", yMax, ")"); - auto projectionMatrix = camera.projectionMatrix->transform(); auto viewMatrix = camera.viewMatrix->transform(); bool reverse_depth = (projectionMatrix(2, 2) > 0.0); @@ -270,15 +257,11 @@ ref_ptr PolytopeIntersector::add(const dvec3& intersection = Intersection::create(coord, localToWorld * coord, localToWorld, _nodePath, arrayStateStack.back()->arrays, indices, instanceIndex); intersections.emplace_back(intersection); - // info("PolytopeIntersector::add(", coord, ", indexRatios.size() = ", indexRatios.size(),"...)"); - return intersection; } void PolytopeIntersector::pushTransform(const Transform& transform) { - // vsg::info("\nPolytopeIntersector::pushTransform(", transform.className(), ")"); - auto& l2wStack = localToWorldStack(); auto& w2lStack = worldToLocalStack(); @@ -301,8 +284,6 @@ void PolytopeIntersector::pushTransform(const Transform& transform) void PolytopeIntersector::popTransform() { - //vsg::info("PolytopeIntersector::popTransform()"); - _polytopeStack.pop_back(); localToWorldStack().pop_back(); worldToLocalStack().pop_back(); @@ -310,20 +291,15 @@ void PolytopeIntersector::popTransform() bool PolytopeIntersector::intersects(const dsphere& bs) { - //debug("intersects( center = ", bs.center, ", radius = ", bs.radius, ")"); if (!bs.valid()) return false; const auto& polytope = _polytopeStack.back(); - // info("PolytopeIntersector::intersects(const dsphere& bs = ", bs.center, ", ", bs.radius, ") : result = ", vsg::intersect(polytope, bs)); - return vsg::intersect(polytope, bs); } bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) { - //info("\nPolytopeIntersector::intersectDraw(", firstVertex, ", ", vertexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); - size_t previous_size = intersections.size(); auto& arrayState = *arrayStateStack.back(); @@ -336,8 +312,6 @@ bool PolytopeIntersector::intersectDraw(uint32_t firstVertex, uint32_t vertexCou bool PolytopeIntersector::intersectDrawIndexed(uint32_t firstIndex, uint32_t indexCount, uint32_t firstInstance, uint32_t instanceCount) { - //info("\nPolytopeIntersector::intersectDrawIndexed(", firstIndex, ", ", indexCount, ", ", firstInstance, ", ", instanceCount, ")) todo."); - size_t previous_size = intersections.size(); auto& arrayState = *arrayStateStack.back();