From 7115f60b91b5717d90f643fd692010905c7004db Mon Sep 17 00:00:00 2001 From: Bryan Galdrikian Date: Thu, 31 May 2018 11:36:08 -0700 Subject: Blast 1.1.3. See docs/release_notes.txt. --- .../source/NvBlastExtDamageAcceleratorAABBTree.cpp | 760 ++++++++++----------- 1 file changed, 380 insertions(+), 380 deletions(-) mode change 100644 => 100755 sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp (limited to 'sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp') diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp old mode 100644 new mode 100755 index 89df930..0f153b7 --- 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 - -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(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(chunks[chunk0].centroid)); - const PxVec3 normal = (reinterpret_cast(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(chunks[chunk0].centroid)); - m_segments[bondIndex].p1 = (reinterpret_cast(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(p0), - reinterpret_cast(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 + +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(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(chunks[chunk0].centroid)); + const PxVec3 normal = (reinterpret_cast(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(chunks[chunk0].centroid)); + m_segments[bondIndex].p1 = (reinterpret_cast(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(p0), + reinterpret_cast(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 -- cgit v1.2.3