aboutsummaryrefslogtreecommitdiff
path: root/sdk/extensions/shaders/source
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/extensions/shaders/source')
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp760
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h296
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h192
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp86
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp1526
5 files changed, 1430 insertions, 1430 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
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h
index baded40..505db50 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h
@@ -1,148 +1,148 @@
-// 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.
-
-#pragma once
-
-#include "NvBlastExtDamageAcceleratorInternal.h"
-#include "NvBlast.h"
-#include "NvBlastArray.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-class ExtDamageAcceleratorAABBTree final : public ExtDamageAcceleratorInternal
-{
-public:
- //////// ctor ////////
-
- ExtDamageAcceleratorAABBTree() :
- m_root(nullptr)
- {
- }
-
- virtual ~ExtDamageAcceleratorAABBTree()
- {
- }
-
- static ExtDamageAcceleratorAABBTree* create(const NvBlastAsset* asset);
-
-
- //////// interface ////////
-
- virtual void release() override;
-
- virtual void findBondCentroidsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const override
- {
- const_cast<ExtDamageAcceleratorAABBTree*>(this)->findInBounds(bounds, resultCallback, false);
- }
-
- virtual void findBondSegmentsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const override
- {
- const_cast<ExtDamageAcceleratorAABBTree*>(this)->findInBounds(bounds, resultCallback, true);
-
- }
-
- virtual void findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const override;
-
- virtual Nv::Blast::DebugBuffer fillDebugRender(int depth, bool segments) override;
-
- virtual void* getImmediateScratch(size_t size) override
- {
- m_scratch.resizeUninitialized(size);
- return m_scratch.begin();
- }
-
-
-private:
- // no copy/assignment
- ExtDamageAcceleratorAABBTree(ExtDamageAcceleratorAABBTree&);
- ExtDamageAcceleratorAABBTree& operator=(const ExtDamageAcceleratorAABBTree& tree);
-
- // Tree node
- struct Node
- {
- int child[2];
- uint32_t first;
- uint32_t last;
- physx::PxBounds3 pointsBound;
- physx::PxBounds3 segmentsBound;
- };
-
-
- void build(const NvBlastAsset* asset);
-
- int createNode(uint32_t startIdx, uint32_t endIdx, uint32_t depth);
-
- void pushResult(ResultCallback& callback, uint32_t pointIndex) const
- {
- callback.push(pointIndex, m_bonds[pointIndex].node0, m_bonds[pointIndex].node1);
- }
-
- void findInBounds(const physx::PxBounds3& bounds, ResultCallback& callback, bool segments) const;
-
- void findPointsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const;
-
- void findSegmentsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const;
-
- void findSegmentsPlaneIntersected(const Node& node, ResultCallback& callback, const physx::PxPlane& plane) const;
-
- void fillDebugBuffer(const Node& node, int currentDepth, int depth, bool segments);
-
-
- //////// data ////////
-
- Node* m_root;
- Array<Node>::type m_nodes;
- Array<uint32_t>::type m_indices;
-
- Array<physx::PxVec3>::type m_points;
-
- struct Segment
- {
- physx::PxVec3 p0;
- physx::PxVec3 p1;
- };
- Array<Segment>::type m_segments;
-
- struct BondData
- {
- uint32_t node0;
- uint32_t node1;
- };
- Array<BondData>::type m_bonds;
-
- Array<Nv::Blast::DebugLine>::type m_debugLineBuffer;
-
- Array<char>::type m_scratch;
-};
-
-
-} // 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.
+
+#pragma once
+
+#include "NvBlastExtDamageAcceleratorInternal.h"
+#include "NvBlast.h"
+#include "NvBlastArray.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+class ExtDamageAcceleratorAABBTree final : public ExtDamageAcceleratorInternal
+{
+public:
+ //////// ctor ////////
+
+ ExtDamageAcceleratorAABBTree() :
+ m_root(nullptr)
+ {
+ }
+
+ virtual ~ExtDamageAcceleratorAABBTree()
+ {
+ }
+
+ static ExtDamageAcceleratorAABBTree* create(const NvBlastAsset* asset);
+
+
+ //////// interface ////////
+
+ virtual void release() override;
+
+ virtual void findBondCentroidsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const override
+ {
+ const_cast<ExtDamageAcceleratorAABBTree*>(this)->findInBounds(bounds, resultCallback, false);
+ }
+
+ virtual void findBondSegmentsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const override
+ {
+ const_cast<ExtDamageAcceleratorAABBTree*>(this)->findInBounds(bounds, resultCallback, true);
+
+ }
+
+ virtual void findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const override;
+
+ virtual Nv::Blast::DebugBuffer fillDebugRender(int depth, bool segments) override;
+
+ virtual void* getImmediateScratch(size_t size) override
+ {
+ m_scratch.resizeUninitialized(size);
+ return m_scratch.begin();
+ }
+
+
+private:
+ // no copy/assignment
+ ExtDamageAcceleratorAABBTree(ExtDamageAcceleratorAABBTree&);
+ ExtDamageAcceleratorAABBTree& operator=(const ExtDamageAcceleratorAABBTree& tree);
+
+ // Tree node
+ struct Node
+ {
+ int child[2];
+ uint32_t first;
+ uint32_t last;
+ physx::PxBounds3 pointsBound;
+ physx::PxBounds3 segmentsBound;
+ };
+
+
+ void build(const NvBlastAsset* asset);
+
+ int createNode(uint32_t startIdx, uint32_t endIdx, uint32_t depth);
+
+ void pushResult(ResultCallback& callback, uint32_t pointIndex) const
+ {
+ callback.push(pointIndex, m_bonds[pointIndex].node0, m_bonds[pointIndex].node1);
+ }
+
+ void findInBounds(const physx::PxBounds3& bounds, ResultCallback& callback, bool segments) const;
+
+ void findPointsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const;
+
+ void findSegmentsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const;
+
+ void findSegmentsPlaneIntersected(const Node& node, ResultCallback& callback, const physx::PxPlane& plane) const;
+
+ void fillDebugBuffer(const Node& node, int currentDepth, int depth, bool segments);
+
+
+ //////// data ////////
+
+ Node* m_root;
+ Array<Node>::type m_nodes;
+ Array<uint32_t>::type m_indices;
+
+ Array<physx::PxVec3>::type m_points;
+
+ struct Segment
+ {
+ physx::PxVec3 p0;
+ physx::PxVec3 p1;
+ };
+ Array<Segment>::type m_segments;
+
+ struct BondData
+ {
+ uint32_t node0;
+ uint32_t node1;
+ };
+ Array<BondData>::type m_bonds;
+
+ Array<Nv::Blast::DebugLine>::type m_debugLineBuffer;
+
+ Array<char>::type m_scratch;
+};
+
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h
index 3879fbc..edd07f5 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h
@@ -1,96 +1,96 @@
-// 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.
-
-#pragma once
-
-#include "NvBlastExtDamageShaders.h"
-#include "PxBounds3.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-
-class ExtDamageAcceleratorInternal : public NvBlastExtDamageAccelerator
-{
-public:
- struct QueryBondData
- {
- uint32_t bond;
- uint32_t node0;
- uint32_t node1;
- };
-
- class ResultCallback
- {
- public:
- ResultCallback(QueryBondData* buffer, uint32_t count) :
- m_bondBuffer(buffer), m_bondMaxCount(count), m_bondCount(0) {}
-
- virtual void processResults(const QueryBondData* bondBuffer, uint32_t count) = 0;
-
- void push(uint32_t bond, uint32_t node0, uint32_t node1)
- {
- m_bondBuffer[m_bondCount].bond = bond;
- m_bondBuffer[m_bondCount].node0 = node0;
- m_bondBuffer[m_bondCount].node1 = node1;
- m_bondCount++;
- if (m_bondCount == m_bondMaxCount)
- {
- dispatch();
- }
- }
-
- void dispatch()
- {
- if (m_bondCount)
- {
- processResults(m_bondBuffer, m_bondCount);
- m_bondCount = 0;
- }
- }
-
- private:
- QueryBondData* m_bondBuffer;
- uint32_t m_bondMaxCount;
-
- uint32_t m_bondCount;
- };
-
- virtual void findBondCentroidsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const = 0;
- virtual void findBondSegmentsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const = 0;
- virtual void findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const = 0;
-
- // Non-thread safe! Multiple calls return the same memory.
- virtual void* getImmediateScratch(size_t size) = 0;
-};
-
-
-} // 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.
+
+#pragma once
+
+#include "NvBlastExtDamageShaders.h"
+#include "PxBounds3.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+
+class ExtDamageAcceleratorInternal : public NvBlastExtDamageAccelerator
+{
+public:
+ struct QueryBondData
+ {
+ uint32_t bond;
+ uint32_t node0;
+ uint32_t node1;
+ };
+
+ class ResultCallback
+ {
+ public:
+ ResultCallback(QueryBondData* buffer, uint32_t count) :
+ m_bondBuffer(buffer), m_bondMaxCount(count), m_bondCount(0) {}
+
+ virtual void processResults(const QueryBondData* bondBuffer, uint32_t count) = 0;
+
+ void push(uint32_t bond, uint32_t node0, uint32_t node1)
+ {
+ m_bondBuffer[m_bondCount].bond = bond;
+ m_bondBuffer[m_bondCount].node0 = node0;
+ m_bondBuffer[m_bondCount].node1 = node1;
+ m_bondCount++;
+ if (m_bondCount == m_bondMaxCount)
+ {
+ dispatch();
+ }
+ }
+
+ void dispatch()
+ {
+ if (m_bondCount)
+ {
+ processResults(m_bondBuffer, m_bondCount);
+ m_bondCount = 0;
+ }
+ }
+
+ private:
+ QueryBondData* m_bondBuffer;
+ uint32_t m_bondMaxCount;
+
+ uint32_t m_bondCount;
+ };
+
+ virtual void findBondCentroidsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const = 0;
+ virtual void findBondSegmentsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const = 0;
+ virtual void findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const = 0;
+
+ // Non-thread safe! Multiple calls return the same memory.
+ virtual void* getImmediateScratch(size_t size) = 0;
+};
+
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp b/sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp
index 381f5e3..d2e563f 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp
@@ -1,43 +1,43 @@
-// 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 "NvBlastExtDamageAcceleratorOctree.h"
-//#include "NvBlastExtDamageAcceleratorKdtree.h"
-#include "NvBlastExtDamageAcceleratorAABBTree.h"
-
-NvBlastExtDamageAccelerator* NvBlastExtDamageAcceleratorCreate(const NvBlastAsset* asset, int type)
-{
- switch (type)
- {
- case 0:
- return nullptr;
- default:
- return Nv::Blast::ExtDamageAcceleratorAABBTree::create(asset);
- break;
- }
-}
+// 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 "NvBlastExtDamageAcceleratorOctree.h"
+//#include "NvBlastExtDamageAcceleratorKdtree.h"
+#include "NvBlastExtDamageAcceleratorAABBTree.h"
+
+NvBlastExtDamageAccelerator* NvBlastExtDamageAcceleratorCreate(const NvBlastAsset* asset, int type)
+{
+ switch (type)
+ {
+ case 0:
+ return nullptr;
+ default:
+ return Nv::Blast::ExtDamageAcceleratorAABBTree::create(asset);
+ break;
+ }
+}
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp b/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp
index cddf8e5..6d9edd2 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp
@@ -1,763 +1,763 @@
-// 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 "NvBlastExtDamageShaders.h"
-#include "NvBlastExtDamageAcceleratorInternal.h"
-#include "NvBlastIndexFns.h"
-#include "NvBlastMath.h"
-#include "NvBlastGeometry.h"
-#include "NvBlastAssert.h"
-#include "NvBlastFixedQueue.h"
-#include "NvBlastFixedBitmap.h"
-#include "NvBlast.h"
-#include <cmath> // for abs() on linux
-#include <new>
-
-
-using namespace Nv::Blast;
-using namespace Nv::Blast::VecMath;
-using namespace physx;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Profiles
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-typedef float(*ProfileFunction)(float, float, float, float);
-
-float falloffProfile(float min, float max, float x, float f = 1.0f)
-{
- if (x > max) return 0.0f;
- if (x < min) return f;
-
- float y = 1.0f - (x - min) / (max - min);
- return y * f;
-}
-
-float cutterProfile(float min, float max, float x, float f = 1.0f)
-{
- if (x > max || x < min) return 0.0f;
-
- return f;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Damage Functions
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-typedef float(*DamageFunction)(const float pos[3], const void* damageDescBuffer);
-
-template <ProfileFunction profileFn, typename DescT = NvBlastExtRadialDamageDesc>
-float pointDistanceDamage(const float pos[3], const void* damageDescBuffer)
-{
- const DescT& desc = *static_cast<const DescT*>(damageDescBuffer);
-
- float relativePosition[3];
- sub(desc.position, pos, relativePosition);
- const float distance = sqrtf(dot(relativePosition, relativePosition));
- const float damage = profileFn(desc.minRadius, desc.maxRadius, distance, desc.damage);
- return damage;
-}
-
-
-// Distance from point 'p' to line segment '(a, b)'
-float distanceToSegment(const float p[3], const float a[3], const float b[3])
-{
- float v[3];
- sub(b, a, v);
-
- float w[3];
- sub(p, a, w);
-
- const float c1 = dot(v, w);
- if (c1 <= 0)
- return length(w);
-
- const float c2 = dot(v, v);
- if (c2 < c1)
- return dist(p, b);
-
- const float t = c1 / c2;
- mul(v, t);
- return dist(v, w);
-}
-
-template <ProfileFunction profileFn>
-float capsuleDistanceDamage(const float pos[3], const void* damageDesc)
-{
- const NvBlastExtCapsuleRadialDamageDesc& desc = *static_cast<const NvBlastExtCapsuleRadialDamageDesc*>(damageDesc);
-
- const float distance = distanceToSegment(pos, desc.position0, desc.position1);
- const float damage = profileFn(desc.minRadius, desc.maxRadius, distance, desc.damage);
- return damage;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// AABB Functions
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-typedef PxBounds3(*BoundFunction)(const void* damageDesc);
-
-PxBounds3 sphereBounds(const void* damageDesc)
-{
- const NvBlastExtRadialDamageDesc& desc = *static_cast<const NvBlastExtRadialDamageDesc*>(damageDesc);
- const physx::PxVec3& p = (reinterpret_cast<const physx::PxVec3&>(desc.position));
- return physx::PxBounds3::centerExtents(p, physx::PxVec3(desc.maxRadius, desc.maxRadius, desc.maxRadius));
-}
-
-PxBounds3 capsuleBounds(const void* damageDesc)
-{
- const NvBlastExtCapsuleRadialDamageDesc& desc = *static_cast<const NvBlastExtCapsuleRadialDamageDesc*>(damageDesc);
- const physx::PxVec3& p0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
- const physx::PxVec3& p1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
- PxBounds3 b = PxBounds3::empty();
- b.include(p0);
- b.include(p1);
- b.fattenFast(desc.maxRadius);
- return b;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Radial Graph Shader Template
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-template <DamageFunction damageFn, BoundFunction boundsFn>
-void RadialProfileGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks;
- const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex;
- const uint32_t* adjacencyPartition = actor->adjacencyPartition;
- const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices;
- const uint32_t* adjacentBondIndices = actor->adjacentBondIndices;
- const NvBlastBond* assetBonds = actor->assetBonds;
- const float* familyBondHealths = actor->familyBondHealths;
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
-
- uint32_t outCount = 0;
-
- auto processBondFn = [&](uint32_t bondIndex, uint32_t node0, uint32_t node1)
- {
- // skip bonds that are already broken or were visited already
- // TODO: investigate why testing against health > -1.0f seems slower
- // could reuse the island edge bitmap instead
- if ((familyBondHealths[bondIndex] > 0.0f))
- {
- const NvBlastBond& bond = assetBonds[bondIndex];
-
- const float totalBondDamage = damageFn(bond.centroid, programParams->damageDesc);
- if (totalBondDamage > 0.0f)
- {
- NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++];
- outCommand.nodeIndex0 = node0;
- outCommand.nodeIndex1 = node1;
- outCommand.health = totalBondDamage;
- }
- }
- };
-
- const ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<const ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
- const uint32_t ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE = actor->assetNodeCount / 3;
- if (damageAccelerator && actor->graphNodeCount > ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE)
- {
- physx::PxBounds3 bounds = boundsFn(programParams->damageDesc);
-
- const uint32_t CALLBACK_BUFFER_SIZE = 1000;
-
- class AcceleratorCallback : public ExtDamageAcceleratorInternal::ResultCallback
- {
- public:
- AcceleratorCallback(NvBlastFractureBuffers* commandBuffers, uint32_t& outCount, const NvBlastGraphShaderActor* actor, const NvBlastExtProgramParams* programParams) :
- ExtDamageAcceleratorInternal::ResultCallback(m_buffer, CALLBACK_BUFFER_SIZE),
- m_actor(actor),
- m_commandBuffers(commandBuffers),
- m_outCount(outCount),
- m_programParams(programParams)
- {
- }
-
- virtual void processResults(const ExtDamageAcceleratorInternal::QueryBondData* bondBuffer, uint32_t count) override
- {
- for (uint32_t i = 0; i < count; i++)
- {
- const ExtDamageAcceleratorInternal::QueryBondData& bondData = bondBuffer[i];
- if (m_actor->nodeActorIndices[bondData.node0] == m_actor->actorIndex)
- {
- if ((m_actor->familyBondHealths[bondData.bond] > 0.0f))
- {
- const NvBlastBond& bond = m_actor->assetBonds[bondData.bond];
-
- const float totalBondDamage = damageFn(bond.centroid, m_programParams->damageDesc);
- if (totalBondDamage > 0.0f)
- {
- NvBlastBondFractureData& outCommand = m_commandBuffers->bondFractures[m_outCount++];
- outCommand.nodeIndex0 = bondData.node0;
- outCommand.nodeIndex1 = bondData.node1;
- outCommand.health = totalBondDamage;
- }
- }
- }
- }
- }
-
- private:
- const NvBlastGraphShaderActor* m_actor;
- NvBlastFractureBuffers* m_commandBuffers;
- uint32_t& m_outCount;
- const NvBlastExtProgramParams* m_programParams;
-
- ExtDamageAcceleratorInternal::QueryBondData m_buffer[CALLBACK_BUFFER_SIZE];
- };
-
- AcceleratorCallback cb(commandBuffers, outCount, actor, programParams);
-
- damageAccelerator->findBondCentroidsInBounds(bounds, cb);
- }
- else
- {
- uint32_t currentNodeIndex = firstGraphNodeIndex;
- while (!Nv::Blast::isInvalidIndex(currentNodeIndex))
- {
- for (uint32_t adj = adjacencyPartition[currentNodeIndex]; adj < adjacencyPartition[currentNodeIndex + 1]; adj++)
- {
- uint32_t adjacentNodeIndex = adjacentNodeIndices[adj];
- if (currentNodeIndex < adjacentNodeIndex)
- {
- uint32_t bondIndex = adjacentBondIndices[adj];
- processBondFn(bondIndex, currentNodeIndex, adjacentNodeIndex);
- }
- }
- currentNodeIndex = graphNodeIndexLinks[currentNodeIndex];
- }
- }
-
- commandBuffers->bondFractureCount = outCount;
- commandBuffers->chunkFractureCount = 0;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Radial Single Shader Template
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-template <DamageFunction damageFn>
-void RadialProfileSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- uint32_t chunkFractureCount = 0;
- uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
- const uint32_t chunkIndex = actor->chunkIndex;
- const NvBlastChunk* assetChunks = actor->assetChunks;
- const NvBlastChunk& chunk = assetChunks[chunkIndex];
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
-
- const float totalDamage = damageFn(chunk.centroid, programParams->damageDesc);
- if (totalDamage > 0.0f && chunkFractureCount < chunkFractureCountMax)
- {
- NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
- frac.chunkIndex = chunkIndex;
- frac.health = totalDamage;
- }
-
- commandBuffers->bondFractureCount = 0;
- commandBuffers->chunkFractureCount = chunkFractureCount;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Radial Shaders Instantiation
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void NvBlastExtFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- RadialProfileGraphShader<pointDistanceDamage<falloffProfile>, sphereBounds>(commandBuffers, actor, params);
-}
-
-void NvBlastExtFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile>>(commandBuffers, actor, params);
-}
-
-void NvBlastExtCutterGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- RadialProfileGraphShader<pointDistanceDamage<cutterProfile>, sphereBounds>(commandBuffers, actor, params);
-}
-
-void NvBlastExtCutterSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- RadialProfileSubgraphShader<pointDistanceDamage<cutterProfile>>(commandBuffers, actor, params);
-}
-
-void NvBlastExtCapsuleFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- RadialProfileGraphShader<capsuleDistanceDamage<falloffProfile>, capsuleBounds>(commandBuffers, actor, params);
-}
-
-void NvBlastExtCapsuleFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- RadialProfileSubgraphShader<capsuleDistanceDamage<falloffProfile>>(commandBuffers, actor, params);
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Shear Shader
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void NvBlastExtShearGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- uint32_t chunkFractureCount = 0;
- uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
- uint32_t bondFractureCount = 0;
- uint32_t bondFractureCountMax = commandBuffers->bondFractureCount;
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtShearDamageDesc& desc = *static_cast<const NvBlastExtShearDamageDesc*>(programParams->damageDesc);
- const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks;
- const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex;
- const uint32_t* chunkIndices = actor->chunkIndices;
- const uint32_t* adjacencyPartition = actor->adjacencyPartition;
- const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices;
- const uint32_t* adjacentBondIndices = actor->adjacentBondIndices;
- const NvBlastBond* assetBonds = actor->assetBonds;
- const NvBlastChunk* assetChunks = actor->assetChunks;
- const float* familyBondHealths = actor->familyBondHealths;
- const float* supportChunkHealths = actor->supportChunkHealths;
-
- uint32_t closestNode = findClosestNode(desc.position
- , firstGraphNodeIndex, graphNodeIndexLinks
- , adjacencyPartition, adjacentNodeIndices, adjacentBondIndices
- , assetBonds, familyBondHealths
- , assetChunks, supportChunkHealths, chunkIndices);
-
- uint32_t nodeIndex = closestNode;
- float maxDist = 0.0f;
- uint32_t nextNode = invalidIndex<uint32_t>();
-
- if (chunkFractureCount < chunkFractureCountMax)
- {
- const uint32_t chunkIndex = chunkIndices[nodeIndex];
- const NvBlastChunk& chunk = assetChunks[chunkIndex];
- NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
- frac.chunkIndex = chunkIndex;
- frac.health = pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>(chunk.centroid, programParams->damageDesc);
- }
-
- do {
- const uint32_t startIndex = adjacencyPartition[nodeIndex];
- const uint32_t stopIndex = adjacencyPartition[nodeIndex + 1];
-
-
- for (uint32_t adjacentNodeIndex = startIndex; adjacentNodeIndex < stopIndex; adjacentNodeIndex++)
- {
- const uint32_t neighbourIndex = adjacentNodeIndices[adjacentNodeIndex];
- const uint32_t bondIndex = adjacentBondIndices[adjacentNodeIndex];
- const NvBlastBond& bond = assetBonds[bondIndex];
-
- if (!(familyBondHealths[bondIndex] > 0.0f))
- continue;
-
- float shear = 1 * std::abs(1 - std::abs(VecMath::dot(desc.normal, bond.normal)));
-
- float d[3]; VecMath::sub(bond.centroid, desc.position, d);
- float ahead = VecMath::dot(d, desc.normal);
- if (ahead > maxDist)
- {
- maxDist = ahead;
- nextNode = neighbourIndex;
- }
-
- const float damage = pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>(bond.centroid, programParams->damageDesc);
- if (damage > 0.0f && bondFractureCount < bondFractureCountMax)
- {
- NvBlastBondFractureData& frac = commandBuffers->bondFractures[bondFractureCount++];
- frac.userdata = bond.userData;
- frac.nodeIndex0 = nodeIndex;
- frac.nodeIndex1 = neighbourIndex;
- frac.health = shear * damage;
- }
- }
-
- if (nodeIndex == nextNode)
- break;
-
- nodeIndex = nextNode;
- } while (!isInvalidIndex(nextNode));
-
- commandBuffers->bondFractureCount = bondFractureCount;
- commandBuffers->chunkFractureCount = chunkFractureCount;
-}
-
-void NvBlastExtShearSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>>(commandBuffers, actor, params);
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Triangle Intersection Damage
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#define SMALL_NUMBER (1.e-4f)
-
-bool intersectSegmentTriangle(const PxVec3& p, const PxVec3& q, const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxPlane& trianglePlane)
-{
- const PxVec3 N = trianglePlane.n;
- const float D = trianglePlane.d;
-
- PxVec3 intersectPoint;
- float t = (-D - (p.dot(N))) / ((q - p).dot(N));
- // If the parameter value is not between 0 and 1, there is no intersection
- if (t > -SMALL_NUMBER && t < 1.f + SMALL_NUMBER)
- {
- intersectPoint = p + t * (q - p);
- }
- else
- {
- return false;
- }
-
- // Compute the normal of the triangle
- const PxVec3 TriNorm = (b - a).cross(c - a);
-
- // Compute twice area of triangle ABC
- const float AreaABCInv = 1.0f / (N.dot(TriNorm));
-
- // Compute v contribution
- const float AreaPBC = N.dot((b - intersectPoint).cross(c - intersectPoint));
- const float v = AreaPBC * AreaABCInv;
- if (v <= 0.f)
- return false;
-
- // Compute w contribution
- const float AreaPCA = N.dot((c - intersectPoint).cross(a - intersectPoint));
- const float w = AreaPCA * AreaABCInv;
- if (w <= 0.f)
- return false;
-
- const float u = 1.0f - v - w;
- return u > 0.f;
-}
-
-void NvBlastExtTriangleIntersectionGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks;
- const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex;
- const uint32_t* adjacencyPartition = actor->adjacencyPartition;
- const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices;
- const uint32_t* adjacentBondIndices = actor->adjacentBondIndices;
- const NvBlastBond* assetBonds = actor->assetBonds;
- const NvBlastChunk* assetChunks = actor->assetChunks;
- const uint32_t* chunkIndices = actor->chunkIndices;
- const float* familyBondHealths = actor->familyBondHealths;
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtTriangleIntersectionDamageDesc& desc = *static_cast<const NvBlastExtTriangleIntersectionDamageDesc*>(programParams->damageDesc);
- const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
- const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
- const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(desc.position2));
- const PxPlane trianglePlane(t0, t1, t2);
-
- uint32_t outCount = 0;
-
- const ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<const ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
- const uint32_t ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE = actor->assetNodeCount / 3;
- if (damageAccelerator && actor->graphNodeCount > ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE)
- {
- const uint32_t CALLBACK_BUFFER_SIZE = 1000;
-
- class AcceleratorCallback : public ExtDamageAcceleratorInternal::ResultCallback
- {
- public:
- AcceleratorCallback(NvBlastFractureBuffers* commandBuffers, uint32_t& outCount, const NvBlastGraphShaderActor* actor, const NvBlastExtTriangleIntersectionDamageDesc& desc) :
- ExtDamageAcceleratorInternal::ResultCallback(m_buffer, CALLBACK_BUFFER_SIZE),
- m_actor(actor),
- m_commandBuffers(commandBuffers),
- m_outCount(outCount),
- m_desc(desc)
- {
- }
-
- virtual void processResults(const ExtDamageAcceleratorInternal::QueryBondData* bondBuffer, uint32_t count) override
- {
- const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position0));
- const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position1));
- const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position2));
- const PxPlane trianglePlane(t0, t1, t2);
-
- for (uint32_t i = 0; i < count; i++)
- {
- const ExtDamageAcceleratorInternal::QueryBondData& bondData = bondBuffer[i];
- if (m_actor->nodeActorIndices[bondData.node0] == m_actor->actorIndex)
- {
- if ((m_actor->familyBondHealths[bondData.bond] > 0.0f))
- {
- const NvBlastBond& bond = m_actor->assetBonds[bondData.bond];
- const uint32_t chunkIndex0 = m_actor->chunkIndices[bondData.node0];
- const uint32_t chunkIndex1 = m_actor->chunkIndices[bondData.node1];
- const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(m_actor->assetChunks[chunkIndex0].centroid));
- const PxVec3& normal = (reinterpret_cast<const PxVec3&>(bond.normal));
- const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
- const physx::PxVec3& c1 = isInvalidIndex(chunkIndex1) ? (c0 + normal * (bondCentroid - c0).dot(normal)) :
- (reinterpret_cast<const physx::PxVec3&>(m_actor->assetChunks[chunkIndex1].centroid));
-
- if(intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
- {
- NvBlastBondFractureData& outCommand = m_commandBuffers->bondFractures[m_outCount++];
- outCommand.nodeIndex0 = bondData.node0;
- outCommand.nodeIndex1 = bondData.node1;
- outCommand.health = m_desc.damage;
- }
- }
- }
- }
- }
-
- private:
- const NvBlastGraphShaderActor* m_actor;
- NvBlastFractureBuffers* m_commandBuffers;
- uint32_t& m_outCount;
- const NvBlastExtTriangleIntersectionDamageDesc& m_desc;
-
- ExtDamageAcceleratorInternal::QueryBondData m_buffer[CALLBACK_BUFFER_SIZE];
- };
-
- AcceleratorCallback cb(commandBuffers, outCount, actor, desc);
-
- damageAccelerator->findBondSegmentsPlaneIntersected(trianglePlane, cb);
- }
- else
- {
- uint32_t currentNodeIndex = firstGraphNodeIndex;
- while (!Nv::Blast::isInvalidIndex(currentNodeIndex))
- {
- for (uint32_t adj = adjacencyPartition[currentNodeIndex]; adj < adjacencyPartition[currentNodeIndex + 1]; adj++)
- {
- uint32_t adjacentNodeIndex = adjacentNodeIndices[adj];
- if (currentNodeIndex < adjacentNodeIndex)
- {
- uint32_t bondIndex = adjacentBondIndices[adj];
- // skip bonds that are already broken or were visited already
- // TODO: investigate why testing against health > -1.0f seems slower
- // could reuse the island edge bitmap instead
- if ((familyBondHealths[bondIndex] > 0.0f))
- {
- const NvBlastBond& bond = assetBonds[bondIndex];
- const uint32_t chunkIndex0 = chunkIndices[currentNodeIndex];
- const uint32_t chunkIndex1 = chunkIndices[adjacentNodeIndex];
- const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex0].centroid));
- const PxVec3& normal = (reinterpret_cast<const PxVec3&>(bond.normal));
- const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
- const physx::PxVec3& c1 = isInvalidIndex(chunkIndex1) ? (c0 + normal * (bondCentroid - c0).dot(normal)) :
- (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex1].centroid));
-
- if (intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
- {
- NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++];
- outCommand.nodeIndex0 = currentNodeIndex;
- outCommand.nodeIndex1 = adjacentNodeIndex;
- outCommand.health = desc.damage;
- }
- }
- }
- }
- currentNodeIndex = graphNodeIndexLinks[currentNodeIndex];
- }
- }
-
- commandBuffers->bondFractureCount = outCount;
- commandBuffers->chunkFractureCount = 0;
-}
-
-void NvBlastExtTriangleIntersectionSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- uint32_t chunkFractureCount = 0;
- uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
- const uint32_t chunkIndex = actor->chunkIndex;
- const NvBlastChunk* assetChunks = actor->assetChunks;
- const NvBlastChunk& chunk = assetChunks[chunkIndex];
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtTriangleIntersectionDamageDesc& desc = *static_cast<const NvBlastExtTriangleIntersectionDamageDesc*>(programParams->damageDesc);
- const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
- const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
- const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(desc.position2));
- const PxPlane trianglePlane(t0, t1, t2);
-
- for (uint32_t subChunkIndex = chunk.firstChildIndex; subChunkIndex < chunk.childIndexStop; subChunkIndex++)
- {
- const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[subChunkIndex].centroid));
- const physx::PxVec3& c1 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[subChunkIndex + 1].centroid));
- if (chunkFractureCount < chunkFractureCountMax && intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
- {
- NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
- frac.chunkIndex = chunkIndex;
- frac.health = desc.damage;
- break;
- }
- }
-
- commandBuffers->bondFractureCount = 0;
- commandBuffers->chunkFractureCount = chunkFractureCount;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Impact Spread Shader
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void NvBlastExtImpactSpreadGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- uint32_t chunkFractureCount = 0;
- uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
- uint32_t bondFractureCount = 0;
- uint32_t bondFractureCountMax = commandBuffers->bondFractureCount;
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtImpactSpreadDamageDesc& desc = *static_cast<const NvBlastExtImpactSpreadDamageDesc*>(programParams->damageDesc);
- const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks;
- const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex;
- const uint32_t* chunkIndices = actor->chunkIndices;
- const uint32_t* adjacencyPartition = actor->adjacencyPartition;
- const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices;
- const uint32_t* adjacentBondIndices = actor->adjacentBondIndices;
- const NvBlastBond* assetBonds = actor->assetBonds;
- const NvBlastChunk* assetChunks = actor->assetChunks;
- const float* familyBondHealths = actor->familyBondHealths;
- const float* supportChunkHealths = actor->supportChunkHealths;
-
- // Find nearest chunk.
- uint32_t closestNode = findClosestNode(desc.position
- , firstGraphNodeIndex, graphNodeIndexLinks
- , adjacencyPartition, adjacentNodeIndices, adjacentBondIndices
- , assetBonds, familyBondHealths
- , assetChunks, supportChunkHealths, chunkIndices);
-
- uint32_t nodeIndex = closestNode;
-
- // Damage this chunk
- if (chunkFractureCount < chunkFractureCountMax)
- {
- const uint32_t chunkIndex = chunkIndices[nodeIndex];
- NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
- frac.chunkIndex = chunkIndex;
- frac.health = desc.damage;
- }
-
- // Breadth-first support graph traversal. For radial falloff metric distance is measured along the edges of the graph
- ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
- NVBLAST_ASSERT_WITH_MESSAGE(damageAccelerator, "This shader requires damage accelerator passed");
- if (damageAccelerator)
- {
- struct NodeData
- {
- uint32_t index;
- float distance;
- };
-
- // Calculating scratch size and requesting it from the accelerator
- const uint32_t bondCount = actor->adjacencyPartition[actor->assetNodeCount];
- const size_t nodeQueueSize = align16(FixedQueue<NodeData>::requiredMemorySize(actor->graphNodeCount));
- const size_t visitedBitmapSize = align16(FixedBitmap::requiredMemorySize(bondCount));
- const size_t scratchSize = 16 + nodeQueueSize + visitedBitmapSize;
-
- void* scratch = damageAccelerator->getImmediateScratch(scratchSize);
-
- // prepare intermediate data on scratch
- scratch = (void*)align16((size_t)scratch); // Bump to 16-byte alignment
- FixedQueue<NodeData>* nodeQueue = new (scratch)FixedQueue<NodeData>(actor->graphNodeCount);
- scratch = pointerOffset(scratch, align16(nodeQueueSize));
- FixedBitmap* visitedBitmap = new (scratch)FixedBitmap(bondCount);
- scratch = pointerOffset(scratch, align16(FixedBitmap::requiredMemorySize(bondCount)));
-
- // initalize traversal
- nodeQueue->pushBack({ nodeIndex, 0.f });
- visitedBitmap->clear();
-
- while (!nodeQueue->empty())
- {
- NodeData currentNode = nodeQueue->popFront();
- const uint32_t startIndex = adjacencyPartition[currentNode.index];
- const uint32_t stopIndex = adjacencyPartition[currentNode.index + 1];
-
- for (uint32_t adjacentNodeIndex = startIndex; adjacentNodeIndex < stopIndex; adjacentNodeIndex++)
- {
- const uint32_t neighbourIndex = adjacentNodeIndices[adjacentNodeIndex];
- const uint32_t bondIndex = adjacentBondIndices[adjacentNodeIndex];
- const NvBlastBond& bond = assetBonds[bondIndex];
-
- const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
-
- if (!(familyBondHealths[bondIndex] > 0.0f))
- continue;
-
- if (visitedBitmap->test(bondIndex))
- continue;
- visitedBitmap->set(bondIndex);
-
- const uint32_t chunkIndex0 = chunkIndices[currentNode.index];
- const uint32_t chunkIndex1 = chunkIndices[neighbourIndex];
- const physx::PxVec3& c0 = reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex0].centroid);
- bool isNeighbourWorldChunk = isInvalidIndex(chunkIndex1);
- const physx::PxVec3& c1 = isNeighbourWorldChunk ? bondCentroid : (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex1].centroid));
-
- const float distance = (c1 - c0).magnitude() * (isNeighbourWorldChunk ? 2.f : 1.f);
- float totalDistance = currentNode.distance + distance;
- float totalDamage = falloffProfile(desc.minRadius, desc.maxRadius, totalDistance);
- if (totalDamage > 0.0f && bondFractureCount < bondFractureCountMax)
- {
- NvBlastBondFractureData& frac = commandBuffers->bondFractures[bondFractureCount++];
- frac.userdata = bond.userData;
- frac.nodeIndex0 = currentNode.index;
- frac.nodeIndex1 = neighbourIndex;
- frac.health = totalDamage;
- if (!isNeighbourWorldChunk)
- {
- nodeQueue->pushBack({ neighbourIndex, totalDistance });
- }
- }
- }
- }
- }
-
- commandBuffers->bondFractureCount = bondFractureCount;
- commandBuffers->chunkFractureCount = chunkFractureCount;
-}
-
-void NvBlastExtImpactSpreadSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- uint32_t chunkFractureCount = 0;
- uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
- const uint32_t chunkIndex = actor->chunkIndex;
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtImpactSpreadDamageDesc& desc = *static_cast<const NvBlastExtImpactSpreadDamageDesc*>(programParams->damageDesc);
-
- if (chunkFractureCount < chunkFractureCountMax)
- {
- NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
- frac.chunkIndex = chunkIndex;
- frac.health = desc.damage;
- }
-
- commandBuffers->bondFractureCount = 0;
- commandBuffers->chunkFractureCount = chunkFractureCount;
-}
+// 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 "NvBlastExtDamageShaders.h"
+#include "NvBlastExtDamageAcceleratorInternal.h"
+#include "NvBlastIndexFns.h"
+#include "NvBlastMath.h"
+#include "NvBlastGeometry.h"
+#include "NvBlastAssert.h"
+#include "NvBlastFixedQueue.h"
+#include "NvBlastFixedBitmap.h"
+#include "NvBlast.h"
+#include <cmath> // for abs() on linux
+#include <new>
+
+
+using namespace Nv::Blast;
+using namespace Nv::Blast::VecMath;
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Profiles
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef float(*ProfileFunction)(float, float, float, float);
+
+float falloffProfile(float min, float max, float x, float f = 1.0f)
+{
+ if (x > max) return 0.0f;
+ if (x < min) return f;
+
+ float y = 1.0f - (x - min) / (max - min);
+ return y * f;
+}
+
+float cutterProfile(float min, float max, float x, float f = 1.0f)
+{
+ if (x > max || x < min) return 0.0f;
+
+ return f;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Damage Functions
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef float(*DamageFunction)(const float pos[3], const void* damageDescBuffer);
+
+template <ProfileFunction profileFn, typename DescT = NvBlastExtRadialDamageDesc>
+float pointDistanceDamage(const float pos[3], const void* damageDescBuffer)
+{
+ const DescT& desc = *static_cast<const DescT*>(damageDescBuffer);
+
+ float relativePosition[3];
+ sub(desc.position, pos, relativePosition);
+ const float distance = sqrtf(dot(relativePosition, relativePosition));
+ const float damage = profileFn(desc.minRadius, desc.maxRadius, distance, desc.damage);
+ return damage;
+}
+
+
+// Distance from point 'p' to line segment '(a, b)'
+float distanceToSegment(const float p[3], const float a[3], const float b[3])
+{
+ float v[3];
+ sub(b, a, v);
+
+ float w[3];
+ sub(p, a, w);
+
+ const float c1 = dot(v, w);
+ if (c1 <= 0)
+ return length(w);
+
+ const float c2 = dot(v, v);
+ if (c2 < c1)
+ return dist(p, b);
+
+ const float t = c1 / c2;
+ mul(v, t);
+ return dist(v, w);
+}
+
+template <ProfileFunction profileFn>
+float capsuleDistanceDamage(const float pos[3], const void* damageDesc)
+{
+ const NvBlastExtCapsuleRadialDamageDesc& desc = *static_cast<const NvBlastExtCapsuleRadialDamageDesc*>(damageDesc);
+
+ const float distance = distanceToSegment(pos, desc.position0, desc.position1);
+ const float damage = profileFn(desc.minRadius, desc.maxRadius, distance, desc.damage);
+ return damage;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// AABB Functions
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef PxBounds3(*BoundFunction)(const void* damageDesc);
+
+PxBounds3 sphereBounds(const void* damageDesc)
+{
+ const NvBlastExtRadialDamageDesc& desc = *static_cast<const NvBlastExtRadialDamageDesc*>(damageDesc);
+ const physx::PxVec3& p = (reinterpret_cast<const physx::PxVec3&>(desc.position));
+ return physx::PxBounds3::centerExtents(p, physx::PxVec3(desc.maxRadius, desc.maxRadius, desc.maxRadius));
+}
+
+PxBounds3 capsuleBounds(const void* damageDesc)
+{
+ const NvBlastExtCapsuleRadialDamageDesc& desc = *static_cast<const NvBlastExtCapsuleRadialDamageDesc*>(damageDesc);
+ const physx::PxVec3& p0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
+ const physx::PxVec3& p1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
+ PxBounds3 b = PxBounds3::empty();
+ b.include(p0);
+ b.include(p1);
+ b.fattenFast(desc.maxRadius);
+ return b;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Radial Graph Shader Template
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <DamageFunction damageFn, BoundFunction boundsFn>
+void RadialProfileGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks;
+ const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex;
+ const uint32_t* adjacencyPartition = actor->adjacencyPartition;
+ const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices;
+ const uint32_t* adjacentBondIndices = actor->adjacentBondIndices;
+ const NvBlastBond* assetBonds = actor->assetBonds;
+ const float* familyBondHealths = actor->familyBondHealths;
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+
+ uint32_t outCount = 0;
+
+ auto processBondFn = [&](uint32_t bondIndex, uint32_t node0, uint32_t node1)
+ {
+ // skip bonds that are already broken or were visited already
+ // TODO: investigate why testing against health > -1.0f seems slower
+ // could reuse the island edge bitmap instead
+ if ((familyBondHealths[bondIndex] > 0.0f))
+ {
+ const NvBlastBond& bond = assetBonds[bondIndex];
+
+ const float totalBondDamage = damageFn(bond.centroid, programParams->damageDesc);
+ if (totalBondDamage > 0.0f)
+ {
+ NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++];
+ outCommand.nodeIndex0 = node0;
+ outCommand.nodeIndex1 = node1;
+ outCommand.health = totalBondDamage;
+ }
+ }
+ };
+
+ const ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<const ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
+ const uint32_t ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE = actor->assetNodeCount / 3;
+ if (damageAccelerator && actor->graphNodeCount > ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE)
+ {
+ physx::PxBounds3 bounds = boundsFn(programParams->damageDesc);
+
+ const uint32_t CALLBACK_BUFFER_SIZE = 1000;
+
+ class AcceleratorCallback : public ExtDamageAcceleratorInternal::ResultCallback
+ {
+ public:
+ AcceleratorCallback(NvBlastFractureBuffers* commandBuffers, uint32_t& outCount, const NvBlastGraphShaderActor* actor, const NvBlastExtProgramParams* programParams) :
+ ExtDamageAcceleratorInternal::ResultCallback(m_buffer, CALLBACK_BUFFER_SIZE),
+ m_actor(actor),
+ m_commandBuffers(commandBuffers),
+ m_outCount(outCount),
+ m_programParams(programParams)
+ {
+ }
+
+ virtual void processResults(const ExtDamageAcceleratorInternal::QueryBondData* bondBuffer, uint32_t count) override
+ {
+ for (uint32_t i = 0; i < count; i++)
+ {
+ const ExtDamageAcceleratorInternal::QueryBondData& bondData = bondBuffer[i];
+ if (m_actor->nodeActorIndices[bondData.node0] == m_actor->actorIndex)
+ {
+ if ((m_actor->familyBondHealths[bondData.bond] > 0.0f))
+ {
+ const NvBlastBond& bond = m_actor->assetBonds[bondData.bond];
+
+ const float totalBondDamage = damageFn(bond.centroid, m_programParams->damageDesc);
+ if (totalBondDamage > 0.0f)
+ {
+ NvBlastBondFractureData& outCommand = m_commandBuffers->bondFractures[m_outCount++];
+ outCommand.nodeIndex0 = bondData.node0;
+ outCommand.nodeIndex1 = bondData.node1;
+ outCommand.health = totalBondDamage;
+ }
+ }
+ }
+ }
+ }
+
+ private:
+ const NvBlastGraphShaderActor* m_actor;
+ NvBlastFractureBuffers* m_commandBuffers;
+ uint32_t& m_outCount;
+ const NvBlastExtProgramParams* m_programParams;
+
+ ExtDamageAcceleratorInternal::QueryBondData m_buffer[CALLBACK_BUFFER_SIZE];
+ };
+
+ AcceleratorCallback cb(commandBuffers, outCount, actor, programParams);
+
+ damageAccelerator->findBondCentroidsInBounds(bounds, cb);
+ }
+ else
+ {
+ uint32_t currentNodeIndex = firstGraphNodeIndex;
+ while (!Nv::Blast::isInvalidIndex(currentNodeIndex))
+ {
+ for (uint32_t adj = adjacencyPartition[currentNodeIndex]; adj < adjacencyPartition[currentNodeIndex + 1]; adj++)
+ {
+ uint32_t adjacentNodeIndex = adjacentNodeIndices[adj];
+ if (currentNodeIndex < adjacentNodeIndex)
+ {
+ uint32_t bondIndex = adjacentBondIndices[adj];
+ processBondFn(bondIndex, currentNodeIndex, adjacentNodeIndex);
+ }
+ }
+ currentNodeIndex = graphNodeIndexLinks[currentNodeIndex];
+ }
+ }
+
+ commandBuffers->bondFractureCount = outCount;
+ commandBuffers->chunkFractureCount = 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Radial Single Shader Template
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <DamageFunction damageFn>
+void RadialProfileSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ uint32_t chunkFractureCount = 0;
+ uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
+ const uint32_t chunkIndex = actor->chunkIndex;
+ const NvBlastChunk* assetChunks = actor->assetChunks;
+ const NvBlastChunk& chunk = assetChunks[chunkIndex];
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+
+ const float totalDamage = damageFn(chunk.centroid, programParams->damageDesc);
+ if (totalDamage > 0.0f && chunkFractureCount < chunkFractureCountMax)
+ {
+ NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
+ frac.chunkIndex = chunkIndex;
+ frac.health = totalDamage;
+ }
+
+ commandBuffers->bondFractureCount = 0;
+ commandBuffers->chunkFractureCount = chunkFractureCount;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Radial Shaders Instantiation
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void NvBlastExtFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ RadialProfileGraphShader<pointDistanceDamage<falloffProfile>, sphereBounds>(commandBuffers, actor, params);
+}
+
+void NvBlastExtFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile>>(commandBuffers, actor, params);
+}
+
+void NvBlastExtCutterGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ RadialProfileGraphShader<pointDistanceDamage<cutterProfile>, sphereBounds>(commandBuffers, actor, params);
+}
+
+void NvBlastExtCutterSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ RadialProfileSubgraphShader<pointDistanceDamage<cutterProfile>>(commandBuffers, actor, params);
+}
+
+void NvBlastExtCapsuleFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ RadialProfileGraphShader<capsuleDistanceDamage<falloffProfile>, capsuleBounds>(commandBuffers, actor, params);
+}
+
+void NvBlastExtCapsuleFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ RadialProfileSubgraphShader<capsuleDistanceDamage<falloffProfile>>(commandBuffers, actor, params);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Shear Shader
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void NvBlastExtShearGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ uint32_t chunkFractureCount = 0;
+ uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
+ uint32_t bondFractureCount = 0;
+ uint32_t bondFractureCountMax = commandBuffers->bondFractureCount;
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtShearDamageDesc& desc = *static_cast<const NvBlastExtShearDamageDesc*>(programParams->damageDesc);
+ const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks;
+ const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex;
+ const uint32_t* chunkIndices = actor->chunkIndices;
+ const uint32_t* adjacencyPartition = actor->adjacencyPartition;
+ const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices;
+ const uint32_t* adjacentBondIndices = actor->adjacentBondIndices;
+ const NvBlastBond* assetBonds = actor->assetBonds;
+ const NvBlastChunk* assetChunks = actor->assetChunks;
+ const float* familyBondHealths = actor->familyBondHealths;
+ const float* supportChunkHealths = actor->supportChunkHealths;
+
+ uint32_t closestNode = findClosestNode(desc.position
+ , firstGraphNodeIndex, graphNodeIndexLinks
+ , adjacencyPartition, adjacentNodeIndices, adjacentBondIndices
+ , assetBonds, familyBondHealths
+ , assetChunks, supportChunkHealths, chunkIndices);
+
+ uint32_t nodeIndex = closestNode;
+ float maxDist = 0.0f;
+ uint32_t nextNode = invalidIndex<uint32_t>();
+
+ if (chunkFractureCount < chunkFractureCountMax)
+ {
+ const uint32_t chunkIndex = chunkIndices[nodeIndex];
+ const NvBlastChunk& chunk = assetChunks[chunkIndex];
+ NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
+ frac.chunkIndex = chunkIndex;
+ frac.health = pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>(chunk.centroid, programParams->damageDesc);
+ }
+
+ do {
+ const uint32_t startIndex = adjacencyPartition[nodeIndex];
+ const uint32_t stopIndex = adjacencyPartition[nodeIndex + 1];
+
+
+ for (uint32_t adjacentNodeIndex = startIndex; adjacentNodeIndex < stopIndex; adjacentNodeIndex++)
+ {
+ const uint32_t neighbourIndex = adjacentNodeIndices[adjacentNodeIndex];
+ const uint32_t bondIndex = adjacentBondIndices[adjacentNodeIndex];
+ const NvBlastBond& bond = assetBonds[bondIndex];
+
+ if (!(familyBondHealths[bondIndex] > 0.0f))
+ continue;
+
+ float shear = 1 * std::abs(1 - std::abs(VecMath::dot(desc.normal, bond.normal)));
+
+ float d[3]; VecMath::sub(bond.centroid, desc.position, d);
+ float ahead = VecMath::dot(d, desc.normal);
+ if (ahead > maxDist)
+ {
+ maxDist = ahead;
+ nextNode = neighbourIndex;
+ }
+
+ const float damage = pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>(bond.centroid, programParams->damageDesc);
+ if (damage > 0.0f && bondFractureCount < bondFractureCountMax)
+ {
+ NvBlastBondFractureData& frac = commandBuffers->bondFractures[bondFractureCount++];
+ frac.userdata = bond.userData;
+ frac.nodeIndex0 = nodeIndex;
+ frac.nodeIndex1 = neighbourIndex;
+ frac.health = shear * damage;
+ }
+ }
+
+ if (nodeIndex == nextNode)
+ break;
+
+ nodeIndex = nextNode;
+ } while (!isInvalidIndex(nextNode));
+
+ commandBuffers->bondFractureCount = bondFractureCount;
+ commandBuffers->chunkFractureCount = chunkFractureCount;
+}
+
+void NvBlastExtShearSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>>(commandBuffers, actor, params);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Triangle Intersection Damage
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define SMALL_NUMBER (1.e-4f)
+
+bool intersectSegmentTriangle(const PxVec3& p, const PxVec3& q, const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxPlane& trianglePlane)
+{
+ const PxVec3 N = trianglePlane.n;
+ const float D = trianglePlane.d;
+
+ PxVec3 intersectPoint;
+ float t = (-D - (p.dot(N))) / ((q - p).dot(N));
+ // If the parameter value is not between 0 and 1, there is no intersection
+ if (t > -SMALL_NUMBER && t < 1.f + SMALL_NUMBER)
+ {
+ intersectPoint = p + t * (q - p);
+ }
+ else
+ {
+ return false;
+ }
+
+ // Compute the normal of the triangle
+ const PxVec3 TriNorm = (b - a).cross(c - a);
+
+ // Compute twice area of triangle ABC
+ const float AreaABCInv = 1.0f / (N.dot(TriNorm));
+
+ // Compute v contribution
+ const float AreaPBC = N.dot((b - intersectPoint).cross(c - intersectPoint));
+ const float v = AreaPBC * AreaABCInv;
+ if (v <= 0.f)
+ return false;
+
+ // Compute w contribution
+ const float AreaPCA = N.dot((c - intersectPoint).cross(a - intersectPoint));
+ const float w = AreaPCA * AreaABCInv;
+ if (w <= 0.f)
+ return false;
+
+ const float u = 1.0f - v - w;
+ return u > 0.f;
+}
+
+void NvBlastExtTriangleIntersectionGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks;
+ const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex;
+ const uint32_t* adjacencyPartition = actor->adjacencyPartition;
+ const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices;
+ const uint32_t* adjacentBondIndices = actor->adjacentBondIndices;
+ const NvBlastBond* assetBonds = actor->assetBonds;
+ const NvBlastChunk* assetChunks = actor->assetChunks;
+ const uint32_t* chunkIndices = actor->chunkIndices;
+ const float* familyBondHealths = actor->familyBondHealths;
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtTriangleIntersectionDamageDesc& desc = *static_cast<const NvBlastExtTriangleIntersectionDamageDesc*>(programParams->damageDesc);
+ const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
+ const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
+ const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(desc.position2));
+ const PxPlane trianglePlane(t0, t1, t2);
+
+ uint32_t outCount = 0;
+
+ const ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<const ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
+ const uint32_t ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE = actor->assetNodeCount / 3;
+ if (damageAccelerator && actor->graphNodeCount > ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE)
+ {
+ const uint32_t CALLBACK_BUFFER_SIZE = 1000;
+
+ class AcceleratorCallback : public ExtDamageAcceleratorInternal::ResultCallback
+ {
+ public:
+ AcceleratorCallback(NvBlastFractureBuffers* commandBuffers, uint32_t& outCount, const NvBlastGraphShaderActor* actor, const NvBlastExtTriangleIntersectionDamageDesc& desc) :
+ ExtDamageAcceleratorInternal::ResultCallback(m_buffer, CALLBACK_BUFFER_SIZE),
+ m_actor(actor),
+ m_commandBuffers(commandBuffers),
+ m_outCount(outCount),
+ m_desc(desc)
+ {
+ }
+
+ virtual void processResults(const ExtDamageAcceleratorInternal::QueryBondData* bondBuffer, uint32_t count) override
+ {
+ const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position0));
+ const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position1));
+ const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position2));
+ const PxPlane trianglePlane(t0, t1, t2);
+
+ for (uint32_t i = 0; i < count; i++)
+ {
+ const ExtDamageAcceleratorInternal::QueryBondData& bondData = bondBuffer[i];
+ if (m_actor->nodeActorIndices[bondData.node0] == m_actor->actorIndex)
+ {
+ if ((m_actor->familyBondHealths[bondData.bond] > 0.0f))
+ {
+ const NvBlastBond& bond = m_actor->assetBonds[bondData.bond];
+ const uint32_t chunkIndex0 = m_actor->chunkIndices[bondData.node0];
+ const uint32_t chunkIndex1 = m_actor->chunkIndices[bondData.node1];
+ const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(m_actor->assetChunks[chunkIndex0].centroid));
+ const PxVec3& normal = (reinterpret_cast<const PxVec3&>(bond.normal));
+ const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
+ const physx::PxVec3& c1 = isInvalidIndex(chunkIndex1) ? (c0 + normal * (bondCentroid - c0).dot(normal)) :
+ (reinterpret_cast<const physx::PxVec3&>(m_actor->assetChunks[chunkIndex1].centroid));
+
+ if(intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
+ {
+ NvBlastBondFractureData& outCommand = m_commandBuffers->bondFractures[m_outCount++];
+ outCommand.nodeIndex0 = bondData.node0;
+ outCommand.nodeIndex1 = bondData.node1;
+ outCommand.health = m_desc.damage;
+ }
+ }
+ }
+ }
+ }
+
+ private:
+ const NvBlastGraphShaderActor* m_actor;
+ NvBlastFractureBuffers* m_commandBuffers;
+ uint32_t& m_outCount;
+ const NvBlastExtTriangleIntersectionDamageDesc& m_desc;
+
+ ExtDamageAcceleratorInternal::QueryBondData m_buffer[CALLBACK_BUFFER_SIZE];
+ };
+
+ AcceleratorCallback cb(commandBuffers, outCount, actor, desc);
+
+ damageAccelerator->findBondSegmentsPlaneIntersected(trianglePlane, cb);
+ }
+ else
+ {
+ uint32_t currentNodeIndex = firstGraphNodeIndex;
+ while (!Nv::Blast::isInvalidIndex(currentNodeIndex))
+ {
+ for (uint32_t adj = adjacencyPartition[currentNodeIndex]; adj < adjacencyPartition[currentNodeIndex + 1]; adj++)
+ {
+ uint32_t adjacentNodeIndex = adjacentNodeIndices[adj];
+ if (currentNodeIndex < adjacentNodeIndex)
+ {
+ uint32_t bondIndex = adjacentBondIndices[adj];
+ // skip bonds that are already broken or were visited already
+ // TODO: investigate why testing against health > -1.0f seems slower
+ // could reuse the island edge bitmap instead
+ if ((familyBondHealths[bondIndex] > 0.0f))
+ {
+ const NvBlastBond& bond = assetBonds[bondIndex];
+ const uint32_t chunkIndex0 = chunkIndices[currentNodeIndex];
+ const uint32_t chunkIndex1 = chunkIndices[adjacentNodeIndex];
+ const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex0].centroid));
+ const PxVec3& normal = (reinterpret_cast<const PxVec3&>(bond.normal));
+ const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
+ const physx::PxVec3& c1 = isInvalidIndex(chunkIndex1) ? (c0 + normal * (bondCentroid - c0).dot(normal)) :
+ (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex1].centroid));
+
+ if (intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
+ {
+ NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++];
+ outCommand.nodeIndex0 = currentNodeIndex;
+ outCommand.nodeIndex1 = adjacentNodeIndex;
+ outCommand.health = desc.damage;
+ }
+ }
+ }
+ }
+ currentNodeIndex = graphNodeIndexLinks[currentNodeIndex];
+ }
+ }
+
+ commandBuffers->bondFractureCount = outCount;
+ commandBuffers->chunkFractureCount = 0;
+}
+
+void NvBlastExtTriangleIntersectionSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ uint32_t chunkFractureCount = 0;
+ uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
+ const uint32_t chunkIndex = actor->chunkIndex;
+ const NvBlastChunk* assetChunks = actor->assetChunks;
+ const NvBlastChunk& chunk = assetChunks[chunkIndex];
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtTriangleIntersectionDamageDesc& desc = *static_cast<const NvBlastExtTriangleIntersectionDamageDesc*>(programParams->damageDesc);
+ const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
+ const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
+ const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(desc.position2));
+ const PxPlane trianglePlane(t0, t1, t2);
+
+ for (uint32_t subChunkIndex = chunk.firstChildIndex; subChunkIndex < chunk.childIndexStop; subChunkIndex++)
+ {
+ const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[subChunkIndex].centroid));
+ const physx::PxVec3& c1 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[subChunkIndex + 1].centroid));
+ if (chunkFractureCount < chunkFractureCountMax && intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
+ {
+ NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
+ frac.chunkIndex = chunkIndex;
+ frac.health = desc.damage;
+ break;
+ }
+ }
+
+ commandBuffers->bondFractureCount = 0;
+ commandBuffers->chunkFractureCount = chunkFractureCount;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Impact Spread Shader
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void NvBlastExtImpactSpreadGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ uint32_t chunkFractureCount = 0;
+ uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
+ uint32_t bondFractureCount = 0;
+ uint32_t bondFractureCountMax = commandBuffers->bondFractureCount;
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtImpactSpreadDamageDesc& desc = *static_cast<const NvBlastExtImpactSpreadDamageDesc*>(programParams->damageDesc);
+ const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks;
+ const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex;
+ const uint32_t* chunkIndices = actor->chunkIndices;
+ const uint32_t* adjacencyPartition = actor->adjacencyPartition;
+ const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices;
+ const uint32_t* adjacentBondIndices = actor->adjacentBondIndices;
+ const NvBlastBond* assetBonds = actor->assetBonds;
+ const NvBlastChunk* assetChunks = actor->assetChunks;
+ const float* familyBondHealths = actor->familyBondHealths;
+ const float* supportChunkHealths = actor->supportChunkHealths;
+
+ // Find nearest chunk.
+ uint32_t closestNode = findClosestNode(desc.position
+ , firstGraphNodeIndex, graphNodeIndexLinks
+ , adjacencyPartition, adjacentNodeIndices, adjacentBondIndices
+ , assetBonds, familyBondHealths
+ , assetChunks, supportChunkHealths, chunkIndices);
+
+ uint32_t nodeIndex = closestNode;
+
+ // Damage this chunk
+ if (chunkFractureCount < chunkFractureCountMax)
+ {
+ const uint32_t chunkIndex = chunkIndices[nodeIndex];
+ NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
+ frac.chunkIndex = chunkIndex;
+ frac.health = desc.damage;
+ }
+
+ // Breadth-first support graph traversal. For radial falloff metric distance is measured along the edges of the graph
+ ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
+ NVBLAST_ASSERT_WITH_MESSAGE(damageAccelerator, "This shader requires damage accelerator passed");
+ if (damageAccelerator)
+ {
+ struct NodeData
+ {
+ uint32_t index;
+ float distance;
+ };
+
+ // Calculating scratch size and requesting it from the accelerator
+ const uint32_t bondCount = actor->adjacencyPartition[actor->assetNodeCount];
+ const size_t nodeQueueSize = align16(FixedQueue<NodeData>::requiredMemorySize(actor->graphNodeCount));
+ const size_t visitedBitmapSize = align16(FixedBitmap::requiredMemorySize(bondCount));
+ const size_t scratchSize = 16 + nodeQueueSize + visitedBitmapSize;
+
+ void* scratch = damageAccelerator->getImmediateScratch(scratchSize);
+
+ // prepare intermediate data on scratch
+ scratch = (void*)align16((size_t)scratch); // Bump to 16-byte alignment
+ FixedQueue<NodeData>* nodeQueue = new (scratch)FixedQueue<NodeData>(actor->graphNodeCount);
+ scratch = pointerOffset(scratch, align16(nodeQueueSize));
+ FixedBitmap* visitedBitmap = new (scratch)FixedBitmap(bondCount);
+ scratch = pointerOffset(scratch, align16(FixedBitmap::requiredMemorySize(bondCount)));
+
+ // initalize traversal
+ nodeQueue->pushBack({ nodeIndex, 0.f });
+ visitedBitmap->clear();
+
+ while (!nodeQueue->empty())
+ {
+ NodeData currentNode = nodeQueue->popFront();
+ const uint32_t startIndex = adjacencyPartition[currentNode.index];
+ const uint32_t stopIndex = adjacencyPartition[currentNode.index + 1];
+
+ for (uint32_t adjacentNodeIndex = startIndex; adjacentNodeIndex < stopIndex; adjacentNodeIndex++)
+ {
+ const uint32_t neighbourIndex = adjacentNodeIndices[adjacentNodeIndex];
+ const uint32_t bondIndex = adjacentBondIndices[adjacentNodeIndex];
+ const NvBlastBond& bond = assetBonds[bondIndex];
+
+ const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
+
+ if (!(familyBondHealths[bondIndex] > 0.0f))
+ continue;
+
+ if (visitedBitmap->test(bondIndex))
+ continue;
+ visitedBitmap->set(bondIndex);
+
+ const uint32_t chunkIndex0 = chunkIndices[currentNode.index];
+ const uint32_t chunkIndex1 = chunkIndices[neighbourIndex];
+ const physx::PxVec3& c0 = reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex0].centroid);
+ bool isNeighbourWorldChunk = isInvalidIndex(chunkIndex1);
+ const physx::PxVec3& c1 = isNeighbourWorldChunk ? bondCentroid : (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex1].centroid));
+
+ const float distance = (c1 - c0).magnitude() * (isNeighbourWorldChunk ? 2.f : 1.f);
+ float totalDistance = currentNode.distance + distance;
+ float totalDamage = falloffProfile(desc.minRadius, desc.maxRadius, totalDistance);
+ if (totalDamage > 0.0f && bondFractureCount < bondFractureCountMax)
+ {
+ NvBlastBondFractureData& frac = commandBuffers->bondFractures[bondFractureCount++];
+ frac.userdata = bond.userData;
+ frac.nodeIndex0 = currentNode.index;
+ frac.nodeIndex1 = neighbourIndex;
+ frac.health = totalDamage;
+ if (!isNeighbourWorldChunk)
+ {
+ nodeQueue->pushBack({ neighbourIndex, totalDistance });
+ }
+ }
+ }
+ }
+ }
+
+ commandBuffers->bondFractureCount = bondFractureCount;
+ commandBuffers->chunkFractureCount = chunkFractureCount;
+}
+
+void NvBlastExtImpactSpreadSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ uint32_t chunkFractureCount = 0;
+ uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
+ const uint32_t chunkIndex = actor->chunkIndex;
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtImpactSpreadDamageDesc& desc = *static_cast<const NvBlastExtImpactSpreadDamageDesc*>(programParams->damageDesc);
+
+ if (chunkFractureCount < chunkFractureCountMax)
+ {
+ NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
+ frac.chunkIndex = chunkIndex;
+ frac.health = desc.damage;
+ }
+
+ commandBuffers->bondFractureCount = 0;
+ commandBuffers->chunkFractureCount = chunkFractureCount;
+}