aboutsummaryrefslogtreecommitdiff
path: root/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp')
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp760
1 files changed, 380 insertions, 380 deletions
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp
index 89df930..0f153b7 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp
@@ -1,380 +1,380 @@
-// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-#include "NvBlastExtDamageAcceleratorAABBTree.h"
-#include "NvBlastIndexFns.h"
-#include "NvBlastAssert.h"
-#include "PxVec4.h"
-#include <algorithm>
-
-using namespace physx;
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Creation
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-ExtDamageAcceleratorAABBTree* ExtDamageAcceleratorAABBTree::create(const NvBlastAsset* asset)
-{
- ExtDamageAcceleratorAABBTree* tree = NVBLAST_NEW(Nv::Blast::ExtDamageAcceleratorAABBTree) ();
- tree->build(asset);
- return tree;
-}
-
-
-void ExtDamageAcceleratorAABBTree::release()
-{
- NVBLAST_DELETE(this, ExtDamageAcceleratorAABBTree);
-}
-
-
-void ExtDamageAcceleratorAABBTree::build(const NvBlastAsset* asset)
-{
- NVBLAST_ASSERT(m_root == nullptr);
-
- const NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, logLL);
- const NvBlastBond* bonds = NvBlastAssetGetBonds(asset, logLL);
- const NvBlastChunk* chunks = NvBlastAssetGetChunks(asset, logLL);
- const uint32_t N = NvBlastAssetGetBondCount(asset, logLL);
-
- m_indices.resizeUninitialized(N);
- m_points.resizeUninitialized(N);
- m_segments.resizeUninitialized(N);
- m_bonds.resizeUninitialized(N);
- m_nodes.reserve(2 * N);
-
- for (uint32_t node0 = 0; node0 < graph.nodeCount; ++node0)
- {
- for (uint32_t j = graph.adjacencyPartition[node0]; j < graph.adjacencyPartition[node0 + 1]; ++j)
- {
- uint32_t bondIndex = graph.adjacentBondIndices[j];
- uint32_t node1 = graph.adjacentNodeIndices[j];
- if (node0 < node1)
- {
- const NvBlastBond& bond = bonds[bondIndex];
- const PxVec3& p = (reinterpret_cast<const PxVec3&>(bond.centroid));
- m_points[bondIndex] = p;
- m_indices[bondIndex] = bondIndex;
- m_bonds[bondIndex].node0 = node0;
- m_bonds[bondIndex].node1 = node1;
-
- // filling bond segments as a connection of 2 chunk centroids
- const uint32_t chunk0 = graph.chunkIndices[node0];
- const uint32_t chunk1 = graph.chunkIndices[node1];
- if (isInvalidIndex(chunk1))
- {
- // for world node we don't have it's centroid, so approximate with projection on bond normal
- m_segments[bondIndex].p0 = (reinterpret_cast<const PxVec3&>(chunks[chunk0].centroid));
- const PxVec3 normal = (reinterpret_cast<const PxVec3&>(bond.normal));
- m_segments[bondIndex].p1 = m_segments[bondIndex].p0 + normal * (p - m_segments[bondIndex].p0).dot(normal) * 2;
-
- }
- else
- {
- m_segments[bondIndex].p0 = (reinterpret_cast<const PxVec3&>(chunks[chunk0].centroid));
- m_segments[bondIndex].p1 = (reinterpret_cast<const PxVec3&>(chunks[chunk1].centroid));
- }
- }
- }
-
- }
-
- int rootIndex = N > 0 ? createNode(0, N - 1, 0) : -1;
- m_root = rootIndex >= 0 ? &m_nodes[rootIndex] : nullptr;
-}
-
-int ExtDamageAcceleratorAABBTree::createNode(uint32_t startIdx, uint32_t endIdx, uint32_t depth)
-{
- if (startIdx > endIdx)
- return -1;
-
- Node node;
- node.first = startIdx;
- node.last = endIdx;
-
- // calc node bounds
- node.pointsBound = PxBounds3::empty();
- node.segmentsBound = PxBounds3::empty();
- for (uint32_t i = node.first; i <= node.last; i++)
- {
- const uint32_t idx = m_indices[i];
- node.pointsBound.include(m_points[idx]);
- node.segmentsBound.include(m_segments[idx].p0);
- node.segmentsBound.include(m_segments[idx].p1);
- }
-
- // select axis of biggest extent
- const PxVec3 ext = node.pointsBound.getExtents();
- uint32_t axis = 0;
- for (uint32_t k = 1; k < 3; k++)
- {
- if (ext[k] > ext[axis])
- {
- axis = k;
- }
- }
-
- // split on selected axis and partially sort around the middle
- const uint32_t mid = startIdx + (endIdx - startIdx) / 2;
- std::nth_element(m_indices.begin() + startIdx, m_indices.begin() + mid, m_indices.begin() + endIdx + 1, [&](uint32_t lhs, uint32_t rhs)
- {
- return m_points[lhs][axis] < m_points[rhs][axis];
- });
-
- const uint32_t BUCKET = 32;
- if (endIdx - startIdx > BUCKET && mid > startIdx && mid < endIdx)
- {
- node.child[0] = createNode(startIdx, mid, depth + 1);
- node.child[1] = createNode(mid + 1, endIdx, depth + 1);
- }
- else
- {
- node.child[0] = -1;
- node.child[1] = -1;
- }
-
- m_nodes.pushBack(node);
-
- return m_nodes.size() - 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Queries
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void ExtDamageAcceleratorAABBTree::findInBounds(const physx::PxBounds3& bounds, ResultCallback& callback, bool segments) const
-{
- if (m_root)
- {
- if (segments)
- findSegmentsInBounds(*m_root, callback, bounds);
- else
- findPointsInBounds(*m_root, callback, bounds);
- callback.dispatch();
- }
-}
-
-void ExtDamageAcceleratorAABBTree::findPointsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const
-{
- if (!bounds.intersects(node.pointsBound))
- {
- return;
- }
-
- // if search bound contains node bound, simply add all point indexes.
- if (node.pointsBound.isInside(bounds))
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- pushResult(callback, m_indices[i]);
- return; // early pruning.
- }
-
- if (node.child[0] < 0)
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- {
- const uint32_t idx = m_indices[i];
- if (bounds.contains(m_points[idx]))
- pushResult(callback, idx);
- }
-
- return;
- }
-
- // check whether child nodes are in range.
- for (uint32_t c = 0; c < 2; ++c)
- {
- findPointsInBounds(m_nodes[node.child[c]], callback, bounds);
- }
-}
-
-void ExtDamageAcceleratorAABBTree::findSegmentsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const
-{
- if (!bounds.intersects(node.segmentsBound))
- {
- return;
- }
-
- // if search bound contains node bound, simply add all point indexes.
- if (node.segmentsBound.isInside(bounds))
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- pushResult(callback, m_indices[i]);
- return; // early pruning.
- }
-
- if (node.child[0] < 0)
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- {
- const uint32_t idx = m_indices[i];
- if (bounds.contains(m_segments[idx].p0) || bounds.contains(m_segments[idx].p1))
- pushResult(callback, idx);
- }
-
- return;
- }
-
- // check whether child nodes are in range.
- for (uint32_t c = 0; c < 2; ++c)
- {
- findSegmentsInBounds(m_nodes[node.child[c]], callback, bounds);
- }
-}
-
-bool intersectSegmentPlane(const PxVec3& v1, const PxVec3& v2, const PxPlane& p)
-{
- const bool s1 = p.distance(v1) > 0.f;
- const bool s2 = p.distance(v2) > 0.f;
- return (s1 && !s2) || (s2 && !s1);
-}
-
-bool intersectBoundsPlane(const PxBounds3& b, const PxPlane& p)
-{
- const PxVec3 extents = b.getExtents();
- const PxVec3 center = b.getCenter();
-
- float r = extents.x * PxAbs(p.n.x) + extents.y * PxAbs(p.n.y) + extents.z * PxAbs(p.n.z);
- float s = p.n.dot(center) + p.d;
-
- return PxAbs(s) <= r;
-}
-
-void ExtDamageAcceleratorAABBTree::findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const
-{
- if (m_root)
- {
- findSegmentsPlaneIntersected(*m_root, resultCallback, plane);
- resultCallback.dispatch();
- }
-}
-
-void ExtDamageAcceleratorAABBTree::findSegmentsPlaneIntersected(const Node& node, ResultCallback& callback, const physx::PxPlane& plane) const
-{
- if (!intersectBoundsPlane(node.segmentsBound, plane))
- {
- return;
- }
-
- if (node.child[0] < 0)
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- {
- const uint32_t idx = m_indices[i];
- if (intersectSegmentPlane(m_segments[idx].p0, m_segments[idx].p1, plane))
- pushResult(callback, idx);
- }
-
- return;
- }
-
- // check whether child nodes are in range.
- for (uint32_t c = 0; c < 2; ++c)
- {
- findSegmentsPlaneIntersected(m_nodes[node.child[c]], callback, plane);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Debug Render
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-static uint32_t PxVec4ToU32Color(const PxVec4& color)
-{
- uint32_t c = 0;
- c |= (int)(color.w * 255); c <<= 8;
- c |= (int)(color.z * 255); c <<= 8;
- c |= (int)(color.y * 255); c <<= 8;
- c |= (int)(color.x * 255);
- return c;
-}
-
-Nv::Blast::DebugBuffer ExtDamageAcceleratorAABBTree::fillDebugRender(int depth, bool segments)
-{
- Nv::Blast::DebugBuffer debugBuffer = { nullptr, 0 };
-
- m_debugLineBuffer.clear();
-
- if (m_root)
- {
- fillDebugBuffer(*m_root, 0, depth, segments);
- }
-
- debugBuffer.lines = m_debugLineBuffer.begin();
- debugBuffer.lineCount = m_debugLineBuffer.size();
-
- return debugBuffer;
-}
-
-void ExtDamageAcceleratorAABBTree::fillDebugBuffer(const Node& node, int currentDepth, int depth, bool segments)
-{
- if (depth < 0 || currentDepth == depth)
- {
- const PxVec4 LEAF_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
- const PxVec4 NON_LEAF_COLOR(0.3f, 0.3f, 0.3f, 1.0f);
-
- // draw box
- const PxBounds3 bounds = segments ? node.segmentsBound : node.pointsBound;
- const PxVec3 center = bounds.getCenter();
- const PxVec3 extents = bounds.getExtents();
-
- const int vs[] = { 0,3,5,6 };
- for (int i = 0; i < 4; i++)
- {
- int v = vs[i];
- for (int d = 1; d < 8; d <<= 1)
- {
- auto flip = [](int x, int k) { return ((x >> k) & 1) * 2.f - 1.f; };
- const float s = std::pow(0.99f, currentDepth);
- PxVec3 p0 = center + s * extents.multiply(PxVec3(flip(v, 0), flip(v, 1), flip(v, 2)));
- PxVec3 p1 = center + s * extents.multiply(PxVec3(flip(v^d, 0), flip(v^d, 1), flip(v^d, 2)));
- m_debugLineBuffer.pushBack(Nv::Blast::DebugLine(
- reinterpret_cast<NvcVec3&>(p0),
- reinterpret_cast<NvcVec3&>(p1),
- PxVec4ToU32Color(LEAF_COLOR * (1.f - (currentDepth + 1) * 0.1f)))
- );
- }
- }
- }
-
- for (uint32_t i = 0; i < 2; ++i)
- {
- if (node.child[i] >= 0)
- {
- fillDebugBuffer(m_nodes[node.child[i]], currentDepth + 1, depth, segments);
- }
- }
-}
-
-
-} // namespace Blast
-} // namespace Nv
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+#include "NvBlastExtDamageAcceleratorAABBTree.h"
+#include "NvBlastIndexFns.h"
+#include "NvBlastAssert.h"
+#include "PxVec4.h"
+#include <algorithm>
+
+using namespace physx;
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Creation
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ExtDamageAcceleratorAABBTree* ExtDamageAcceleratorAABBTree::create(const NvBlastAsset* asset)
+{
+ ExtDamageAcceleratorAABBTree* tree = NVBLAST_NEW(Nv::Blast::ExtDamageAcceleratorAABBTree) ();
+ tree->build(asset);
+ return tree;
+}
+
+
+void ExtDamageAcceleratorAABBTree::release()
+{
+ NVBLAST_DELETE(this, ExtDamageAcceleratorAABBTree);
+}
+
+
+void ExtDamageAcceleratorAABBTree::build(const NvBlastAsset* asset)
+{
+ NVBLAST_ASSERT(m_root == nullptr);
+
+ const NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, logLL);
+ const NvBlastBond* bonds = NvBlastAssetGetBonds(asset, logLL);
+ const NvBlastChunk* chunks = NvBlastAssetGetChunks(asset, logLL);
+ const uint32_t N = NvBlastAssetGetBondCount(asset, logLL);
+
+ m_indices.resizeUninitialized(N);
+ m_points.resizeUninitialized(N);
+ m_segments.resizeUninitialized(N);
+ m_bonds.resizeUninitialized(N);
+ m_nodes.reserve(2 * N);
+
+ for (uint32_t node0 = 0; node0 < graph.nodeCount; ++node0)
+ {
+ for (uint32_t j = graph.adjacencyPartition[node0]; j < graph.adjacencyPartition[node0 + 1]; ++j)
+ {
+ uint32_t bondIndex = graph.adjacentBondIndices[j];
+ uint32_t node1 = graph.adjacentNodeIndices[j];
+ if (node0 < node1)
+ {
+ const NvBlastBond& bond = bonds[bondIndex];
+ const PxVec3& p = (reinterpret_cast<const PxVec3&>(bond.centroid));
+ m_points[bondIndex] = p;
+ m_indices[bondIndex] = bondIndex;
+ m_bonds[bondIndex].node0 = node0;
+ m_bonds[bondIndex].node1 = node1;
+
+ // filling bond segments as a connection of 2 chunk centroids
+ const uint32_t chunk0 = graph.chunkIndices[node0];
+ const uint32_t chunk1 = graph.chunkIndices[node1];
+ if (isInvalidIndex(chunk1))
+ {
+ // for world node we don't have it's centroid, so approximate with projection on bond normal
+ m_segments[bondIndex].p0 = (reinterpret_cast<const PxVec3&>(chunks[chunk0].centroid));
+ const PxVec3 normal = (reinterpret_cast<const PxVec3&>(bond.normal));
+ m_segments[bondIndex].p1 = m_segments[bondIndex].p0 + normal * (p - m_segments[bondIndex].p0).dot(normal) * 2;
+
+ }
+ else
+ {
+ m_segments[bondIndex].p0 = (reinterpret_cast<const PxVec3&>(chunks[chunk0].centroid));
+ m_segments[bondIndex].p1 = (reinterpret_cast<const PxVec3&>(chunks[chunk1].centroid));
+ }
+ }
+ }
+
+ }
+
+ int rootIndex = N > 0 ? createNode(0, N - 1, 0) : -1;
+ m_root = rootIndex >= 0 ? &m_nodes[rootIndex] : nullptr;
+}
+
+int ExtDamageAcceleratorAABBTree::createNode(uint32_t startIdx, uint32_t endIdx, uint32_t depth)
+{
+ if (startIdx > endIdx)
+ return -1;
+
+ Node node;
+ node.first = startIdx;
+ node.last = endIdx;
+
+ // calc node bounds
+ node.pointsBound = PxBounds3::empty();
+ node.segmentsBound = PxBounds3::empty();
+ for (uint32_t i = node.first; i <= node.last; i++)
+ {
+ const uint32_t idx = m_indices[i];
+ node.pointsBound.include(m_points[idx]);
+ node.segmentsBound.include(m_segments[idx].p0);
+ node.segmentsBound.include(m_segments[idx].p1);
+ }
+
+ // select axis of biggest extent
+ const PxVec3 ext = node.pointsBound.getExtents();
+ uint32_t axis = 0;
+ for (uint32_t k = 1; k < 3; k++)
+ {
+ if (ext[k] > ext[axis])
+ {
+ axis = k;
+ }
+ }
+
+ // split on selected axis and partially sort around the middle
+ const uint32_t mid = startIdx + (endIdx - startIdx) / 2;
+ std::nth_element(m_indices.begin() + startIdx, m_indices.begin() + mid, m_indices.begin() + endIdx + 1, [&](uint32_t lhs, uint32_t rhs)
+ {
+ return m_points[lhs][axis] < m_points[rhs][axis];
+ });
+
+ const uint32_t BUCKET = 32;
+ if (endIdx - startIdx > BUCKET && mid > startIdx && mid < endIdx)
+ {
+ node.child[0] = createNode(startIdx, mid, depth + 1);
+ node.child[1] = createNode(mid + 1, endIdx, depth + 1);
+ }
+ else
+ {
+ node.child[0] = -1;
+ node.child[1] = -1;
+ }
+
+ m_nodes.pushBack(node);
+
+ return m_nodes.size() - 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Queries
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void ExtDamageAcceleratorAABBTree::findInBounds(const physx::PxBounds3& bounds, ResultCallback& callback, bool segments) const
+{
+ if (m_root)
+ {
+ if (segments)
+ findSegmentsInBounds(*m_root, callback, bounds);
+ else
+ findPointsInBounds(*m_root, callback, bounds);
+ callback.dispatch();
+ }
+}
+
+void ExtDamageAcceleratorAABBTree::findPointsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const
+{
+ if (!bounds.intersects(node.pointsBound))
+ {
+ return;
+ }
+
+ // if search bound contains node bound, simply add all point indexes.
+ if (node.pointsBound.isInside(bounds))
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ pushResult(callback, m_indices[i]);
+ return; // early pruning.
+ }
+
+ if (node.child[0] < 0)
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ {
+ const uint32_t idx = m_indices[i];
+ if (bounds.contains(m_points[idx]))
+ pushResult(callback, idx);
+ }
+
+ return;
+ }
+
+ // check whether child nodes are in range.
+ for (uint32_t c = 0; c < 2; ++c)
+ {
+ findPointsInBounds(m_nodes[node.child[c]], callback, bounds);
+ }
+}
+
+void ExtDamageAcceleratorAABBTree::findSegmentsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const
+{
+ if (!bounds.intersects(node.segmentsBound))
+ {
+ return;
+ }
+
+ // if search bound contains node bound, simply add all point indexes.
+ if (node.segmentsBound.isInside(bounds))
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ pushResult(callback, m_indices[i]);
+ return; // early pruning.
+ }
+
+ if (node.child[0] < 0)
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ {
+ const uint32_t idx = m_indices[i];
+ if (bounds.contains(m_segments[idx].p0) || bounds.contains(m_segments[idx].p1))
+ pushResult(callback, idx);
+ }
+
+ return;
+ }
+
+ // check whether child nodes are in range.
+ for (uint32_t c = 0; c < 2; ++c)
+ {
+ findSegmentsInBounds(m_nodes[node.child[c]], callback, bounds);
+ }
+}
+
+bool intersectSegmentPlane(const PxVec3& v1, const PxVec3& v2, const PxPlane& p)
+{
+ const bool s1 = p.distance(v1) > 0.f;
+ const bool s2 = p.distance(v2) > 0.f;
+ return (s1 && !s2) || (s2 && !s1);
+}
+
+bool intersectBoundsPlane(const PxBounds3& b, const PxPlane& p)
+{
+ const PxVec3 extents = b.getExtents();
+ const PxVec3 center = b.getCenter();
+
+ float r = extents.x * PxAbs(p.n.x) + extents.y * PxAbs(p.n.y) + extents.z * PxAbs(p.n.z);
+ float s = p.n.dot(center) + p.d;
+
+ return PxAbs(s) <= r;
+}
+
+void ExtDamageAcceleratorAABBTree::findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const
+{
+ if (m_root)
+ {
+ findSegmentsPlaneIntersected(*m_root, resultCallback, plane);
+ resultCallback.dispatch();
+ }
+}
+
+void ExtDamageAcceleratorAABBTree::findSegmentsPlaneIntersected(const Node& node, ResultCallback& callback, const physx::PxPlane& plane) const
+{
+ if (!intersectBoundsPlane(node.segmentsBound, plane))
+ {
+ return;
+ }
+
+ if (node.child[0] < 0)
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ {
+ const uint32_t idx = m_indices[i];
+ if (intersectSegmentPlane(m_segments[idx].p0, m_segments[idx].p1, plane))
+ pushResult(callback, idx);
+ }
+
+ return;
+ }
+
+ // check whether child nodes are in range.
+ for (uint32_t c = 0; c < 2; ++c)
+ {
+ findSegmentsPlaneIntersected(m_nodes[node.child[c]], callback, plane);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Debug Render
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static uint32_t PxVec4ToU32Color(const PxVec4& color)
+{
+ uint32_t c = 0;
+ c |= (int)(color.w * 255); c <<= 8;
+ c |= (int)(color.z * 255); c <<= 8;
+ c |= (int)(color.y * 255); c <<= 8;
+ c |= (int)(color.x * 255);
+ return c;
+}
+
+Nv::Blast::DebugBuffer ExtDamageAcceleratorAABBTree::fillDebugRender(int depth, bool segments)
+{
+ Nv::Blast::DebugBuffer debugBuffer = { nullptr, 0 };
+
+ m_debugLineBuffer.clear();
+
+ if (m_root)
+ {
+ fillDebugBuffer(*m_root, 0, depth, segments);
+ }
+
+ debugBuffer.lines = m_debugLineBuffer.begin();
+ debugBuffer.lineCount = m_debugLineBuffer.size();
+
+ return debugBuffer;
+}
+
+void ExtDamageAcceleratorAABBTree::fillDebugBuffer(const Node& node, int currentDepth, int depth, bool segments)
+{
+ if (depth < 0 || currentDepth == depth)
+ {
+ const PxVec4 LEAF_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
+ const PxVec4 NON_LEAF_COLOR(0.3f, 0.3f, 0.3f, 1.0f);
+
+ // draw box
+ const PxBounds3 bounds = segments ? node.segmentsBound : node.pointsBound;
+ const PxVec3 center = bounds.getCenter();
+ const PxVec3 extents = bounds.getExtents();
+
+ const int vs[] = { 0,3,5,6 };
+ for (int i = 0; i < 4; i++)
+ {
+ int v = vs[i];
+ for (int d = 1; d < 8; d <<= 1)
+ {
+ auto flip = [](int x, int k) { return ((x >> k) & 1) * 2.f - 1.f; };
+ const float s = std::pow(0.99f, currentDepth);
+ PxVec3 p0 = center + s * extents.multiply(PxVec3(flip(v, 0), flip(v, 1), flip(v, 2)));
+ PxVec3 p1 = center + s * extents.multiply(PxVec3(flip(v^d, 0), flip(v^d, 1), flip(v^d, 2)));
+ m_debugLineBuffer.pushBack(Nv::Blast::DebugLine(
+ reinterpret_cast<NvcVec3&>(p0),
+ reinterpret_cast<NvcVec3&>(p1),
+ PxVec4ToU32Color(LEAF_COLOR * (1.f - (currentDepth + 1) * 0.1f)))
+ );
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < 2; ++i)
+ {
+ if (node.child[i] >= 0)
+ {
+ fillDebugBuffer(m_nodes[node.child[i]], currentDepth + 1, depth, segments);
+ }
+ }
+}
+
+
+} // namespace Blast
+} // namespace Nv