diff options
Diffstat (limited to 'sdk/extensions/shaders/source')
| -rwxr-xr-x[-rw-r--r--] | sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp | 760 | ||||
| -rwxr-xr-x[-rw-r--r--] | sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h | 296 | ||||
| -rwxr-xr-x[-rw-r--r--] | sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h | 192 | ||||
| -rwxr-xr-x[-rw-r--r--] | sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp | 86 | ||||
| -rwxr-xr-x[-rw-r--r--] | sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp | 1526 |
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;
+}
|