diff options
| author | Anton Novoselov <[email protected]> | 2017-08-01 12:53:38 +0300 |
|---|---|---|
| committer | Anton Novoselov <[email protected]> | 2017-08-01 12:53:38 +0300 |
| commit | 236f03c0b9a4982328ed1201978f7f69d192d9b2 (patch) | |
| tree | e486f2fa39dba203563895541e92c60ed3e25759 /sdk/lowlevel/source | |
| parent | Added screens to welcome page (diff) | |
| download | blast-236f03c0b9a4982328ed1201978f7f69d192d9b2.tar.xz blast-236f03c0b9a4982328ed1201978f7f69d192d9b2.zip | |
Blast 1.1 release (windows / linux)
see docs/release_notes.txt for details
Diffstat (limited to 'sdk/lowlevel/source')
| -rw-r--r-- | sdk/lowlevel/source/NvBlastActor.cpp | 629 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastActor.h | 198 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastActorSerializationBlock.cpp | 109 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastActorSerializationBlock.h | 36 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastAsset.cpp | 236 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastAsset.h | 36 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastAssetHelper.cpp | 108 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastChunkHierarchy.h | 36 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastFamily.cpp | 535 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastFamily.h | 216 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastFamilyGraph.cpp | 36 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastFamilyGraph.h | 37 | ||||
| -rw-r--r-- | sdk/lowlevel/source/NvBlastSupportGraph.h | 37 |
13 files changed, 1388 insertions, 861 deletions
diff --git a/sdk/lowlevel/source/NvBlastActor.cpp b/sdk/lowlevel/source/NvBlastActor.cpp index b93c47a..afed7bb 100644 --- a/sdk/lowlevel/source/NvBlastActor.cpp +++ b/sdk/lowlevel/source/NvBlastActor.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastActor.h" #include "NvBlastFamilyGraph.h" @@ -24,29 +42,11 @@ namespace Nv namespace Blast { -//////// Local helper functions //////// - -#if NVBLAST_CHECK_PARAMS -/** -Helper function to validate fracture buffer values being meaningful. -*/ -static inline bool isValid(const NvBlastFractureBuffers* buffers) -{ - if (buffers->chunkFractureCount != 0 && buffers->chunkFractures == nullptr) - return false; - - if (buffers->bondFractureCount != 0 && buffers->bondFractures == nullptr) - return false; - - return true; -} -#endif - //////// Actor static methods //////// size_t Actor::createRequiredScratch(const NvBlastFamily* family) { -#if NVBLAST_CHECK_PARAMS +#if NVBLASTLL_CHECK_PARAMS if (family == nullptr || reinterpret_cast<const FamilyHeader*>(family)->m_asset == nullptr) { NVBLAST_ALWAYS_ASSERT(); @@ -61,22 +61,22 @@ size_t Actor::createRequiredScratch(const NvBlastFamily* family) Actor* Actor::create(NvBlastFamily* family, const NvBlastActorDesc* desc, void* scratch, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "Actor::create: NULL family pointer input.", return nullptr); - NVBLAST_CHECK(reinterpret_cast<FamilyHeader*>(family)->m_asset != nullptr, logFn, "Actor::create: family has NULL asset.", return nullptr); - NVBLAST_CHECK(reinterpret_cast<FamilyHeader*>(family)->m_asset->m_graph.m_nodeCount != 0, logFn, "Actor::create: family's asset has no support chunks.", return nullptr); - NVBLAST_CHECK(desc != nullptr, logFn, "Actor::create: NULL desc pointer input.", return nullptr); - NVBLAST_CHECK(scratch != nullptr, logFn, "Actor::create: NULL scratch input.", return nullptr); + NVBLASTLL_CHECK(family != nullptr, logFn, "Actor::create: NULL family pointer input.", return nullptr); + NVBLASTLL_CHECK(reinterpret_cast<FamilyHeader*>(family)->m_asset != nullptr, logFn, "Actor::create: family has NULL asset.", return nullptr); + NVBLASTLL_CHECK(reinterpret_cast<FamilyHeader*>(family)->m_asset->m_graph.m_nodeCount != 0, logFn, "Actor::create: family's asset has no support chunks.", return nullptr); + NVBLASTLL_CHECK(desc != nullptr, logFn, "Actor::create: NULL desc pointer input.", return nullptr); + NVBLASTLL_CHECK(scratch != nullptr, logFn, "Actor::create: NULL scratch input.", return nullptr); FamilyHeader* header = reinterpret_cast<FamilyHeader*>(family); if (header->m_actorCount > 0) { - NVBLAST_LOG_ERROR(logFn, "Actor::create: input family is not empty."); + NVBLASTLL_LOG_ERROR(logFn, "Actor::create: input family is not empty."); return nullptr; } const Asset& solverAsset = *static_cast<const Asset*>(header->m_asset); - const Nv::Blast::SupportGraph& graph = solverAsset.m_graph; + const SupportGraph& graph = solverAsset.m_graph; // Lower support chunk healths - initialize float* lowerSupportChunkHealths = header->getLowerSupportChunkHealths(); @@ -190,14 +190,14 @@ uint32_t Actor::damageBond(const NvBlastBondFractureData& cmd) void Actor::generateFracture(NvBlastFractureBuffers* commandBuffers, const NvBlastDamageProgram& program, const NvBlastProgramParams* programParams, NvBlastLog logFn, NvBlastTimers* timers) const { - NVBLAST_CHECK(commandBuffers != nullptr, logFn, "Actor::generateFracture: NULL commandBuffers pointer input.", return); - NVBLAST_CHECK(isValid(commandBuffers), logFn, "NvBlastActorGenerateFracture: commandBuffers memory is NULL but size is > 0.", + NVBLASTLL_CHECK(commandBuffers != nullptr, logFn, "Actor::generateFracture: NULL commandBuffers pointer input.", return); + NVBLASTLL_CHECK(isValid(commandBuffers), logFn, "NvBlastActorGenerateFracture: commandBuffers memory is NULL but size is > 0.", commandBuffers->bondFractureCount = 0; commandBuffers->chunkFractureCount = 0; return); -#if NVBLAST_CHECK_PARAMS +#if NVBLASTLL_CHECK_PARAMS if (commandBuffers->bondFractureCount == 0 && commandBuffers->chunkFractureCount == 0) { - NVBLAST_LOG_WARNING(logFn, "NvBlastActorGenerateFracture: commandBuffers do not provide any space."); + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorGenerateFracture: commandBuffers do not provide any space."); return; } #endif @@ -221,7 +221,9 @@ void Actor::generateFracture(NvBlastFractureBuffers* commandBuffers, const NvBla graph->getAdjacentNodeIndices(), graph->getAdjacentBondIndices(), getBonds(), - getBondHealths() + getChunks(), + getBondHealths(), + getLowerSupportChunkHealths() }; program.graphShaderFunction(commandBuffers, &shaderActor, programParams); @@ -252,374 +254,6 @@ void Actor::generateFracture(NvBlastFractureBuffers* commandBuffers, const NvBla } -void Actor::fractureSubSupportNoEvents(uint32_t chunkIndex, uint32_t suboffset, float healthDamage, float* chunkHealths, const NvBlastChunk* chunks) -{ - const NvBlastChunk& chunk = chunks[chunkIndex]; - uint32_t numChildren = chunk.childIndexStop - chunk.firstChildIndex; - - if (numChildren > 0) - { - healthDamage /= numChildren; - for (uint32_t childIndex = chunk.firstChildIndex; childIndex < chunk.childIndexStop; childIndex++) - { - float& health = chunkHealths[childIndex - suboffset]; - if (health > 0.0f) - { - float remainingDamage = healthDamage - health; - health -= healthDamage; - - NVBLAST_ASSERT(chunks[childIndex].parentChunkIndex == chunkIndex); - - if (health <= 0.0f && remainingDamage > 0.0f) - { - fractureSubSupportNoEvents(childIndex, suboffset, remainingDamage, chunkHealths, chunks); - } - } - } - } -} - - -void Actor::fractureSubSupport(uint32_t chunkIndex, uint32_t suboffset, float healthDamage, float* chunkHealths, const NvBlastChunk* chunks, NvBlastChunkFractureData* outBuffer, uint32_t* currentIndex, const uint32_t maxCount) -{ - const NvBlastChunk& chunk = chunks[chunkIndex]; - uint32_t numChildren = chunk.childIndexStop - chunk.firstChildIndex; - - if (numChildren > 0) - { - healthDamage /= numChildren; - for (uint32_t childIndex = chunk.firstChildIndex; childIndex < chunk.childIndexStop; childIndex++) - { - float& health = chunkHealths[childIndex - suboffset]; - if (health > 0.0f) - { - float remainingDamage = healthDamage - health; - health -= healthDamage; - - NVBLAST_ASSERT(chunks[childIndex].parentChunkIndex == chunkIndex); - - if (*currentIndex < maxCount) - { - NvBlastChunkFractureData& event = outBuffer[*currentIndex]; - event.userdata = chunks[childIndex].userData; - event.chunkIndex = childIndex; - event.health = health; - } - (*currentIndex)++; - - if (health <= 0.0f && remainingDamage > 0.0f) - { - fractureSubSupport(childIndex, suboffset, remainingDamage, chunkHealths, chunks, outBuffer, currentIndex, maxCount); - } - } - } - } - -} - - -void Actor::fractureNoEvents(uint32_t chunkFractureCount, const NvBlastChunkFractureData* chunkFractures) -{ - const Asset& asset = *getAsset(); - const SupportGraph& graph = *getGraph(); - const uint32_t* graphAdjacencyPartition = graph.getAdjacencyPartition(); - const uint32_t* graphAdjacentNodeIndices = graph.getAdjacentNodeIndices(); - float* bondHealths = getBondHealths(); - float* chunkHealths = getLowerSupportChunkHealths(); - float* subChunkHealths = getSubsupportChunkHealths(); - const NvBlastChunk* chunks = getChunks(); - - for (uint32_t i = 0; i < chunkFractureCount; ++i) - { - const NvBlastChunkFractureData& command = chunkFractures[i]; - const uint32_t chunkIndex = command.chunkIndex; - const uint32_t chunkHealthIndex = asset.getContiguousLowerSupportIndex(chunkIndex); - NVBLAST_ASSERT(!isInvalidIndex(chunkHealthIndex)); - if (isInvalidIndex(chunkHealthIndex)) - { - continue; - } - float& health = chunkHealths[chunkHealthIndex]; - if (health > 0.0f && command.health > 0.0f) - { - const uint32_t nodeIndex = asset.getChunkToGraphNodeMap()[chunkIndex]; - if (getGraphNodeCount() > 1 && !isInvalidIndex(nodeIndex)) - { - for (uint32_t adjacentIndex = graphAdjacencyPartition[nodeIndex]; adjacentIndex < graphAdjacencyPartition[nodeIndex + 1]; adjacentIndex++) - { - - const uint32_t bondIndex = graph.findBond(nodeIndex, graphAdjacentNodeIndices[adjacentIndex]); - NVBLAST_ASSERT(!isInvalidIndex(bondIndex)); - if (bondHealths[bondIndex] > 0.0f) - { - bondHealths[bondIndex] = 0.0f; - } - } - getFamilyGraph()->notifyNodeRemoved(getIndex(), nodeIndex, &graph); - } - - health -= command.health; - - const float remainingDamage = -health; - - if (remainingDamage > 0.0f) // node chunk has been damaged beyond its health - { - uint32_t firstSubOffset = getFirstSubsupportChunkIndex(); - fractureSubSupportNoEvents(chunkIndex, firstSubOffset, remainingDamage, subChunkHealths, chunks); - } - } - } -} - - -void Actor::fractureWithEvents(uint32_t chunkFractureCount, const NvBlastChunkFractureData* commands, NvBlastChunkFractureData* events, uint32_t eventsSize, uint32_t* count) -{ - const Asset& asset = *getAsset(); - const SupportGraph& graph = *getGraph(); - const uint32_t* graphAdjacencyPartition = graph.getAdjacencyPartition(); - const uint32_t* graphAdjacentNodeIndices = graph.getAdjacentNodeIndices(); - float* bondHealths = getBondHealths(); - float* chunkHealths = getLowerSupportChunkHealths(); - float* subChunkHealths = getSubsupportChunkHealths(); - const NvBlastChunk* chunks = getChunks(); - - for (uint32_t i = 0; i < chunkFractureCount; ++i) - { - const NvBlastChunkFractureData& command = commands[i]; - const uint32_t chunkIndex = command.chunkIndex; - const uint32_t chunkHealthIndex = asset.getContiguousLowerSupportIndex(chunkIndex); - NVBLAST_ASSERT(!isInvalidIndex(chunkHealthIndex)); - if (isInvalidIndex(chunkHealthIndex)) - { - continue; - } - float& health = chunkHealths[chunkHealthIndex]; - if (health > 0.0f && command.health > 0.0f) - { - const uint32_t nodeIndex = asset.getChunkToGraphNodeMap()[chunkIndex]; - if (getGraphNodeCount() > 1 && !isInvalidIndex(nodeIndex)) - { - for (uint32_t adjacentIndex = graphAdjacencyPartition[nodeIndex]; adjacentIndex < graphAdjacencyPartition[nodeIndex + 1]; adjacentIndex++) - { - const uint32_t bondIndex = graph.findBond(nodeIndex, graphAdjacentNodeIndices[adjacentIndex]); - NVBLAST_ASSERT(!isInvalidIndex(bondIndex)); - if (bondHealths[bondIndex] > 0.0f) - { - bondHealths[bondIndex] = 0.0f; - } - } - getFamilyGraph()->notifyNodeRemoved(getIndex(), nodeIndex, &graph); - } - - health -= command.health; - - if (*count < eventsSize) - { - NvBlastChunkFractureData& outEvent = events[*count]; - outEvent.userdata = chunks[chunkIndex].userData; - outEvent.chunkIndex = chunkIndex; - outEvent.health = health; - } - (*count)++; - - const float remainingDamage = -health; - - if (remainingDamage > 0.0f) // node chunk has been damaged beyond its health - { - uint32_t firstSubOffset = getFirstSubsupportChunkIndex(); - fractureSubSupport(chunkIndex, firstSubOffset, remainingDamage, subChunkHealths, chunks, events, count, eventsSize); - } - } - } -} - - -void Actor::fractureInPlaceEvents(uint32_t chunkFractureCount, NvBlastChunkFractureData* inoutbuffer, uint32_t eventsSize, uint32_t* count) -{ - const Asset& asset = *getAsset(); - const SupportGraph& graph = *getGraph(); - const uint32_t* graphAdjacencyPartition = graph.getAdjacencyPartition(); - const uint32_t* graphAdjacentNodeIndices = graph.getAdjacentNodeIndices(); - float* bondHealths = getBondHealths(); - float* chunkHealths = getLowerSupportChunkHealths(); - float* subChunkHealths = getSubsupportChunkHealths(); - const NvBlastChunk* chunks = getChunks(); - - // - // First level Chunk Fractures - // - - for (uint32_t i = 0; i < chunkFractureCount; ++i) - { - const NvBlastChunkFractureData& command = inoutbuffer[i]; - const uint32_t chunkIndex = command.chunkIndex; - const uint32_t chunkHealthIndex = asset.getContiguousLowerSupportIndex(chunkIndex); - NVBLAST_ASSERT(!isInvalidIndex(chunkHealthIndex)); - if (isInvalidIndex(chunkHealthIndex)) - { - continue; - } - float& health = chunkHealths[chunkHealthIndex]; - if (health > 0.0f && command.health > 0.0f) - { - const uint32_t nodeIndex = asset.getChunkToGraphNodeMap()[chunkIndex]; - if (getGraphNodeCount() > 1 && !isInvalidIndex(nodeIndex)) - { - for (uint32_t adjacentIndex = graphAdjacencyPartition[nodeIndex]; adjacentIndex < graphAdjacencyPartition[nodeIndex + 1]; adjacentIndex++) - { - const uint32_t bondIndex = graph.findBond(nodeIndex, graphAdjacentNodeIndices[adjacentIndex]); - NVBLAST_ASSERT(!isInvalidIndex(bondIndex)); - if (bondHealths[bondIndex] > 0.0f) - { - bondHealths[bondIndex] = 0.0f; - } - } - getFamilyGraph()->notifyNodeRemoved(getIndex(), nodeIndex, &graph); - } - - health -= command.health; - - NvBlastChunkFractureData& outEvent = inoutbuffer[(*count)++]; - outEvent.userdata = chunks[chunkIndex].userData; - outEvent.chunkIndex = chunkIndex; - outEvent.health = health; - } - } - - // - // Hierarchical Chunk Fractures - // - - uint32_t commandedChunkFractures = *count; - - for (uint32_t i = 0; i < commandedChunkFractures; ++i) - { - NvBlastChunkFractureData& event = inoutbuffer[i]; - const uint32_t chunkIndex = event.chunkIndex; - - const float remainingDamage = -event.health; - if (remainingDamage > 0.0f) // node chunk has been damaged beyond its health - { - uint32_t firstSubOffset = getFirstSubsupportChunkIndex(); - fractureSubSupport(chunkIndex, firstSubOffset, remainingDamage, subChunkHealths, chunks, inoutbuffer, count, eventsSize); - } - } -} - - -void Actor::applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands, NvBlastLog logFn, NvBlastTimers* timers) -{ - NVBLAST_CHECK(commands != nullptr, logFn, "Actor::applyFracture: NULL commands pointer input.", return); - NVBLAST_CHECK(isValid(commands), logFn, "Actor::applyFracture: commands memory is NULL but size is > 0.", return); - NVBLAST_CHECK(eventBuffers == nullptr || isValid(eventBuffers), logFn, "NvBlastActorApplyFracture: eventBuffers memory is NULL but size is > 0.", - eventBuffers->bondFractureCount = 0; eventBuffers->chunkFractureCount = 0; return); - -#if NVBLAST_CHECK_PARAMS - if (eventBuffers != nullptr && eventBuffers->bondFractureCount == 0 && eventBuffers->chunkFractureCount == 0) - { - NVBLAST_LOG_WARNING(logFn, "NvBlastActorApplyFracture: eventBuffers do not provide any space."); - return; - } -#endif - -#if NV_PROFILE - Time time; -#else - NV_UNUSED(timers); -#endif - - // - // Chunk Fracture - // - - if (eventBuffers == nullptr || eventBuffers->chunkFractures == nullptr) - { - // immediate hierarchical fracture - fractureNoEvents(commands->chunkFractureCount, commands->chunkFractures); - } - else if (eventBuffers->chunkFractures != commands->chunkFractures) - { - // immediate hierarchical fracture - uint32_t count = 0; - fractureWithEvents(commands->chunkFractureCount, commands->chunkFractures, eventBuffers->chunkFractures, eventBuffers->chunkFractureCount, &count); - - if (count > eventBuffers->chunkFractureCount) - { - NVBLAST_LOG_WARNING(logFn, "NvBlastActorApplyFracture: eventBuffers too small. Chunk events were lost."); - } - else - { - eventBuffers->chunkFractureCount = count; - } - } - else if (eventBuffers->chunkFractures == commands->chunkFractures) - { - // compacting first - uint32_t count = 0; - fractureInPlaceEvents(commands->chunkFractureCount, commands->chunkFractures, eventBuffers->chunkFractureCount, &count); - - if (count > eventBuffers->chunkFractureCount) - { - NVBLAST_LOG_WARNING(logFn, "NvBlastActorApplyFracture: eventBuffers too small. Chunk events were lost."); - } - else - { - eventBuffers->chunkFractureCount = count; - } - } - - // - // Bond Fracture - // - - uint32_t outCount = 0; - const uint32_t eventBufferSize = eventBuffers ? eventBuffers->bondFractureCount : 0; - - NvBlastBond* bonds = getBonds(); - float* bondHealths = getBondHealths(); - for (uint32_t i = 0; i < commands->bondFractureCount; ++i) - { - const NvBlastBondFractureData& frac = commands->bondFractures[i]; - - const uint32_t bondIndex = damageBond(frac.nodeIndex0, frac.nodeIndex1, frac.health); - - if (!isInvalidIndex(bondIndex)) - { - if (eventBuffers && eventBuffers->bondFractures) - { - if (outCount < eventBufferSize) - { - NvBlastBondFractureData& outEvent = eventBuffers->bondFractures[outCount]; - outEvent.userdata = bonds[bondIndex].userData; - outEvent.nodeIndex0 = frac.nodeIndex0; - outEvent.nodeIndex1 = frac.nodeIndex1; - outEvent.health = bondHealths[bondIndex]; - } - } - outCount++; - } - } - - if (eventBuffers && eventBuffers->bondFractures) - { - if (outCount > eventBufferSize) - { - NVBLAST_LOG_WARNING(logFn, "NvBlastActorApplyFracture: eventBuffers too small. Bond events were lost."); - } - else - { - eventBuffers->bondFractureCount = outCount; - } - } - -#if NV_PROFILE - if (timers != nullptr) - { - timers->fracture += time.getElapsedTicks(); - } -#endif - -} size_t Actor::splitRequiredScratch() const @@ -630,9 +264,9 @@ size_t Actor::splitRequiredScratch() const uint32_t Actor::split(NvBlastActorSplitEvent* result, uint32_t newActorsMaxCount, void* scratch, NvBlastLog logFn, NvBlastTimers* timers) { - NVBLAST_CHECK(result != nullptr, logFn, "Actor::split: NULL result pointer input.", return 0); - NVBLAST_CHECK(newActorsMaxCount > 0 && result->newActors != nullptr, logFn, "NvBlastActorSplit: no space for results provided.", return 0); - NVBLAST_CHECK(scratch != nullptr, logFn, "Actor::split: NULL scratch pointer input.", return 0); + NVBLASTLL_CHECK(result != nullptr, logFn, "Actor::split: NULL result pointer input.", return 0); + NVBLASTLL_CHECK(newActorsMaxCount > 0 && result->newActors != nullptr, logFn, "NvBlastActorSplit: no space for results provided.", return 0); + NVBLASTLL_CHECK(scratch != nullptr, logFn, "Actor::split: NULL scratch pointer input.", return 0); #if NV_PROFILE Time time; @@ -708,10 +342,21 @@ uint32_t Actor::split(NvBlastActorSplitEvent* result, uint32_t newActorsMaxCount #endif // Recalculate visible chunk lists if the graph nodes have been redistributed + uint32_t actualActorsCount = 0; for (uint32_t i = 0; i < actorsCount; ++i) { - newActors[i]->updateVisibleChunksFromGraphNodes(); + newActors[actualActorsCount] = newActors[i]; + newActors[actualActorsCount]->updateVisibleChunksFromGraphNodes(); + if (newActors[actualActorsCount]->getVisibleChunkCount() > 0) // If we've split such that the world node is by itself, it will have no visible chunks + { + ++actualActorsCount; + } + else + { + getFamilyHeader()->returnActor(*newActors[actualActorsCount]); + } } + actorsCount = actualActorsCount; #if NV_PROFILE if (timers != nullptr) @@ -780,7 +425,7 @@ uint32_t Actor::partitionMultipleGraphNodes(Actor** newActors, uint32_t newActor // Check for single subsupport chunk, no partitioning if (m_graphNodeCount <= 1) { - NVBLAST_LOG_WARNING(logFn, "Nv::Blast::Actor::partitionMultipleGraphNodes: actor is a single lower-support chunk, and cannot be partitioned by this function."); + NVBLASTLL_LOG_WARNING(logFn, "Nv::Blast::Actor::partitionMultipleGraphNodes: actor is a single lower-support chunk, and cannot be partitioned by this function."); return 0; } @@ -810,7 +455,11 @@ uint32_t Actor::partitionMultipleGraphNodes(Actor** newActors, uint32_t newActor if (islandID == thisActorIndex) { - m_leafChunkCount += subtreeLeafChunkCounts[graphChunkIndices[graphNodeIndex]]; + const uint32_t graphChunkIndex = graphChunkIndices[graphNodeIndex]; + if (!isInvalidIndex(graphChunkIndex)) // Invalid if this is the world chunk + { + m_leafChunkCount += subtreeLeafChunkCounts[graphChunkIndex]; + } lastGraphNodeIndex = graphNodeIndex; continue; // Leave the chunk in this actor } @@ -855,7 +504,11 @@ uint32_t Actor::partitionMultipleGraphNodes(Actor** newActors, uint32_t newActor newActor->m_firstGraphNodeIndex = graphNodeIndex; ++newActor->m_graphNodeCount; // Add to the actor's leaf chunk count - newActor->m_leafChunkCount += subtreeLeafChunkCounts[graphChunkIndices[graphNodeIndex]]; + const uint32_t graphChunkIndex = graphChunkIndices[graphNodeIndex]; + if (!isInvalidIndex(graphChunkIndex)) // Invalid if this is the world chunk + { + newActor->m_leafChunkCount += subtreeLeafChunkCounts[graphChunkIndex]; + } } if (m_graphNodeCount > 0) @@ -878,7 +531,7 @@ uint32_t Actor::partitionMultipleGraphNodes(Actor** newActors, uint32_t newActor if (overflow) { - NVBLAST_LOG_WARNING(logFn, "Nv::Blast::Actor::partitionMultipleGraphNodes: input newActors array could not hold all actors generated."); + NVBLASTLL_LOG_WARNING(logFn, "Nv::Blast::Actor::partitionMultipleGraphNodes: input newActors array could not hold all actors generated."); } return newActorCount; @@ -892,7 +545,7 @@ uint32_t Actor::partitionSingleLowerSupportChunk(Actor** newActors, uint32_t new // Ensure this is a single subsupport chunk, no partitioning if (m_graphNodeCount > 1) { - NVBLAST_LOG_WARNING(logFn, "Nv::Blast::Actor::partitionSingleLowerSupportChunk: actor is not a single lower-support chunk, and cannot be partitioned by this function."); + NVBLASTLL_LOG_WARNING(logFn, "Nv::Blast::Actor::partitionSingleLowerSupportChunk: actor is not a single lower-support chunk, and cannot be partitioned by this function."); return 0; } @@ -901,6 +554,12 @@ uint32_t Actor::partitionSingleLowerSupportChunk(Actor** newActors, uint32_t new // The conditional (visible vs. support chunk) is needed because we allow single-child chunk chains // This makes it possible that an actor with a single support chunk will have a different visible chunk (ancestor of the support chunk) const uint32_t chunkIndex = m_graphNodeCount == 0 ? m_firstVisibleChunkIndex : getGraph()->getChunkIndices()[m_firstGraphNodeIndex]; + + if (isInvalidIndex(chunkIndex)) + { + return 0; // This actor has no chunks; only a graph node representing the world + } + NVBLAST_ASSERT(isInvalidIndex(header->getVisibleChunkIndexLinks()[chunkIndex].m_adj[1])); const NvBlastChunk& chunk = header->m_asset->getChunks()[chunkIndex]; @@ -909,7 +568,7 @@ uint32_t Actor::partitionSingleLowerSupportChunk(Actor** newActors, uint32_t new // Warn if we cannot fit all child chunks in the output list if (childCount > newActorsSize) { - NVBLAST_LOG_WARNING(logFn, "Nv::Blast::Actor::partitionSingleLowerSupportChunk: input newActors array will not hold all actors generated."); + NVBLASTLL_LOG_WARNING(logFn, "Nv::Blast::Actor::partitionSingleLowerSupportChunk: input newActors array will not hold all actors generated."); childCount = newActorsSize; } @@ -959,7 +618,7 @@ void Actor::updateVisibleChunksFromGraphNodes() Actor* actors = header->getActors(); IndexDLink<uint32_t>* visibleChunkIndexLinks = header->getVisibleChunkIndexLinks(); uint32_t* chunkActorIndices = header->getChunkActorIndices(); - const Nv::Blast::SupportGraph& graph = asset->m_graph; + const SupportGraph& graph = asset->m_graph; const uint32_t* graphChunkIndices = graph.getChunkIndices(); const NvBlastChunk* chunks = asset->getChunks(); const uint32_t upperSupportChunkCount = asset->getUpperSupportChunkCount(); @@ -968,7 +627,11 @@ void Actor::updateVisibleChunksFromGraphNodes() const uint32_t* graphNodeIndexLinks = header->getGraphNodeIndexLinks(); for (uint32_t graphNodeIndex = m_firstGraphNodeIndex; !isInvalidIndex(graphNodeIndex); graphNodeIndex = graphNodeIndexLinks[graphNodeIndex]) { - updateVisibleChunksFromSupportChunk<Actor>(actors, visibleChunkIndexLinks, chunkActorIndices, thisActorIndex, graphChunkIndices[graphNodeIndex], chunks, upperSupportChunkCount); + const uint32_t supportChunkIndex = graphChunkIndices[graphNodeIndex]; + if (!isInvalidIndex(supportChunkIndex)) // Invalid if this is the world chunk + { + updateVisibleChunksFromSupportChunk<Actor>(actors, visibleChunkIndexLinks, chunkActorIndices, thisActorIndex, graphChunkIndices[graphNodeIndex], chunks, upperSupportChunkCount); + } } } @@ -983,9 +646,9 @@ extern "C" NvBlastActor* NvBlastFamilyCreateFirstActor(NvBlastFamily* family, const NvBlastActorDesc* desc, void* scratch, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyCreateFirstActor: NULL family input.", return nullptr); - NVBLAST_CHECK(desc != nullptr, logFn, "NvBlastFamilyCreateFirstActor: NULL desc input.", return nullptr); - NVBLAST_CHECK(scratch != nullptr, logFn, "NvBlastFamilyCreateFirstActor: NULL scratch input.", return nullptr); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyCreateFirstActor: NULL family input.", return nullptr); + NVBLASTLL_CHECK(desc != nullptr, logFn, "NvBlastFamilyCreateFirstActor: NULL desc input.", return nullptr); + NVBLASTLL_CHECK(scratch != nullptr, logFn, "NvBlastFamilyCreateFirstActor: NULL scratch input.", return nullptr); return Nv::Blast::Actor::create(family, desc, scratch, logFn); } @@ -993,8 +656,8 @@ NvBlastActor* NvBlastFamilyCreateFirstActor(NvBlastFamily* family, const NvBlast size_t NvBlastFamilyGetRequiredScratchForCreateFirstActor(const NvBlastFamily* family, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetRequiredScratchForCreateFirstActor: NULL family input.", return 0); - NVBLAST_CHECK(reinterpret_cast<const Nv::Blast::FamilyHeader*>(family)->m_asset != nullptr, + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyGetRequiredScratchForCreateFirstActor: NULL family input.", return 0); + NVBLASTLL_CHECK(reinterpret_cast<const Nv::Blast::FamilyHeader*>(family)->m_asset != nullptr, logFn, "NvBlastFamilyGetRequiredScratchForCreateFirstActor: family has NULL asset.", return 0); return Nv::Blast::Actor::createRequiredScratch(family); @@ -1003,13 +666,13 @@ size_t NvBlastFamilyGetRequiredScratchForCreateFirstActor(const NvBlastFamily* f bool NvBlastActorDeactivate(NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorDeactivate: NULL actor input.", return false); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorDeactivate: NULL actor input.", return false); Nv::Blast::Actor& a = *static_cast<Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_WARNING(logFn, "NvBlastActorDeactivate: inactive actor input."); + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorDeactivate: inactive actor input."); } return a.release(); @@ -1018,13 +681,13 @@ bool NvBlastActorDeactivate(NvBlastActor* actor, NvBlastLog logFn) uint32_t NvBlastActorGetVisibleChunkCount(const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetVisibleChunkCount: NULL actor input.", return 0); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetVisibleChunkCount: NULL actor input.", return 0); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetVisibleChunkCount: inactive actor input."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetVisibleChunkCount: inactive actor input."); return 0; } @@ -1034,14 +697,14 @@ uint32_t NvBlastActorGetVisibleChunkCount(const NvBlastActor* actor, NvBlastLog uint32_t NvBlastActorGetVisibleChunkIndices(uint32_t* visibleChunkIndices, uint32_t visibleChunkIndicesSize, const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(visibleChunkIndices != nullptr, logFn, "NvBlastActorGetVisibleChunkIndices: NULL visibleChunkIndices pointer input.", return 0); - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetVisibleChunkIndices: NULL actor pointer input.", return 0); + NVBLASTLL_CHECK(visibleChunkIndices != nullptr, logFn, "NvBlastActorGetVisibleChunkIndices: NULL visibleChunkIndices pointer input.", return 0); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetVisibleChunkIndices: NULL actor pointer input.", return 0); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetVisibleChunkIndices: inactive actor pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetVisibleChunkIndices: inactive actor pointer input."); return 0; } @@ -1058,13 +721,13 @@ uint32_t NvBlastActorGetVisibleChunkIndices(uint32_t* visibleChunkIndices, uint3 uint32_t NvBlastActorGetGraphNodeCount(const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetGraphNodeCount: NULL actor pointer input.", return 0); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetGraphNodeCount: NULL actor pointer input.", return 0); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetGraphNodeCount: inactive actor pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetGraphNodeCount: inactive actor pointer input."); return 0; } @@ -1074,22 +737,27 @@ uint32_t NvBlastActorGetGraphNodeCount(const NvBlastActor* actor, NvBlastLog log uint32_t NvBlastActorGetGraphNodeIndices(uint32_t* graphNodeIndices, uint32_t graphNodeIndicesSize, const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(graphNodeIndices != nullptr, logFn, "NvBlastActorGetGraphNodeIndices: NULL graphNodeIndices pointer input.", return 0); - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetGraphNodeIndices: NULL actor pointer input.", return 0); + NVBLASTLL_CHECK(graphNodeIndices != nullptr, logFn, "NvBlastActorGetGraphNodeIndices: NULL graphNodeIndices pointer input.", return 0); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetGraphNodeIndices: NULL actor pointer input.", return 0); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetGraphNodeIndices: inactive actor pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetGraphNodeIndices: inactive actor pointer input."); return 0; } // Iterate through graph node list and write to supplied array + const uint32_t* graphChunkIndices = a.getAsset()->m_graph.getChunkIndices(); uint32_t indexCount = 0; for (Nv::Blast::Actor::GraphNodeIt i = a; indexCount < graphNodeIndicesSize && (bool)i; ++i) { - graphNodeIndices[indexCount++] = (uint32_t)i; + const uint32_t graphNodeIndex = (uint32_t)i; + if (!Nv::Blast::isInvalidIndex(graphChunkIndices[graphNodeIndex])) + { + graphNodeIndices[indexCount++] = graphNodeIndex; + } } return indexCount; @@ -1098,13 +766,13 @@ uint32_t NvBlastActorGetGraphNodeIndices(uint32_t* graphNodeIndices, uint32_t gr const float* NvBlastActorGetBondHealths(const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetBondHealths: NULL actor pointer input.", return nullptr); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetBondHealths: NULL actor pointer input.", return nullptr); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetBondHealths: inactive actor pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetBondHealths: inactive actor pointer input."); return nullptr; } @@ -1114,13 +782,13 @@ const float* NvBlastActorGetBondHealths(const NvBlastActor* actor, NvBlastLog lo NvBlastFamily* NvBlastActorGetFamily(const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetFamily: NULL actor pointer input.", return nullptr); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetFamily: NULL actor pointer input.", return nullptr); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetFamily: inactive actor pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetFamily: inactive actor pointer input."); return nullptr; } @@ -1130,13 +798,13 @@ NvBlastFamily* NvBlastActorGetFamily(const NvBlastActor* actor, NvBlastLog logFn uint32_t NvBlastActorGetIndex(const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetIndex: NULL actor pointer input.", return Nv::Blast::invalidIndex<uint32_t>()); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetIndex: NULL actor pointer input.", return Nv::Blast::invalidIndex<uint32_t>()); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetIndex: actor is not active."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetIndex: actor is not active."); return Nv::Blast::invalidIndex<uint32_t>(); } @@ -1154,14 +822,14 @@ void NvBlastActorGenerateFracture NvBlastTimers* timers ) { - NVBLAST_CHECK(commandBuffers != nullptr, logFn, "NvBlastActorGenerateFracture: NULL commandBuffers pointer input.", return); - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGenerateFracture: NULL actor pointer input.", return); + NVBLASTLL_CHECK(commandBuffers != nullptr, logFn, "NvBlastActorGenerateFracture: NULL commandBuffers pointer input.", return); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGenerateFracture: NULL actor pointer input.", return); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGenerateFracture: actor is not active."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGenerateFracture: actor is not active."); commandBuffers->bondFractureCount = 0; commandBuffers->chunkFractureCount = 0; return; @@ -1180,15 +848,15 @@ void NvBlastActorApplyFracture NvBlastTimers* timers ) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorApplyFracture: NULL actor pointer input.", return); - NVBLAST_CHECK(commands != nullptr, logFn, "NvBlastActorApplyFracture: NULL commands pointer input.", return); - NVBLAST_CHECK(Nv::Blast::isValid(commands), logFn, "NvBlastActorApplyFracture: commands memory is NULL but size is > 0.", return); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorApplyFracture: NULL actor pointer input.", return); + NVBLASTLL_CHECK(commands != nullptr, logFn, "NvBlastActorApplyFracture: NULL commands pointer input.", return); + NVBLASTLL_CHECK(Nv::Blast::isValid(commands), logFn, "NvBlastActorApplyFracture: commands memory is NULL but size is > 0.", return); Nv::Blast::Actor& a = *static_cast<Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorApplyFracture: actor is not active."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorApplyFracture: actor is not active."); if (eventBuffers != nullptr) { eventBuffers->bondFractureCount = 0; @@ -1197,19 +865,19 @@ void NvBlastActorApplyFracture return; } - a.applyFracture(eventBuffers, commands, logFn, timers); + a.getFamilyHeader()->applyFracture(eventBuffers, commands, &a, logFn, timers); } size_t NvBlastActorGetRequiredScratchForSplit(const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetRequiredScratchForSplit: NULL actor input.", return 0); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetRequiredScratchForSplit: NULL actor input.", return 0); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetRequiredScratchForSplit: actor is not active."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetRequiredScratchForSplit: actor is not active."); return 0; } @@ -1219,13 +887,13 @@ size_t NvBlastActorGetRequiredScratchForSplit(const NvBlastActor* actor, NvBlast uint32_t NvBlastActorGetMaxActorCountForSplit(const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetMaxActorCountForSplit: NULL actor input.", return 0); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetMaxActorCountForSplit: NULL actor input.", return 0); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetMaxActorCountForSplit: actor is not active."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetMaxActorCountForSplit: actor is not active."); return 0; } @@ -1243,16 +911,16 @@ uint32_t NvBlastActorSplit NvBlastTimers* timers ) { - NVBLAST_CHECK(result != nullptr, logFn, "NvBlastActorSplit: NULL result pointer input.", return 0); - NVBLAST_CHECK(newActorsMaxCount > 0 && result->newActors != nullptr, logFn, "NvBlastActorSplit: no space for results provided.", return 0); - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorSplit: NULL actor pointer input.", return 0); - NVBLAST_CHECK(scratch != nullptr, logFn, "NvBlastActorSplit: NULL scratch pointer input.", return 0); + NVBLASTLL_CHECK(result != nullptr, logFn, "NvBlastActorSplit: NULL result pointer input.", return 0); + NVBLASTLL_CHECK(newActorsMaxCount > 0 && result->newActors != nullptr, logFn, "NvBlastActorSplit: no space for results provided.", return 0); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorSplit: NULL actor pointer input.", return 0); + NVBLASTLL_CHECK(scratch != nullptr, logFn, "NvBlastActorSplit: NULL scratch pointer input.", return 0); Nv::Blast::Actor& a = *static_cast<Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetIndex: actor is not active."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetIndex: actor is not active."); return 0; } @@ -1262,13 +930,13 @@ uint32_t NvBlastActorSplit bool NvBlastActorCanFracture(const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorCanFracture: NULL actor input.", return false); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorCanFracture: NULL actor input.", return false); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorCanFracture: actor is not active."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorCanFracture: actor is not active."); return false; } @@ -1287,30 +955,25 @@ bool NvBlastActorCanFracture(const NvBlastActor* actor, NvBlastLog logFn) } -} // extern "C" +bool NvBlastActorIsBoundToWorld(const NvBlastActor* actor, NvBlastLog logFn) +{ + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorIsBoundToWorld: NULL actor input.", return false); + return static_cast<const Nv::Blast::Actor*>(actor)->isBoundToWorld(); +} -// deprecated API, still used in tests -uint32_t NvBlastActorClosestChunk(const float point[4], const NvBlastActor* actor, NvBlastLog logFn) + +bool NvBlastActorIsSplitRequired(const NvBlastActor* actor, NvBlastLog logFn) { - const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorIsSplitRequired: NULL actor input.", return false); - if (a.isSubSupportChunk()) + const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); + if (!a.isActive()) { - NVBLAST_LOG_WARNING(logFn, "NvBlastActorClosestChunk: not a graph actor."); - return Nv::Blast::invalidIndex<uint32_t>(); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorIsSplitRequired: actor is not active."); + return false; } - - uint32_t closestNode = Nv::Blast::findNodeByPositionLinked( - point, - a.getFirstGraphNodeIndex(), - a.getFamilyHeader()->getGraphNodeIndexLinks(), - a.getAsset()->m_graph.getAdjacencyPartition(), - a.getAsset()->m_graph.getAdjacentNodeIndices(), - a.getAsset()->m_graph.getAdjacentBondIndices(), - a.getAsset()->getBonds(), - a.getFamilyHeader()->getBondHealths() - ); - - return a.getAsset()->m_graph.getChunkIndices()[closestNode]; + return a.isSplitRequired(); } + +} // extern "C" diff --git a/sdk/lowlevel/source/NvBlastActor.h b/sdk/lowlevel/source/NvBlastActor.h index 42879e7..7e30660 100644 --- a/sdk/lowlevel/source/NvBlastActor.h +++ b/sdk/lowlevel/source/NvBlastActor.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTACTOR_H #define NVBLASTACTOR_H @@ -16,6 +34,8 @@ #include "NvBlastDLink.h" #include "NvBlastIteratorBase.h" #include "NvBlastSupportGraph.h" +#include "NvBlastFamilyGraph.h" +#include "NvBlastPreprocessorInternal.h" #include <cstring> @@ -309,6 +329,11 @@ public: //////// Damage and fracturing methods //////// /** + See NvBlastActorGenerateFracture + */ + void generateFracture(NvBlastFractureBuffers* commandBuffers, const NvBlastDamageProgram& program, const NvBlastProgramParams* programParams, NvBlastLog logFn, NvBlastTimers* timers) const; + + /** Damage bond between two chunks by health amount (instance graph also will be notified in case bond is broken after). */ uint32_t damageBond(uint32_t nodeIndex0, uint32_t nodeIndex1, float healthDamage); @@ -324,73 +349,6 @@ public: uint32_t damageBond(const NvBlastBondFractureData& cmd); /** - See NvBlastActorGenerateFracture - */ - void generateFracture(NvBlastFractureBuffers* commandBuffers, const NvBlastDamageProgram& program, const NvBlastProgramParams* programParams, NvBlastLog logFn, NvBlastTimers* timers) const; - - /** - Hierarchically distribute damage to child chunks. - - \param chunkIndex asset chunk index to hierarchically damage - \param suboffset index of the first sub-support health - \param healthDamage damage strength to apply - \param chunkHealths instance chunk healths - \param chunks asset chunk collection - */ - void fractureSubSupportNoEvents(uint32_t chunkIndex, uint32_t suboffset, float healthDamage, float* chunkHealths, const NvBlastChunk* chunks); - - /** - Hierarchically distribute damage to child chunks, recording a fracture event for each health damage applied. - - If outBuffer is too small, events are dropped but the chunks are still damaged. - - \param chunkIndex asset chunk index to hierarchically damage - \param suboffset index of the first sub-support health - \param healthDamage damage strength to apply - \param chunkHealths instance chunk healths - \param chunks asset chunk collection - \param outBuffer target buffer for fracture events - \param currentIndex current position in outBuffer - returns the number of damaged chunks - \param maxCount capacity of outBuffer - */ - void fractureSubSupport(uint32_t chunkIndex, uint32_t suboffset, float healthDamage, float* chunkHealths, const NvBlastChunk* chunks, NvBlastChunkFractureData* outBuffer, uint32_t* currentIndex, const uint32_t maxCount); - - /** - Apply chunk fracture commands hierarchically. - - \param chunkFractureCount number of chunk fracture commands to apply - \param chunkFractures array of chunk fracture commands - */ - void fractureNoEvents(uint32_t chunkFractureCount, const NvBlastChunkFractureData* chunkFractures); - - /** - Apply chunk fracture commands hierarchically, recording a fracture event for each health damage applied. - - If events array is too small, events are dropped but the chunks are still damaged. - - \param chunkFractureCount number of chunk fracture commands to apply - \param commands array of chunk fracture commands - \param events target buffer for fracture events - \param eventsSize number of available entries in 'events' - \param count returns the number of damaged chunks - */ - void fractureWithEvents(uint32_t chunkFractureCount, const NvBlastChunkFractureData* commands, NvBlastChunkFractureData* events, uint32_t eventsSize, uint32_t* count); - - /** - Apply chunk fracture commands hierarchically, recording a fracture event for each health damage applied. - - In-Place version: fracture commands are replaced by fracture events. - - If inoutbuffer array is too small, events are dropped but the chunks are still damaged. - - \param chunkFractureCount number of chunk fracture commands to apply - \param inoutbuffer array of chunk fracture commands to be replaced by events - \param eventsSize number of available entries in inoutbuffer - \param count returns the number of damaged chunks - */ - void fractureInPlaceEvents(uint32_t chunkFractureCount, NvBlastChunkFractureData* inoutbuffer, uint32_t eventsSize, uint32_t* count); - - /** See NvBlastActorApplyFracture */ void applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands, NvBlastLog logFn, NvBlastTimers* timers); @@ -473,6 +431,16 @@ public: */ uint32_t partitionMultipleGraphNodes(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn); + /** + \return true iff this actor contains the "world" support graph node, created when a bond contains the invalidIndex<uint32_t>() value for one of their chunkIndices. + */ + bool isBoundToWorld() const; + + /** + \return true iff this actor was damaged and split() call is required. + */ + bool isSplitRequired() const; + private: //////// Data //////// @@ -695,7 +663,7 @@ NV_INLINE bool Actor::release() NV_INLINE uint32_t Actor::partition(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn) { - NVBLAST_CHECK(newActorsSize == 0 || newActors != nullptr, logFn, "Nv::Blast::Actor::partition: NULL newActors pointer array input with non-zero newActorCount.", return 0); + NVBLASTLL_CHECK(newActorsSize == 0 || newActors != nullptr, logFn, "Nv::Blast::Actor::partition: NULL newActors pointer array input with non-zero newActorCount.", return 0); // Call one of two partition functions depending on the actor's support status return m_graphNodeCount <= 1 ? @@ -704,6 +672,58 @@ NV_INLINE uint32_t Actor::partition(Actor** newActors, uint32_t newActorsSize, N } +NV_INLINE bool Actor::isBoundToWorld() const +{ + const SupportGraph& graph = *getGraph(); + + if (graph.m_nodeCount == 0) + { + return false; // This shouldn't happen + } + + const uint32_t lastGraphChunkIndex = graph.getChunkIndices()[graph.m_nodeCount - 1]; + + if (!isInvalidIndex(lastGraphChunkIndex)) + { + return false; // There is no world node + } + + return getFamilyGraph()->getIslandIds()[graph.m_nodeCount - 1] == getIndex(); +} + + +NV_INLINE bool Actor::isSplitRequired() const +{ + NVBLAST_ASSERT(isActive()); + + if (getGraphNodeCount() <= 1) + { + uint32_t chunkHealthIndex = isSingleSupportChunk() ? getIndex() : getFirstVisibleChunkIndex() - getFirstSubsupportChunkIndex() + getGraph()->m_nodeCount; + float* chunkHealths = getLowerSupportChunkHealths(); + if (chunkHealths[chunkHealthIndex] <= 0.0f) + { + const uint32_t chunkIndex = m_graphNodeCount == 0 ? m_firstVisibleChunkIndex : getGraph()->getChunkIndices()[m_firstGraphNodeIndex]; + if (!isInvalidIndex(chunkIndex)) + { + const NvBlastChunk& chunk = getChunks()[chunkIndex]; + uint32_t childCount = chunk.childIndexStop - chunk.firstChildIndex; + return childCount > 0; + } + } + } + else + { + uint32_t* firstDirtyNodeIndices = getFamilyGraph()->getFirstDirtyNodeIndices(); + if (!isInvalidIndex(firstDirtyNodeIndices[getIndex()])) + { + return true; + } + + } + return false; +} + + //////// Actor::VisibleChunkIt inline methods //////// NV_INLINE Actor::VisibleChunkIt::VisibleChunkIt(const Actor& actor) : DListIt<uint32_t>(actor.m_firstVisibleChunkIndex, actor.getFamilyHeader()->getVisibleChunkIndexLinks()) @@ -717,16 +737,28 @@ NV_INLINE Actor::GraphNodeIt::GraphNodeIt(const Actor& actor) : LListIt<uint32_t { } -} // namespace Blast -} // namespace Nv +//////// Helper functions //////// +#if NVBLASTLL_CHECK_PARAMS /** -Returns the closest chunk asset index for a supported actor. -Helper functions still used in tests. -Has become obsolete with introduction of chunkMap and its inverse. +Helper function to validate fracture buffer values being meaningful. */ -uint32_t NvBlastActorClosestChunk(const float point[4], const NvBlastActor* actor, NvBlastLog logFn); +static inline bool isValid(const NvBlastFractureBuffers* buffers) +{ + if (buffers->chunkFractureCount != 0 && buffers->chunkFractures == nullptr) + return false; + + if (buffers->bondFractureCount != 0 && buffers->bondFractures == nullptr) + return false; + + return true; +} +#endif + + +} // namespace Blast +} // namespace Nv #endif // ifndef NVBLASTACTOR_H diff --git a/sdk/lowlevel/source/NvBlastActorSerializationBlock.cpp b/sdk/lowlevel/source/NvBlastActorSerializationBlock.cpp index e496a69..ca830a7 100644 --- a/sdk/lowlevel/source/NvBlastActorSerializationBlock.cpp +++ b/sdk/lowlevel/source/NvBlastActorSerializationBlock.cpp @@ -1,12 +1,29 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. #include "NvBlastActor.h" @@ -25,18 +42,18 @@ namespace Blast Actor* Actor::deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "Actor::deserialize: NULL family pointer input.", return nullptr); + NVBLASTLL_CHECK(family != nullptr, logFn, "Actor::deserialize: NULL family pointer input.", return nullptr); const ActorSerializationHeader* serHeader = reinterpret_cast<const ActorSerializationHeader*>(buffer); if (serHeader->m_formatVersion != ActorSerializationFormat::Current) { - NVBLAST_LOG_ERROR(logFn, "Actor::deserialize: wrong data format. Serialization data must be converted to current version."); + NVBLASTLL_LOG_ERROR(logFn, "Actor::deserialize: wrong data format. Serialization data must be converted to current version."); return nullptr; } FamilyHeader* header = reinterpret_cast<FamilyHeader*>(family); const Asset* asset = header->m_asset; - const Nv::Blast::SupportGraph& graph = asset->m_graph; + const SupportGraph& graph = asset->m_graph; const uint32_t* graphChunkIndices = graph.getChunkIndices(); const uint32_t* graphAdjacencyPartition = graph.getAdjacencyPartition(); const uint32_t* graphAdjacentNodeIndices = graph.getAdjacentNodeIndices(); @@ -55,7 +72,7 @@ Actor* Actor::deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog if (actor == nullptr) { - NVBLAST_LOG_ERROR(logFn, "Actor::deserialize: invalid actor index in serialized data. Actor not created."); + NVBLASTLL_LOG_ERROR(logFn, "Actor::deserialize: invalid actor index in serialized data. Actor not created."); return nullptr; } @@ -63,7 +80,7 @@ Actor* Actor::deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog uint32_t* chunkActorIndices = header->getChunkActorIndices(); FamilyGraph* familyGraph = header->getFamilyGraph(); -#if NVBLAST_CHECK_PARAMS +#if NVBLASTLL_CHECK_PARAMS { const uint32_t* serVisibleChunkIndices = serHeader->getVisibleChunkIndices(); for (uint32_t i = 0; i < serHeader->m_visibleChunkCount; ++i) @@ -71,7 +88,7 @@ Actor* Actor::deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog const uint32_t visibleChunkIndex = serVisibleChunkIndices[i]; if (!isInvalidIndex(chunkActorIndices[visibleChunkIndex])) { - NVBLAST_LOG_ERROR(logFn, "Actor::deserialize: visible chunk already has an actor in family. Actor not created."); + NVBLASTLL_LOG_ERROR(logFn, "Actor::deserialize: visible chunk already has an actor in family. Actor not created."); header->returnActor(*actor); return nullptr; } @@ -125,7 +142,7 @@ Actor* Actor::deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog { uint32_t serLowerSupportChunkCount = 0; float* graphNodeHealths = header->getLowerSupportChunkHealths(); - for (Nv::Blast::Actor::GraphNodeIt i = *actor; (bool)i; ++i) + for (Actor::GraphNodeIt i = *actor; (bool)i; ++i) { const uint32_t graphNodeIndex = (uint32_t)i; graphNodeHealths[graphNodeIndex] = serLowerSupportChunkHealths[serLowerSupportChunkCount++]; @@ -152,7 +169,7 @@ Actor* Actor::deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog { const float* serBondHealths = serHeader->getBondHealths(); float* bondHealths = header->getBondHealths(); - for (Nv::Blast::Actor::GraphNodeIt i = *actor; (bool)i; ++i) + for (Actor::GraphNodeIt i = *actor; (bool)i; ++i) { const uint32_t graphNodeIndex = (uint32_t)i; for (uint32_t adjacentIndex = graphAdjacencyPartition[graphNodeIndex]; adjacentIndex < graphAdjacencyPartition[graphNodeIndex + 1]; ++adjacentIndex) @@ -176,7 +193,7 @@ Actor* Actor::deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog { const uint32_t* serFastRoute = serHeader->getFastRoute(); uint32_t* fastRoute = header->getFamilyGraph()->getFastRoute(); - for (Nv::Blast::Actor::GraphNodeIt i = *actor; (bool)i; ++i) + for (Actor::GraphNodeIt i = *actor; (bool)i; ++i) { fastRoute[(uint32_t)i] = *serFastRoute++; } @@ -186,7 +203,7 @@ Actor* Actor::deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog { const uint32_t* serHopCounts = serHeader->getHopCounts(); uint32_t* hopCounts = header->getFamilyGraph()->getHopCounts(); - for (Nv::Blast::Actor::GraphNodeIt i = *actor; (bool)i; ++i) + for (Actor::GraphNodeIt i = *actor; (bool)i; ++i) { hopCounts[(uint32_t)i] = *serHopCounts++; } @@ -198,7 +215,7 @@ Actor* Actor::deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog uint32_t serBondIndex = 0; const FixedBoolArray* serEdgeRemovedArray = serHeader->getEdgeRemovedArray(); FixedBoolArray* edgeRemovedArray = familyGraph->getIsEdgeRemoved(); - for (Nv::Blast::Actor::GraphNodeIt i = *actor; (bool)i; ++i) + for (Actor::GraphNodeIt i = *actor; (bool)i; ++i) { const uint32_t graphNodeIndex = (uint32_t)i; for (uint32_t adjacentIndex = graphAdjacencyPartition[graphNodeIndex]; adjacentIndex < graphAdjacencyPartition[graphNodeIndex + 1]; ++adjacentIndex) @@ -232,7 +249,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c { // Set up pointers and such const Asset* asset = getAsset(); - const Nv::Blast::SupportGraph& graph = asset->m_graph; + const SupportGraph& graph = asset->m_graph; const uint32_t* graphChunkIndices = graph.getChunkIndices(); const uint32_t* graphAdjacencyPartition = graph.getAdjacencyPartition(); const uint32_t* graphAdjacentNodeIndices = graph.getAdjacentNodeIndices(); @@ -247,7 +264,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c const uint32_t* firstDirtyNodeIndices = header->getFamilyGraph()->getFirstDirtyNodeIndices(); if (!isInvalidIndex(firstDirtyNodeIndices[thisActorIndex])) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: instance graph has dirty nodes. Call Nv::Blast::Actor::findIslands before serializing."); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: instance graph has dirty nodes. Call Nv::Blast::Actor::findIslands before serializing."); return 0; } } @@ -274,12 +291,12 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c offset = align16(offset + m_visibleChunkCount*sizeof(uint32_t)); if (offset > bufferSize) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::Actor::serialize: buffer size exceeded."); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::Actor::serialize: buffer size exceeded."); return 0; // Buffer size insufficient } uint32_t* serVisibleChunkIndices = serHeader->getVisibleChunkIndices(); uint32_t serVisibleChunkCount = 0; - for (Nv::Blast::Actor::VisibleChunkIt i = *this; (bool)i; ++i) + for (Actor::VisibleChunkIt i = *this; (bool)i; ++i) { NVBLAST_ASSERT(serVisibleChunkCount < m_visibleChunkCount); serVisibleChunkIndices[serVisibleChunkCount++] = (uint32_t)i; @@ -293,12 +310,12 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c offset = align16(offset + m_graphNodeCount*sizeof(uint32_t)); if (offset > bufferSize) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); return 0; // Buffer size insufficient } uint32_t* serGraphNodeIndices = serHeader->getGraphNodeIndices(); uint32_t serGraphNodeCount = 0; - for (Nv::Blast::Actor::GraphNodeIt i = *this; (bool)i; ++i) + for (Actor::GraphNodeIt i = *this; (bool)i; ++i) { NVBLAST_ASSERT(serGraphNodeCount < m_graphNodeCount); serGraphNodeIndices[serGraphNodeCount++] = (uint32_t)i; @@ -316,7 +333,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c { uint32_t serLowerSupportChunkCount = 0; const float* graphNodeHealths = header->getLowerSupportChunkHealths(); - for (Nv::Blast::Actor::GraphNodeIt i = *this; (bool)i; ++i) + for (Actor::GraphNodeIt i = *this; (bool)i; ++i) { const uint32_t graphNodeIndex = (uint32_t)i; serLowerSupportChunkHealths[serLowerSupportChunkCount++] = graphNodeHealths[graphNodeIndex]; @@ -329,7 +346,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c { if (offset >= bufferSize) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); return 0; // Buffer size insufficient } serLowerSupportChunkHealths[serLowerSupportChunkCount++] = subsupportHealths[(uint32_t)j - subsupportChunkCount]; @@ -343,7 +360,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c NVBLAST_ASSERT(m_firstVisibleChunkIndex >= subsupportChunkCount); if (offset >= bufferSize) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); return 0; // Buffer size insufficient } *serLowerSupportChunkHealths = subsupportHealths[m_firstVisibleChunkIndex - subsupportChunkCount]; @@ -358,7 +375,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c serHeader->m_bondHealthsOffset = (uint32_t)offset; float* serBondHealths = serHeader->getBondHealths(); const float* bondHealths = header->getBondHealths(); - for (Nv::Blast::Actor::GraphNodeIt i = *this; (bool)i; ++i) + for (Actor::GraphNodeIt i = *this; (bool)i; ++i) { const uint32_t graphNodeIndex = (uint32_t)i; for (uint32_t adjacentIndex = graphAdjacencyPartition[graphNodeIndex]; adjacentIndex < graphAdjacencyPartition[graphNodeIndex + 1]; ++adjacentIndex) @@ -372,7 +389,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c { if (offset >= bufferSize) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); return 0; // Buffer size insufficient } const uint32_t adjacentBondIndex = graphAdjacentBondIndices[adjacentIndex]; @@ -391,12 +408,12 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c offset = align16(offset + m_graphNodeCount*sizeof(uint32_t)); if (offset > bufferSize) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); return 0; // Buffer size insufficient } uint32_t* serFastRoute = serHeader->getFastRoute(); const uint32_t* fastRoute = header->getFamilyGraph()->getFastRoute(); - for (Nv::Blast::Actor::GraphNodeIt i = *this; (bool)i; ++i) + for (Actor::GraphNodeIt i = *this; (bool)i; ++i) { *serFastRoute++ = fastRoute[(uint32_t)i]; } @@ -408,12 +425,12 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c offset = align16(offset + m_graphNodeCount*sizeof(uint32_t)); if (offset > bufferSize) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); return 0; // Buffer size insufficient } uint32_t* serHopCounts = serHeader->getHopCounts(); const uint32_t* hopCounts = header->getFamilyGraph()->getHopCounts(); - for (Nv::Blast::Actor::GraphNodeIt i = *this; (bool)i; ++i) + for (Actor::GraphNodeIt i = *this; (bool)i; ++i) { *serHopCounts++ = hopCounts[(uint32_t)i]; } @@ -426,7 +443,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c offset = align16(offset + FixedBoolArray::requiredMemorySize(serBondCount)); if (offset > bufferSize) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::serialize: buffer size exceeded."); return 0; // Buffer size insufficient } uint32_t serBondIndex = 0; @@ -434,7 +451,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c new (serEdgeRemovedArray)FixedBoolArray(serBondCount); serEdgeRemovedArray->fill(); // Reset bits as we find bonds const FixedBoolArray* edgeRemovedArray = header->getFamilyGraph()->getIsEdgeRemoved(); - for (Nv::Blast::Actor::GraphNodeIt i = *this; (bool)i; ++i) + for (Actor::GraphNodeIt i = *this; (bool)i; ++i) { const uint32_t graphNodeIndex = (uint32_t)i; for (uint32_t adjacentIndex = graphAdjacencyPartition[graphNodeIndex]; adjacentIndex < graphAdjacencyPartition[graphNodeIndex + 1]; ++adjacentIndex) @@ -468,7 +485,7 @@ uint32_t Actor::serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) c uint32_t Actor::serializationRequiredStorage(NvBlastLog logFn) const { const Asset* asset = getAsset(); - const Nv::Blast::SupportGraph& graph = asset->m_graph; + const SupportGraph& graph = asset->m_graph; const uint32_t* graphChunkIndices = graph.getChunkIndices(); const uint32_t* graphAdjacencyPartition = graph.getAdjacencyPartition(); const uint32_t* graphAdjacentNodeIndices = graph.getAdjacentNodeIndices(); @@ -515,7 +532,7 @@ uint32_t Actor::serializationRequiredStorage(NvBlastLog logFn) const if (dataSize > UINT32_MAX) { - NVBLAST_LOG_WARNING(logFn, "Nv::Blast::Actor::serializationRequiredStorage: Serialization block size exceeds 4GB. Returning 0.\n"); + NVBLASTLL_LOG_WARNING(logFn, "Nv::Blast::Actor::serializationRequiredStorage: Serialization block size exceeds 4GB. Returning 0.\n"); return 0; } @@ -533,13 +550,13 @@ extern "C" uint32_t NvBlastActorGetSerializationSize(const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorGetSerializationSize: NULL actor pointer input.", return 0); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorGetSerializationSize: NULL actor pointer input.", return 0); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorGetSerializationSize: inactive actor pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorGetSerializationSize: inactive actor pointer input."); return 0; } @@ -549,14 +566,14 @@ uint32_t NvBlastActorGetSerializationSize(const NvBlastActor* actor, NvBlastLog uint32_t NvBlastActorSerialize(void* buffer, uint32_t bufferSize, const NvBlastActor* actor, NvBlastLog logFn) { - NVBLAST_CHECK(buffer != nullptr, logFn, "NvBlastActorSerialize: NULL buffer pointer input.", return 0); - NVBLAST_CHECK(actor != nullptr, logFn, "NvBlastActorSerialize: NULL actor pointer input.", return 0); + NVBLASTLL_CHECK(buffer != nullptr, logFn, "NvBlastActorSerialize: NULL buffer pointer input.", return 0); + NVBLASTLL_CHECK(actor != nullptr, logFn, "NvBlastActorSerialize: NULL actor pointer input.", return 0); const Nv::Blast::Actor& a = *static_cast<const Nv::Blast::Actor*>(actor); if (!a.isActive()) { - NVBLAST_LOG_ERROR(logFn, "NvBlastActorSerialize: inactive actor pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastActorSerialize: inactive actor pointer input."); return 0; } @@ -566,8 +583,8 @@ uint32_t NvBlastActorSerialize(void* buffer, uint32_t bufferSize, const NvBlastA NvBlastActor* NvBlastFamilyDeserializeActor(NvBlastFamily* family, const void* buffer, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyDeserializeActor: NULL family input. No actor deserialized.", return nullptr); - NVBLAST_CHECK(buffer != nullptr, logFn, "NvBlastFamilyDeserializeActor: NULL buffer pointer input. No actor deserialized.", return nullptr); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyDeserializeActor: NULL family input. No actor deserialized.", return nullptr); + NVBLASTLL_CHECK(buffer != nullptr, logFn, "NvBlastFamilyDeserializeActor: NULL buffer pointer input. No actor deserialized.", return nullptr); return Nv::Blast::Actor::deserialize(family, buffer, logFn); } diff --git a/sdk/lowlevel/source/NvBlastActorSerializationBlock.h b/sdk/lowlevel/source/NvBlastActorSerializationBlock.h index 1388a74..95e9842 100644 --- a/sdk/lowlevel/source/NvBlastActorSerializationBlock.h +++ b/sdk/lowlevel/source/NvBlastActorSerializationBlock.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTACTORSERIALIZATIONBLOCK_H #define NVBLASTACTORSERIALIZATIONBLOCK_H diff --git a/sdk/lowlevel/source/NvBlastAsset.cpp b/sdk/lowlevel/source/NvBlastAsset.cpp index 29fc6b0..354a3ac 100644 --- a/sdk/lowlevel/source/NvBlastAsset.cpp +++ b/sdk/lowlevel/source/NvBlastAsset.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastAssert.h" #include "NvBlastAsset.h" @@ -36,37 +54,37 @@ static bool solverAssetBuildValidateInput(void* mem, const NvBlastAssetDesc* des { if (mem == nullptr) { - NVBLAST_LOG_ERROR(logFn, "AssetBuildValidateInput: NULL mem pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "AssetBuildValidateInput: NULL mem pointer input."); return false; } if (desc == nullptr) { - NVBLAST_LOG_ERROR(logFn, "AssetBuildValidateInput: NULL desc pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "AssetBuildValidateInput: NULL desc pointer input."); return false; } if (desc->chunkCount == 0) { - NVBLAST_LOG_ERROR(logFn, "AssetBuildValidateInput: Zero chunk count not allowed."); + NVBLASTLL_LOG_ERROR(logFn, "AssetBuildValidateInput: Zero chunk count not allowed."); return false; } if (desc->chunkDescs == nullptr) { - NVBLAST_LOG_ERROR(logFn, "AssetBuildValidateInput: NULL chunkDescs pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "AssetBuildValidateInput: NULL chunkDescs pointer input."); return false; } if (desc->bondCount != 0 && desc->bondDescs == nullptr) { - NVBLAST_LOG_ERROR(logFn, "AssetBuildValidateInput: bondCount non-zero but NULL bondDescs pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "AssetBuildValidateInput: bondCount non-zero but NULL bondDescs pointer input."); return false; } if (scratch == nullptr) { - NVBLAST_LOG_ERROR(logFn, "AssetBuildValidateInput: NULL scratch pointer input."); + NVBLASTLL_LOG_ERROR(logFn, "AssetBuildValidateInput: NULL scratch pointer input."); return false; } @@ -111,7 +129,7 @@ Asset* initializeAsset(void* mem, NvBlastID id, uint32_t chunkCount, uint32_t gr // Restricting our data size to < 4GB so that we may use uint32_t offsets if (dataSize > (size_t)UINT32_MAX) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::allocateAsset: Asset data size will exceed 4GB. Instance not created.\n"); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::allocateAsset: Asset data size will exceed 4GB. Instance not created.\n"); return nullptr; } @@ -121,7 +139,7 @@ Asset* initializeAsset(void* mem, NvBlastID id, uint32_t chunkCount, uint32_t gr // Fill in fields const size_t graphOffset = NV_OFFSET_OF(Asset, m_graph); asset->m_header.dataType = NvBlastDataBlock::AssetDataBlock; - asset->m_header.formatVersion = NvBlastAssetDataFormat::Current; + asset->m_header.formatVersion = 0; // Not currently using this field asset->m_header.size = (uint32_t)dataSize; asset->m_header.reserved = 0; asset->m_ID = id; @@ -223,7 +241,7 @@ static bool testForValidTrees(uint32_t chunkCount, const NvBlastChunkDesc* chunk // Ensure there are no loops if (testForLoop(chunkDescs, i)) { - NVBLAST_LOG_WARNING(logFn, "testForValidTrees: loop found. Asset will not be created."); + NVBLASTLL_LOG_WARNING(logFn, "testForValidTrees: loop found. Asset will not be created."); return false; } } @@ -255,7 +273,7 @@ class BondsOrdered public: bool operator () (const BondSortData& bond0, const BondSortData& bond1) const { - return (bond0.m_c0 != bond1.m_c0) ? (bond0.m_c0 < bond1.m_c0) : (bond0.m_c1 < bond1.m_c1); + return (bond0.m_c0 != bond1.m_c0) ? (bond0.m_c0 < bond1.m_c0) : (bond0.m_c1 != bond1.m_c1 ? bond0.m_c1 < bond1.m_c1 : bond0.m_b < bond1.m_b); } }; @@ -273,6 +291,19 @@ size_t Asset::getMemorySize(const NvBlastAssetDesc* desc) graphNodeCount += (uint32_t)((desc->chunkDescs[i].flags & NvBlastChunkDesc::SupportFlag) != 0); } + for (uint32_t i = 0; i < desc->bondCount; ++i) + { + const NvBlastBondDesc& bondDesc = desc->bondDescs[i]; + const uint32_t chunkIndex0 = bondDesc.chunkIndices[0]; + const uint32_t chunkIndex1 = bondDesc.chunkIndices[1]; + if ((isInvalidIndex(chunkIndex0) && chunkIndex1 < desc->chunkCount) || + (isInvalidIndex(chunkIndex1) && chunkIndex0 < desc->chunkCount)) + { + ++graphNodeCount; // world node + break; + } + } + AssetDataOffsets offsets; return createAssetDataOffsets(offsets, desc->chunkCount, graphNodeCount, desc->bondCount); } @@ -280,7 +311,7 @@ size_t Asset::getMemorySize(const NvBlastAssetDesc* desc) size_t Asset::createRequiredScratch(const NvBlastAssetDesc* desc) { -#if NVBLAST_CHECK_PARAMS +#if NVBLASTLL_CHECK_PARAMS if (desc == nullptr) { NVBLAST_ALWAYS_ASSERT(); @@ -292,14 +323,14 @@ size_t Asset::createRequiredScratch(const NvBlastAssetDesc* desc) return 16 + align16(desc->chunkCount*sizeof(char)) + align16(desc->chunkCount*sizeof(uint32_t)) + - align16(2 * desc->bondCount*sizeof(Nv::Blast::BondSortData)) + + align16(2 * desc->bondCount*sizeof(BondSortData)) + align16(desc->bondCount*sizeof(uint32_t)); } Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvBlastLog logFn) { -#if NVBLAST_CHECK_PARAMS +#if NVBLASTLL_CHECK_PARAMS if (!solverAssetBuildValidateInput(mem, desc, scratch, logFn)) { return nullptr; @@ -308,7 +339,7 @@ Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvB NV_UNUSED(solverAssetBuildValidateInput); #endif - NVBLAST_CHECK((reinterpret_cast<uintptr_t>(mem) & 0xF) == 0, logFn, "NvBlastCreateAsset: mem pointer not 16-byte aligned.", return nullptr); + NVBLASTLL_CHECK((reinterpret_cast<uintptr_t>(mem) & 0xF) == 0, logFn, "NvBlastCreateAsset: mem pointer not 16-byte aligned.", return nullptr); // Make sure we have valid trees before proceeding if (!testForValidTrees(desc->chunkCount, desc->chunkDescs, logFn)) @@ -319,20 +350,21 @@ Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvB scratch = (void*)align16((size_t)scratch); // Bump to 16-byte alignment (see padding in NvBlastGetRequiredScratchForCreateAsset) // reserve chunkAnnotation on scratch - char* chunkAnnotation = reinterpret_cast<char*>(scratch); scratch = Nv::Blast::pointerOffset(scratch, align16(desc->chunkCount)); + char* chunkAnnotation = reinterpret_cast<char*>(scratch); scratch = pointerOffset(scratch, align16(desc->chunkCount)); // test for coverage, chunkAnnotation will be filled there. uint32_t leafChunkCount; uint32_t supportChunkCount; if (!ensureExactSupportCoverage(supportChunkCount, leafChunkCount, chunkAnnotation, desc->chunkCount, const_cast<NvBlastChunkDesc*>(desc->chunkDescs), true, logFn)) { + NVBLASTLL_LOG_ERROR(logFn, "NvBlastCreateAsset: support coverage is not exact. Asset will not be created. The Asset helper function NvBlastEnsureAssetExactSupportCoverage may be used to create exact coverage."); return nullptr; } // test for valid chunk order if (!testForValidChunkOrder(desc->chunkCount, desc->chunkDescs, chunkAnnotation, scratch)) { - NVBLAST_LOG_ERROR(logFn, "NvBlastCreateAsset: chunks order is invalid. Asset will not be created. Use Asset helper functions such as NvBlastBuildAssetDescChunkReorderMap to fix descriptor order."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastCreateAsset: chunks order is invalid. Asset will not be created. Use Asset helper functions such as NvBlastBuildAssetDescChunkReorderMap to fix descriptor order."); return nullptr; } @@ -348,7 +380,7 @@ Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvB } // Create map from global indices to graph node indices and initialize to invalid values - uint32_t* graphNodeIndexMap = (uint32_t*)scratch; scratch = Nv::Blast::pointerOffset(scratch, align16(desc->chunkCount * sizeof(uint32_t))); + uint32_t* graphNodeIndexMap = (uint32_t*)scratch; scratch = pointerOffset(scratch, align16(desc->chunkCount * sizeof(uint32_t))); memset(graphNodeIndexMap, 0xFF, desc->chunkCount*sizeof(uint32_t)); // Fill graphNodeIndexMap @@ -363,7 +395,7 @@ Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvB NVBLAST_ASSERT(graphNodeCount == supportChunkCount); // Scratch array for bond sorting, of size 2*desc->bondCount - Nv::Blast::BondSortData* bondSortArray = (Nv::Blast::BondSortData*)scratch; scratch = Nv::Blast::pointerOffset(scratch, align16(2 * desc->bondCount*sizeof(Nv::Blast::BondSortData))); + BondSortData* bondSortArray = (BondSortData*)scratch; scratch = pointerOffset(scratch, align16(2 * desc->bondCount*sizeof(BondSortData))); // Bond remapping array of size desc->bondCount uint32_t* bondMap = (uint32_t*)scratch; @@ -380,33 +412,56 @@ Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvB // Construct temp array of chunk index pairs and bond indices. This array is symmetrized to hold the reversed chunk indices as well. uint32_t bondSortArraySize = 0; - Nv::Blast::BondSortData* t = bondSortArray; + BondSortData* t = bondSortArray; + bool addWorldNode = false; for (uint32_t i = 0; i < desc->bondCount; ++i) { const NvBlastBondDesc& bondDesc = desc->bondDescs[i]; const uint32_t chunkIndex0 = bondDesc.chunkIndices[0]; const uint32_t chunkIndex1 = bondDesc.chunkIndices[1]; - if (chunkIndex0 >= desc->chunkCount || chunkIndex1 >= desc->chunkCount || chunkIndex0 == chunkIndex1) + if ((chunkIndex0 >= desc->chunkCount && !isInvalidIndex(chunkIndex0)) || + (chunkIndex1 >= desc->chunkCount && !isInvalidIndex(chunkIndex1)) || + chunkIndex0 == chunkIndex1) { invalidFound = true; continue; } - const uint32_t graphIndex0 = graphNodeIndexMap[chunkIndex0]; - const uint32_t graphIndex1 = graphNodeIndexMap[chunkIndex1]; - if (Nv::Blast::isInvalidIndex(graphIndex0) || Nv::Blast::isInvalidIndex(graphIndex1)) + uint32_t graphIndex0; + if (!isInvalidIndex(chunkIndex0)) + { + graphIndex0 = graphNodeIndexMap[chunkIndex0]; + } + else + { + addWorldNode = true; + graphIndex0 = graphNodeCount; // Will set graphNodeCount = supportChunkCount + 1 + } + + uint32_t graphIndex1; + if (!isInvalidIndex(chunkIndex1)) + { + graphIndex1 = graphNodeIndexMap[chunkIndex1]; + } + else + { + addWorldNode = true; + graphIndex1 = graphNodeCount; // Will set graphNodeCount = supportChunkCount + 1 + } + + if (isInvalidIndex(graphIndex0) || isInvalidIndex(graphIndex1)) { nonSupportFound = true; continue; } - t[bondSortArraySize++] = Nv::Blast::BondSortData(graphIndex0, graphIndex1, i); - t[bondSortArraySize++] = Nv::Blast::BondSortData(graphIndex1, graphIndex0, i); + t[bondSortArraySize++] = BondSortData(graphIndex0, graphIndex1, i); + t[bondSortArraySize++] = BondSortData(graphIndex1, graphIndex0, i); } // Sort the temp array - std::sort(bondSortArray, bondSortArray + bondSortArraySize, Nv::Blast::BondsOrdered()); + std::sort(bondSortArray, bondSortArray + bondSortArraySize, BondsOrdered()); uint32_t symmetrizedBondCount = 0; for (uint32_t i = 0; i < bondSortArraySize; ++i) @@ -426,48 +481,55 @@ Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvB bondCount = symmetrizedBondCount / 2; + // World node references found in bonds; add a world node + if (addWorldNode) + { + ++graphNodeCount; + } + // Report warnings if (invalidFound) { - NVBLAST_LOG_WARNING(logFn, "NvBlastCreateAsset: Invalid bonds found (non-existent or same chunks referenced) and removed from asset."); + NVBLASTLL_LOG_WARNING(logFn, "NvBlastCreateAsset: Invalid bonds found (non-existent or same chunks referenced) and removed from asset."); } if (duplicateFound) { - NVBLAST_LOG_WARNING(logFn, "NvBlastCreateAsset: Duplicate bonds found and removed from asset."); + NVBLASTLL_LOG_WARNING(logFn, "NvBlastCreateAsset: Duplicate bonds found and removed from asset."); } if (nonSupportFound) { - NVBLAST_LOG_WARNING(logFn, "NvBlastCreateAsset: Bonds referencing non-support chunks found and removed from asset."); + NVBLASTLL_LOG_WARNING(logFn, "NvBlastCreateAsset: Bonds referencing non-support chunks found and removed from asset."); } } // Allocate memory for asset NvBlastID id; memset(&id, 0, sizeof(NvBlastID)); // To do - create an actual id - Nv::Blast::Asset* asset = initializeAsset(mem, id, desc->chunkCount, supportChunkCount, leafChunkCount, firstSubsupportChunkIndex, bondCount, logFn); + Asset* asset = initializeAsset(mem, id, desc->chunkCount, graphNodeCount, leafChunkCount, firstSubsupportChunkIndex, bondCount, logFn); // Asset data pointers - Nv::Blast::SupportGraph& graph = asset->m_graph; + SupportGraph& graph = asset->m_graph; NvBlastChunk* chunks = asset->getChunks(); NvBlastBond* bonds = asset->getBonds(); uint32_t* subtreeLeafChunkCounts = asset->getSubtreeLeafChunkCounts(); // Create chunks uint32_t* graphChunkIndices = graph.getChunkIndices(); + memset(graphChunkIndices, 0xFF, graphNodeCount * sizeof(uint32_t)); // Ensures unmapped node indices go to invalidIndex - this is important for the world node, if added for (uint32_t i = 0; i < desc->chunkCount; ++i) { const NvBlastChunkDesc& chunkDesc = desc->chunkDescs[i]; - const uint32_t newChunkIndex = i; - NvBlastChunk& assetChunk = chunks[newChunkIndex]; + NvBlastChunk& assetChunk = chunks[i]; memcpy(assetChunk.centroid, chunkDesc.centroid, 3 * sizeof(float)); assetChunk.volume = chunkDesc.volume; - assetChunk.parentChunkIndex = Nv::Blast::isInvalidIndex(chunkDesc.parentChunkIndex) ? chunkDesc.parentChunkIndex : chunkDesc.parentChunkIndex; - assetChunk.firstChildIndex = Nv::Blast::invalidIndex<uint32_t>(); // Will be filled in below + assetChunk.parentChunkIndex = isInvalidIndex(chunkDesc.parentChunkIndex) ? chunkDesc.parentChunkIndex : chunkDesc.parentChunkIndex; + assetChunk.firstChildIndex = invalidIndex<uint32_t>(); // Will be filled in below assetChunk.childIndexStop = assetChunk.firstChildIndex; assetChunk.userData = chunkDesc.userData; - if (!Nv::Blast::isInvalidIndex(graphNodeIndexMap[newChunkIndex])) + const uint32_t graphNodeIndex = graphNodeIndexMap[i]; + if (!isInvalidIndex(graphNodeIndex)) { - graphChunkIndices[graphNodeIndexMap[newChunkIndex]] = newChunkIndex; + graphChunkIndices[graphNodeIndex] = i; } } @@ -478,7 +540,7 @@ Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvB for (uint32_t i = 0; i < desc->chunkCount; ++i) { const uint32_t parentChunkIndex = chunks[i].parentChunkIndex; - if (!Nv::Blast::isInvalidIndex(parentChunkIndex)) + if (!isInvalidIndex(parentChunkIndex)) { if (chunks[parentChunkIndex].childIndexStop == chunks[parentChunkIndex].firstChildIndex) { @@ -495,32 +557,22 @@ Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvB if (bondCount > 0) { // Create the lookup table from the sorted array - Nv::Blast::createIndexStartLookup<uint32_t>(graphAdjacencyPartition, 0, graphNodeCount - 1, &bondSortArray->m_c0, 2 * bondCount, sizeof(Nv::Blast::BondSortData)); + createIndexStartLookup<uint32_t>(graphAdjacencyPartition, 0, graphNodeCount - 1, &bondSortArray->m_c0, 2 * bondCount, sizeof(BondSortData)); // Write the adjacent chunk and bond index data uint32_t bondIndex = 0; for (uint32_t i = 0; i < 2 * bondCount; ++i) { - const Nv::Blast::BondSortData& bondSortData = bondSortArray[i]; + const BondSortData& bondSortData = bondSortArray[i]; graphAdjacentNodeIndices[i] = bondSortData.m_c1; const uint32_t oldBondIndex = bondSortData.m_b; const NvBlastBondDesc& bondDesc = desc->bondDescs[oldBondIndex]; - if (Nv::Blast::isInvalidIndex(bondMap[oldBondIndex])) + if (isInvalidIndex(bondMap[oldBondIndex])) { bonds[bondIndex] = bondDesc.bond; - // Our convention is that the bond normal points away from the lower-indexed chunk, towards the higher-indexed chunk. - // If our new (graph node) indexing would reverse this direction from the bond descriptor's indexing, we must flip the nomral. - const bool nodeIndicesOrdered = bondSortData.m_c0 < bondSortData.m_c1; - const bool descNodeIndicesOrdered = bondDesc.chunkIndices[0] < bondDesc.chunkIndices[1]; - if (descNodeIndicesOrdered && !nodeIndicesOrdered) - { - float* normal = bonds[bondIndex].normal; - normal[0] = -normal[0]; - normal[1] = -normal[1]; - normal[2] = -normal[2]; - } bondMap[oldBondIndex] = bondIndex++; } + NVBLAST_ASSERT(bondMap[oldBondIndex] < bondCount); graphAdjacentBondIndices[i] = bondMap[oldBondIndex]; } } @@ -535,7 +587,7 @@ Asset* Asset::create(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvB uint32_t* breadthFirstChunkIndices = graphNodeIndexMap; // Reusing graphNodeIndexMap ... graphNodeIndexMap may no longer be used for (uint32_t startChunkIndex = 0; startChunkIndex < desc->chunkCount; ++startChunkIndex) { - if (!Nv::Blast::isInvalidIndex(chunks[startChunkIndex].parentChunkIndex)) + if (!isInvalidIndex(chunks[startChunkIndex].parentChunkIndex)) { break; // Only iterate through root chunks at this level } @@ -637,7 +689,7 @@ bool Asset::ensureExactSupportCoverage(uint32_t& supportChunkCount, uint32_t& le if (redundantCoverage) { - NVBLAST_LOG_INFO(logFn, "NvBlastCreateAsset: some leaf-to-root chains had more than one support chunk. Some support chunks removed."); + NVBLASTLL_LOG_INFO(logFn, "NvBlastCreateAsset: some leaf-to-root chains had more than one support chunk. Some support chunks removed."); } if (insufficientCoverage) @@ -698,7 +750,7 @@ bool Asset::ensureExactSupportCoverage(uint32_t& supportChunkCount, uint32_t& le } } - NVBLAST_LOG_INFO(logFn, "NvBlastCreateAsset: some leaf-to-root chains had no support chunks. Support chunks added."); + NVBLASTLL_LOG_INFO(logFn, "NvBlastCreateAsset: some leaf-to-root chains had no support chunks. Support chunks added."); } // Apply changes and count the number of support chunks @@ -731,12 +783,12 @@ bool Asset::testForValidChunkOrder(uint32_t chunkCount, const NvBlastChunkDesc* const uint32_t parentChunkIndex = chunkDescs[i].parentChunkIndex; if (parentChunkIndex != currentParentChunkIndex) { - if (!Nv::Blast::isInvalidIndex(currentParentChunkIndex)) + if (!isInvalidIndex(currentParentChunkIndex)) { chunkMarks[currentParentChunkIndex] = 1; } currentParentChunkIndex = parentChunkIndex; - if (Nv::Blast::isInvalidIndex(currentParentChunkIndex)) + if (isInvalidIndex(currentParentChunkIndex)) { return false; } @@ -772,7 +824,7 @@ extern "C" size_t NvBlastGetRequiredScratchForCreateAsset(const NvBlastAssetDesc* desc, NvBlastLog logFn) { - NVBLAST_CHECK(desc != nullptr, logFn, "NvBlastGetRequiredScratchForCreateAsset: NULL desc pointer input.", return 0); + NVBLASTLL_CHECK(desc != nullptr, logFn, "NvBlastGetRequiredScratchForCreateAsset: NULL desc pointer input.", return 0); return Nv::Blast::Asset::createRequiredScratch(desc); } @@ -780,7 +832,7 @@ size_t NvBlastGetRequiredScratchForCreateAsset(const NvBlastAssetDesc* desc, NvB size_t NvBlastGetAssetMemorySize(const NvBlastAssetDesc* desc, NvBlastLog logFn) { - NVBLAST_CHECK(desc != nullptr, logFn, "NvBlastGetAssetMemorySize: NULL desc input.", return 0); + NVBLASTLL_CHECK(desc != nullptr, logFn, "NvBlastGetAssetMemorySize: NULL desc input.", return 0); return Nv::Blast::Asset::getMemorySize(desc); } @@ -794,7 +846,7 @@ NvBlastAsset* NvBlastCreateAsset(void* mem, const NvBlastAssetDesc* desc, void* size_t NvBlastAssetGetFamilyMemorySize(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetFamilyMemorySize: NULL asset pointer input.", return 0); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetFamilyMemorySize: NULL asset pointer input.", return 0); return Nv::Blast::getFamilyMemorySize(reinterpret_cast<const Nv::Blast::Asset*>(asset)); } @@ -802,7 +854,7 @@ size_t NvBlastAssetGetFamilyMemorySize(const NvBlastAsset* asset, NvBlastLog log NvBlastID NvBlastAssetGetID(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetID: NULL asset pointer input.", NvBlastID zero; memset(&zero, 0, sizeof(NvBlastID)); return zero); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetID: NULL asset pointer input.", NvBlastID zero; memset(&zero, 0, sizeof(NvBlastID)); return zero); return ((Nv::Blast::Asset*)asset)->m_ID; } @@ -810,8 +862,8 @@ NvBlastID NvBlastAssetGetID(const NvBlastAsset* asset, NvBlastLog logFn) bool NvBlastAssetSetID(NvBlastAsset* asset, const NvBlastID* id, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetSetID: NULL asset pointer input.", return false); - NVBLAST_CHECK(id != nullptr, logFn, "NvBlastAssetSetID: NULL id pointer input.", return false); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetSetID: NULL asset pointer input.", return false); + NVBLASTLL_CHECK(id != nullptr, logFn, "NvBlastAssetSetID: NULL id pointer input.", return false); ((Nv::Blast::Asset*)asset)->m_ID = *id; @@ -821,7 +873,7 @@ bool NvBlastAssetSetID(NvBlastAsset* asset, const NvBlastID* id, NvBlastLog logF uint32_t NvBlastAssetGetFormatVersion(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetFormatVersion: NULL asset input.", return UINT32_MAX); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetFormatVersion: NULL asset input.", return UINT32_MAX); return ((Nv::Blast::Asset*)asset)->m_header.formatVersion; } @@ -829,7 +881,7 @@ uint32_t NvBlastAssetGetFormatVersion(const NvBlastAsset* asset, NvBlastLog logF uint32_t NvBlastAssetGetSize(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetSize: NULL asset input.", return 0); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetSize: NULL asset input.", return 0); return ((Nv::Blast::Asset*)asset)->m_header.size; } @@ -837,15 +889,31 @@ uint32_t NvBlastAssetGetSize(const NvBlastAsset* asset, NvBlastLog logFn) uint32_t NvBlastAssetGetChunkCount(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetChunkCount: NULL asset input.", return 0); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetChunkCount: NULL asset input.", return 0); return ((Nv::Blast::Asset*)asset)->m_chunkCount; } +uint32_t NvBlastAssetGetSupportChunkCount(const NvBlastAsset* asset, NvBlastLog logFn) +{ + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetSupportChunkCount: NULL asset input.", return 0); + + const Nv::Blast::Asset* a = reinterpret_cast<const Nv::Blast::Asset*>(asset); + const Nv::Blast::SupportGraph& graph = a->m_graph; + + if (graph.m_nodeCount == 0) + { + return 0; // This shouldn't happen + } + + return Nv::Blast::isInvalidIndex(graph.getChunkIndices()[graph.m_nodeCount - 1]) ? graph.m_nodeCount - 1 : graph.m_nodeCount; +} + + uint32_t NvBlastAssetGetLeafChunkCount(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetLeafChunkCount: NULL asset input.", return 0); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetLeafChunkCount: NULL asset input.", return 0); return ((Nv::Blast::Asset*)asset)->m_leafChunkCount; } @@ -853,7 +921,7 @@ uint32_t NvBlastAssetGetLeafChunkCount(const NvBlastAsset* asset, NvBlastLog log uint32_t NvBlastAssetGetFirstSubsupportChunkIndex(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetFirstSubsupportChunkIndex: NULL asset input.", return 0); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetFirstSubsupportChunkIndex: NULL asset input.", return 0); return ((Nv::Blast::Asset*)asset)->m_firstSubsupportChunkIndex; } @@ -861,7 +929,7 @@ uint32_t NvBlastAssetGetFirstSubsupportChunkIndex(const NvBlastAsset* asset, NvB uint32_t NvBlastAssetGetBondCount(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetBondCount: NULL asset input.", return 0); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetBondCount: NULL asset input.", return 0); return ((Nv::Blast::Asset*)asset)->m_bondCount; } @@ -869,7 +937,7 @@ uint32_t NvBlastAssetGetBondCount(const NvBlastAsset* asset, NvBlastLog logFn) const NvBlastSupportGraph NvBlastAssetGetSupportGraph(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetSupportGraph: NULL asset input.", + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetSupportGraph: NULL asset input.", NvBlastSupportGraph blank; blank.nodeCount = 0; blank.chunkIndices = blank.adjacencyPartition = blank.adjacentNodeIndices = blank.adjacentBondIndices = nullptr; return blank); const Nv::Blast::SupportGraph& supportGraph = static_cast<const Nv::Blast::Asset*>(asset)->m_graph; @@ -887,7 +955,7 @@ const NvBlastSupportGraph NvBlastAssetGetSupportGraph(const NvBlastAsset* asset, const uint32_t* NvBlastAssetGetChunkToGraphNodeMap(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetChunkToGraphNodeMap: NULL asset input.", return nullptr); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetChunkToGraphNodeMap: NULL asset input.", return nullptr); return static_cast<const Nv::Blast::Asset*>(asset)->getChunkToGraphNodeMap(); } @@ -895,7 +963,7 @@ const uint32_t* NvBlastAssetGetChunkToGraphNodeMap(const NvBlastAsset* asset, Nv const NvBlastChunk* NvBlastAssetGetChunks(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetChunks: NULL asset input.", return 0); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetChunks: NULL asset input.", return 0); return ((Nv::Blast::Asset*)asset)->getChunks(); } @@ -903,7 +971,7 @@ const NvBlastChunk* NvBlastAssetGetChunks(const NvBlastAsset* asset, NvBlastLog const NvBlastBond* NvBlastAssetGetBonds(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetBonds: NULL asset input.", return 0); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetBonds: NULL asset input.", return 0); return ((Nv::Blast::Asset*)asset)->getBonds(); } @@ -911,7 +979,7 @@ const NvBlastBond* NvBlastAssetGetBonds(const NvBlastAsset* asset, NvBlastLog lo uint32_t NvBlastAssetGetActorSerializationSizeUpperBound(const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastAssetGetActorSerializationSizeUpperBound: NULL asset input.", return 0); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastAssetGetActorSerializationSizeUpperBound: NULL asset input.", return 0); const Nv::Blast::Asset& solverAsset = *(const Nv::Blast::Asset*)asset; const uint32_t graphNodeCount = solverAsset.m_graph.m_nodeCount; @@ -921,7 +989,7 @@ uint32_t NvBlastAssetGetActorSerializationSizeUpperBound(const NvBlastAsset* ass if (upperBound > UINT32_MAX) { - NVBLAST_LOG_WARNING(logFn, "NvBlastAssetGetActorSerializationSizeUpperBound: Serialization block size exceeds 4GB. Returning 0.\n"); + NVBLASTLL_LOG_WARNING(logFn, "NvBlastAssetGetActorSerializationSizeUpperBound: Serialization block size exceeds 4GB. Returning 0.\n"); return 0; } diff --git a/sdk/lowlevel/source/NvBlastAsset.h b/sdk/lowlevel/source/NvBlastAsset.h index 30e8161..65f8b43 100644 --- a/sdk/lowlevel/source/NvBlastAsset.h +++ b/sdk/lowlevel/source/NvBlastAsset.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTASSET_H #define NVBLASTASSET_H diff --git a/sdk/lowlevel/source/NvBlastAssetHelper.cpp b/sdk/lowlevel/source/NvBlastAssetHelper.cpp index 0d6c5d2..cc3d643 100644 --- a/sdk/lowlevel/source/NvBlastAssetHelper.cpp +++ b/sdk/lowlevel/source/NvBlastAssetHelper.cpp @@ -1,17 +1,37 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastAsset.h" #include "NvBlastIndexFns.h" #include "NvBlastAssert.h" #include "NvBlastMemory.h" +#include "NvBlastMath.h" +#include "NvBlastPreprocessorInternal.h" #include <algorithm> @@ -62,9 +82,9 @@ extern "C" bool NvBlastBuildAssetDescChunkReorderMap(uint32_t* chunkReorderMap, const NvBlastChunkDesc* chunkDescs, uint32_t chunkCount, void* scratch, NvBlastLog logFn) { - NVBLAST_CHECK(chunkCount == 0 || chunkDescs != nullptr, logFn, "NvBlastBuildAssetDescChunkReorderMap: NULL chunkDescs input with non-zero chunkCount", return false); - NVBLAST_CHECK(chunkReorderMap == nullptr || chunkCount != 0, logFn, "NvBlastBuildAssetDescChunkReorderMap: NULL chunkReorderMap input with non-zero chunkCount", return false); - NVBLAST_CHECK(chunkCount == 0 || scratch != nullptr, logFn, "NvBlastBuildAssetDescChunkReorderMap: NULL scratch input with non-zero chunkCount", return false); + NVBLASTLL_CHECK(chunkCount == 0 || chunkDescs != nullptr, logFn, "NvBlastBuildAssetDescChunkReorderMap: NULL chunkDescs input with non-zero chunkCount", return false); + NVBLASTLL_CHECK(chunkReorderMap == nullptr || chunkCount != 0, logFn, "NvBlastBuildAssetDescChunkReorderMap: NULL chunkReorderMap input with non-zero chunkCount", return false); + NVBLASTLL_CHECK(chunkCount == 0 || scratch != nullptr, logFn, "NvBlastBuildAssetDescChunkReorderMap: NULL scratch input with non-zero chunkCount", return false); uint32_t* chunkMap = static_cast<uint32_t*>(scratch); scratch = pointerOffset(scratch, chunkCount * sizeof(uint32_t)); char* chunkAnnotation = static_cast<char*>(scratch); scratch = pointerOffset(scratch, chunkCount * sizeof(char)); @@ -73,7 +93,7 @@ bool NvBlastBuildAssetDescChunkReorderMap(uint32_t* chunkReorderMap, const NvBla uint32_t leafChunkCount; if (!Asset::ensureExactSupportCoverage(supportChunkCount, leafChunkCount, chunkAnnotation, chunkCount, const_cast<NvBlastChunkDesc*>(chunkDescs), true, logFn)) { - NVBLAST_LOG_ERROR(logFn, "NvBlastBuildAssetDescChunkReorderMap: chunk descriptors did not have exact coverage, map could not be built. Use NvBlastEnsureAssetExactSupportCoverage to fix descriptors."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastBuildAssetDescChunkReorderMap: chunk descriptors did not have exact coverage, map could not be built. Use NvBlastEnsureAssetExactSupportCoverage to fix descriptors."); return false; } @@ -108,14 +128,15 @@ void NvBlastApplyAssetDescChunkReorderMap NvBlastBondDesc* bondDescs, uint32_t bondCount, const uint32_t* chunkReorderMap, + bool keepBondNormalChunkOrder, NvBlastLog logFn ) { - NVBLAST_CHECK(chunkCount == 0 || chunkDescs != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL chunkDescs input with non-zero chunkCount", return); - NVBLAST_CHECK(reorderedChunkDescs == nullptr || chunkCount != 0, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL reorderedChunkDescs input with non-zero chunkCount", return); - NVBLAST_CHECK(chunkReorderMap == nullptr || chunkCount != 0, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL chunkReorderMap input with non-zero chunkCount", return); - NVBLAST_CHECK(bondCount == 0 || bondDescs != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL bondDescs input with non-zero bondCount", return); - NVBLAST_CHECK(bondDescs == nullptr || chunkReorderMap != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL bondDescs input with NULL chunkReorderMap", return); + NVBLASTLL_CHECK(chunkCount == 0 || chunkDescs != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL chunkDescs input with non-zero chunkCount", return); + NVBLASTLL_CHECK(reorderedChunkDescs == nullptr || chunkCount != 0, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL reorderedChunkDescs input with non-zero chunkCount", return); + NVBLASTLL_CHECK(chunkReorderMap == nullptr || chunkCount != 0, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL chunkReorderMap input with non-zero chunkCount", return); + NVBLASTLL_CHECK(bondCount == 0 || bondDescs != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL bondDescs input with non-zero bondCount", return); + NVBLASTLL_CHECK(bondDescs == nullptr || chunkReorderMap != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMap: NULL bondDescs input with NULL chunkReorderMap", return); // Copy chunk descs if (reorderedChunkDescs) @@ -135,35 +156,58 @@ void NvBlastApplyAssetDescChunkReorderMap { for (uint32_t i = 0; i < bondCount; ++i) { - for (int j = 0; j < 2; ++j) + NvBlastBondDesc& bondDesc = bondDescs[i]; + uint32_t& index0 = bondDesc.chunkIndices[0]; + uint32_t& index1 = bondDesc.chunkIndices[1]; + const uint32_t newIndex0 = index0 < chunkCount ? chunkReorderMap[index0] : index0; + const uint32_t newIndex1 = index1 < chunkCount ? chunkReorderMap[index1] : index1; + if (keepBondNormalChunkOrder && (index0 < index1) != (newIndex0 < newIndex1)) { - uint32_t& index = bondDescs[i].chunkIndices[j]; - if (index < chunkCount) - { - index = chunkReorderMap[index]; - } + VecMath::mul(bondDesc.bond.normal, -1); } + index0 = newIndex0; + index1 = newIndex1; } } } -void NvBlastApplyAssetDescChunkReorderMapInplace(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount, NvBlastBondDesc* bondDescs, uint32_t bondCount, const uint32_t* chunkReorderMap, void* scratch, NvBlastLog logFn) +void NvBlastApplyAssetDescChunkReorderMapInPlace +( + NvBlastChunkDesc* chunkDescs, + uint32_t chunkCount, + NvBlastBondDesc* bondDescs, + uint32_t bondCount, + const uint32_t* chunkReorderMap, + bool keepBondNormalChunkOrder, + void* scratch, + NvBlastLog logFn +) { - NVBLAST_CHECK(chunkCount == 0 || chunkDescs != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMapInplace: NULL chunkDescs input with non-zero chunkCount", return); - NVBLAST_CHECK(chunkCount == 0 || scratch != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMapInplace: NULL scratch input with non-zero chunkCount", return); + NVBLASTLL_CHECK(chunkCount == 0 || chunkDescs != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMapInPlace: NULL chunkDescs input with non-zero chunkCount", return); + NVBLASTLL_CHECK(chunkCount == 0 || scratch != nullptr, logFn, "NvBlastApplyAssetDescChunkReorderMapInPlace: NULL scratch input with non-zero chunkCount", return); NvBlastChunkDesc* chunksTemp = static_cast<NvBlastChunkDesc*>(scratch); memcpy(chunksTemp, chunkDescs, sizeof(NvBlastChunkDesc) * chunkCount); - NvBlastApplyAssetDescChunkReorderMap(chunkDescs, chunksTemp, chunkCount, bondDescs, bondCount, chunkReorderMap, logFn); + NvBlastApplyAssetDescChunkReorderMap(chunkDescs, chunksTemp, chunkCount, bondDescs, bondCount, chunkReorderMap, keepBondNormalChunkOrder, logFn); } -bool NvBlastReorderAssetDescChunks(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount, NvBlastBondDesc* bondDescs, uint32_t bondCount, uint32_t* chunkReorderMap, void* scratch, NvBlastLog logFn) +bool NvBlastReorderAssetDescChunks +( + NvBlastChunkDesc* chunkDescs, + uint32_t chunkCount, + NvBlastBondDesc* bondDescs, + uint32_t bondCount, + uint32_t* chunkReorderMap, + bool keepBondNormalChunkOrder, + void* scratch, + NvBlastLog logFn +) { if (!NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap, chunkDescs, chunkCount, scratch, logFn)) { - NvBlastApplyAssetDescChunkReorderMapInplace(chunkDescs, chunkCount, bondDescs, bondCount, chunkReorderMap, scratch, logFn); + NvBlastApplyAssetDescChunkReorderMapInPlace(chunkDescs, chunkCount, bondDescs, bondCount, chunkReorderMap, keepBondNormalChunkOrder, scratch, logFn); return false; } return true; @@ -172,8 +216,8 @@ bool NvBlastReorderAssetDescChunks(NvBlastChunkDesc* chunkDescs, uint32_t chunkC bool NvBlastEnsureAssetExactSupportCoverage(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount, void* scratch, NvBlastLog logFn) { - NVBLAST_CHECK(chunkCount == 0 || chunkDescs != nullptr, logFn, "NvBlastEnsureAssetExactSupportCoverage: NULL chunkDescs input with non-zero chunkCount", return false); - NVBLAST_CHECK(chunkCount == 0 || scratch != nullptr, logFn, "NvBlastEnsureAssetExactSupportCoverage: NULL scratch input with non-zero chunkCount", return false); + NVBLASTLL_CHECK(chunkCount == 0 || chunkDescs != nullptr, logFn, "NvBlastEnsureAssetExactSupportCoverage: NULL chunkDescs input with non-zero chunkCount", return false); + NVBLASTLL_CHECK(chunkCount == 0 || scratch != nullptr, logFn, "NvBlastEnsureAssetExactSupportCoverage: NULL scratch input with non-zero chunkCount", return false); uint32_t supportChunkCount; uint32_t leafChunkCount; diff --git a/sdk/lowlevel/source/NvBlastChunkHierarchy.h b/sdk/lowlevel/source/NvBlastChunkHierarchy.h index e7e05c6..52380e8 100644 --- a/sdk/lowlevel/source/NvBlastChunkHierarchy.h +++ b/sdk/lowlevel/source/NvBlastChunkHierarchy.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTCHUNKHIERARCHY_H #define NVBLASTCHUNKHIERARCHY_H diff --git a/sdk/lowlevel/source/NvBlastFamily.cpp b/sdk/lowlevel/source/NvBlastFamily.cpp index 1f517b1..b0888c6 100644 --- a/sdk/lowlevel/source/NvBlastFamily.cpp +++ b/sdk/lowlevel/source/NvBlastFamily.cpp @@ -1,17 +1,35 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. #include "NvBlastFamily.h" #include "NvBlastFamilyGraph.h" #include "NvBlastIndexFns.h" +#include "NvBlastTime.h" #include <new> @@ -36,7 +54,7 @@ struct FamilyDataOffsets static size_t createFamilyDataOffsets(FamilyDataOffsets& offsets, const Asset* asset) { - const Nv::Blast::SupportGraph& graph = asset->m_graph; + const SupportGraph& graph = asset->m_graph; NvBlastCreateOffsetStart(sizeof(FamilyHeader)); NvBlastCreateOffsetAlign16(offsets.m_actors, asset->getLowerSupportChunkCount() * sizeof(Actor)); @@ -52,7 +70,7 @@ static size_t createFamilyDataOffsets(FamilyDataOffsets& offsets, const Asset* a size_t getFamilyMemorySize(const Asset* asset) { -#if NVBLAST_CHECK_PARAMS +#if NVBLASTLL_CHECK_PARAMS if (asset == nullptr) { NVBLAST_ALWAYS_ASSERT(); @@ -67,20 +85,20 @@ size_t getFamilyMemorySize(const Asset* asset) NvBlastFamily* createFamily(void* mem, const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(mem != nullptr, logFn, "createFamily: NULL mem pointer input.", return nullptr); - NVBLAST_CHECK(asset != nullptr, logFn, "createFamily: NULL asset pointer input.", return nullptr); + NVBLASTLL_CHECK(mem != nullptr, logFn, "createFamily: NULL mem pointer input.", return nullptr); + NVBLASTLL_CHECK(asset != nullptr, logFn, "createFamily: NULL asset pointer input.", return nullptr); - NVBLAST_CHECK((reinterpret_cast<uintptr_t>(mem) & 0xF) == 0, logFn, "createFamily: mem pointer not 16-byte aligned.", return nullptr); + NVBLASTLL_CHECK((reinterpret_cast<uintptr_t>(mem) & 0xF) == 0, logFn, "createFamily: mem pointer not 16-byte aligned.", return nullptr); const Asset& solverAsset = *static_cast<const Asset*>(asset); if (solverAsset.m_chunkCount == 0) { - NVBLAST_LOG_ERROR(logFn, "createFamily: Asset has no chunks. Family not created.\n"); + NVBLASTLL_LOG_ERROR(logFn, "createFamily: Asset has no chunks. Family not created.\n"); return nullptr; } - const Nv::Blast::SupportGraph& graph = solverAsset.m_graph; + const SupportGraph& graph = solverAsset.m_graph; const uint32_t bondCount = solverAsset.getBondCount(); @@ -97,7 +115,7 @@ NvBlastFamily* createFamily(void* mem, const NvBlastAsset* asset, NvBlastLog log // Restricting our data size to < 4GB so that we may use uint32_t offsets if (dataSize > (size_t)UINT32_MAX) { - NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::instanceAllocate: Instance data block size will exceed 4GB. Instance not created.\n"); + NVBLASTLL_LOG_ERROR(logFn, "Nv::Blast::Actor::instanceAllocate: Instance data block size will exceed 4GB. Instance not created.\n"); return nullptr; } @@ -107,7 +125,7 @@ NvBlastFamily* createFamily(void* mem, const NvBlastAsset* asset, NvBlastLog log // Fill in family header FamilyHeader* header = (FamilyHeader*)family; header->dataType = NvBlastDataBlock::FamilyDataBlock; - header->formatVersion = NvBlastFamilyDataFormat::Current; + header->formatVersion = 0; // Not currently using this field header->size = (uint32_t)dataSize; header->m_assetID = solverAsset.m_ID; header->m_actorCount = 0; @@ -150,6 +168,417 @@ NvBlastFamily* createFamily(void* mem, const NvBlastAsset* asset, NvBlastLog log return family; } + +//////// Family member methods //////// + +void FamilyHeader::fractureSubSupportNoEvents(uint32_t chunkIndex, uint32_t suboffset, float healthDamage, float* chunkHealths, const NvBlastChunk* chunks) +{ + const NvBlastChunk& chunk = chunks[chunkIndex]; + uint32_t numChildren = chunk.childIndexStop - chunk.firstChildIndex; + + if (numChildren > 0) + { + healthDamage /= numChildren; + for (uint32_t childIndex = chunk.firstChildIndex; childIndex < chunk.childIndexStop; childIndex++) + { + float& health = chunkHealths[childIndex - suboffset]; + if (health > 0.0f) + { + float remainingDamage = healthDamage - health; + health -= healthDamage; + + NVBLAST_ASSERT(chunks[childIndex].parentChunkIndex == chunkIndex); + + if (health <= 0.0f && remainingDamage > 0.0f) + { + fractureSubSupportNoEvents(childIndex, suboffset, remainingDamage, chunkHealths, chunks); + } + } + } + } +} + + +void FamilyHeader::fractureSubSupport(uint32_t chunkIndex, uint32_t suboffset, float healthDamage, float* chunkHealths, const NvBlastChunk* chunks, NvBlastChunkFractureData* outBuffer, uint32_t* currentIndex, const uint32_t maxCount) +{ + const NvBlastChunk& chunk = chunks[chunkIndex]; + uint32_t numChildren = chunk.childIndexStop - chunk.firstChildIndex; + + if (numChildren > 0) + { + healthDamage /= numChildren; + for (uint32_t childIndex = chunk.firstChildIndex; childIndex < chunk.childIndexStop; childIndex++) + { + float& health = chunkHealths[childIndex - suboffset]; + if (health > 0.0f) + { + float remainingDamage = healthDamage - health; + health -= healthDamage; + + NVBLAST_ASSERT(chunks[childIndex].parentChunkIndex == chunkIndex); + + if (*currentIndex < maxCount) + { + NvBlastChunkFractureData& event = outBuffer[*currentIndex]; + event.userdata = chunks[childIndex].userData; + event.chunkIndex = childIndex; + event.health = health; + } + (*currentIndex)++; + + if (health <= 0.0f && remainingDamage > 0.0f) + { + fractureSubSupport(childIndex, suboffset, remainingDamage, chunkHealths, chunks, outBuffer, currentIndex, maxCount); + } + } + } + } + +} + + +void FamilyHeader::fractureNoEvents(uint32_t chunkFractureCount, const NvBlastChunkFractureData* chunkFractures, Actor* filterActor, NvBlastLog logFn) +{ + const SupportGraph& graph = m_asset->m_graph; + const uint32_t* graphAdjacencyPartition = graph.getAdjacencyPartition(); + const uint32_t* adjacentBondIndices = graph.getAdjacentBondIndices(); + float* bondHealths = getBondHealths(); + float* chunkHealths = getLowerSupportChunkHealths(); + float* subChunkHealths = getSubsupportChunkHealths(); + const NvBlastChunk* chunks = m_asset->getChunks(); + + for (uint32_t i = 0; i < chunkFractureCount; ++i) + { + const NvBlastChunkFractureData& command = chunkFractures[i]; + const uint32_t chunkIndex = command.chunkIndex; + const uint32_t chunkHealthIndex = m_asset->getContiguousLowerSupportIndex(chunkIndex); + NVBLAST_ASSERT(!isInvalidIndex(chunkHealthIndex)); + if (isInvalidIndex(chunkHealthIndex)) + { + continue; + } + float& health = chunkHealths[chunkHealthIndex]; + if (health > 0.0f && command.health > 0.0f) + { + Actor* actor = getGetChunkActor(chunkIndex); + if (filterActor && filterActor != actor) + { + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorApplyFracture: chunk fracture command corresponds to other actor, command is ignored."); + } + else if (actor) + { + const uint32_t nodeIndex = m_asset->getChunkToGraphNodeMap()[chunkIndex]; + if (actor->getGraphNodeCount() > 1 && !isInvalidIndex(nodeIndex)) + { + for (uint32_t adjacentIndex = graphAdjacencyPartition[nodeIndex]; adjacentIndex < graphAdjacencyPartition[nodeIndex + 1]; adjacentIndex++) + { + const uint32_t bondIndex = adjacentBondIndices[adjacentIndex]; + NVBLAST_ASSERT(!isInvalidIndex(bondIndex)); + if (bondHealths[bondIndex] > 0.0f) + { + bondHealths[bondIndex] = 0.0f; + } + } + getFamilyGraph()->notifyNodeRemoved(actor->getIndex(), nodeIndex, &graph); + } + + health -= command.health; + + const float remainingDamage = -health; + + if (remainingDamage > 0.0f) // node chunk has been damaged beyond its health + { + fractureSubSupportNoEvents(chunkIndex, m_asset->m_firstSubsupportChunkIndex, remainingDamage, subChunkHealths, chunks); + } + } + } + } +} + + +void FamilyHeader::fractureWithEvents(uint32_t chunkFractureCount, const NvBlastChunkFractureData* commands, NvBlastChunkFractureData* events, uint32_t eventsSize, uint32_t* count, Actor* filterActor, NvBlastLog logFn) +{ + const SupportGraph& graph = m_asset->m_graph; + const uint32_t* graphAdjacencyPartition = graph.getAdjacencyPartition(); + const uint32_t* adjacentBondIndices = graph.getAdjacentBondIndices(); + float* bondHealths = getBondHealths(); + float* chunkHealths = getLowerSupportChunkHealths(); + float* subChunkHealths = getSubsupportChunkHealths(); + const NvBlastChunk* chunks = m_asset->getChunks(); + + for (uint32_t i = 0; i < chunkFractureCount; ++i) + { + const NvBlastChunkFractureData& command = commands[i]; + const uint32_t chunkIndex = command.chunkIndex; + const uint32_t chunkHealthIndex = m_asset->getContiguousLowerSupportIndex(chunkIndex); + NVBLAST_ASSERT(!isInvalidIndex(chunkHealthIndex)); + if (isInvalidIndex(chunkHealthIndex)) + { + continue; + } + float& health = chunkHealths[chunkHealthIndex]; + if (health > 0.0f && command.health > 0.0f) + { + Actor* actor = getGetChunkActor(chunkIndex); + if (filterActor && filterActor != actor) + { + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorApplyFracture: chunk fracture command corresponds to other actor, command is ignored."); + } + else if (actor) + { + const uint32_t nodeIndex = m_asset->getChunkToGraphNodeMap()[chunkIndex]; + if (actor->getGraphNodeCount() > 1 && !isInvalidIndex(nodeIndex)) + { + for (uint32_t adjacentIndex = graphAdjacencyPartition[nodeIndex]; adjacentIndex < graphAdjacencyPartition[nodeIndex + 1]; adjacentIndex++) + { + const uint32_t bondIndex = adjacentBondIndices[adjacentIndex]; + NVBLAST_ASSERT(!isInvalidIndex(bondIndex)); + if (bondHealths[bondIndex] > 0.0f) + { + bondHealths[bondIndex] = 0.0f; + } + } + getFamilyGraph()->notifyNodeRemoved(actor->getIndex(), nodeIndex, &graph); + } + + health -= command.health; + + if (*count < eventsSize) + { + NvBlastChunkFractureData& outEvent = events[*count]; + outEvent.userdata = chunks[chunkIndex].userData; + outEvent.chunkIndex = chunkIndex; + outEvent.health = health; + } + (*count)++; + + const float remainingDamage = -health; + + if (remainingDamage > 0.0f) // node chunk has been damaged beyond its health + { + fractureSubSupport(chunkIndex, m_asset->m_firstSubsupportChunkIndex, remainingDamage, subChunkHealths, chunks, events, count, eventsSize); + } + } + } + } +} + + +void FamilyHeader::fractureInPlaceEvents(uint32_t chunkFractureCount, NvBlastChunkFractureData* inoutbuffer, uint32_t eventsSize, uint32_t* count, Actor* filterActor, NvBlastLog logFn) +{ + const SupportGraph& graph = m_asset->m_graph; + const uint32_t* graphAdjacencyPartition = graph.getAdjacencyPartition(); + const uint32_t* adjacentBondIndices = graph.getAdjacentBondIndices(); + float* bondHealths = getBondHealths(); + float* chunkHealths = getLowerSupportChunkHealths(); + float* subChunkHealths = getSubsupportChunkHealths(); + const NvBlastChunk* chunks = m_asset->getChunks(); + + // + // First level Chunk Fractures + // + + for (uint32_t i = 0; i < chunkFractureCount; ++i) + { + const NvBlastChunkFractureData& command = inoutbuffer[i]; + const uint32_t chunkIndex = command.chunkIndex; + const uint32_t chunkHealthIndex = m_asset->getContiguousLowerSupportIndex(chunkIndex); + NVBLAST_ASSERT(!isInvalidIndex(chunkHealthIndex)); + if (isInvalidIndex(chunkHealthIndex)) + { + continue; + } + float& health = chunkHealths[chunkHealthIndex]; + if (health > 0.0f && command.health > 0.0f) + { + Actor* actor = getGetChunkActor(chunkIndex); + if (filterActor && filterActor != actor) + { + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorApplyFracture: chunk fracture command corresponds to other actor, command is ignored."); + } + else if (actor) + { + const uint32_t nodeIndex = m_asset->getChunkToGraphNodeMap()[chunkIndex]; + if (actor->getGraphNodeCount() > 1 && !isInvalidIndex(nodeIndex)) + { + for (uint32_t adjacentIndex = graphAdjacencyPartition[nodeIndex]; adjacentIndex < graphAdjacencyPartition[nodeIndex + 1]; adjacentIndex++) + { + const uint32_t bondIndex = adjacentBondIndices[adjacentIndex]; + NVBLAST_ASSERT(!isInvalidIndex(bondIndex)); + if (bondHealths[bondIndex] > 0.0f) + { + bondHealths[bondIndex] = 0.0f; + } + } + getFamilyGraph()->notifyNodeRemoved(actor->getIndex(), nodeIndex, &graph); + } + + health -= command.health; + + NvBlastChunkFractureData& outEvent = inoutbuffer[(*count)++]; + outEvent.userdata = chunks[chunkIndex].userData; + outEvent.chunkIndex = chunkIndex; + outEvent.health = health; + } + } + } + + // + // Hierarchical Chunk Fractures + // + + uint32_t commandedChunkFractures = *count; + + for (uint32_t i = 0; i < commandedChunkFractures; ++i) + { + NvBlastChunkFractureData& event = inoutbuffer[i]; + const uint32_t chunkIndex = event.chunkIndex; + + const float remainingDamage = -event.health; + if (remainingDamage > 0.0f) // node chunk has been damaged beyond its health + { + fractureSubSupport(chunkIndex, m_asset->m_firstSubsupportChunkIndex, remainingDamage, subChunkHealths, chunks, inoutbuffer, count, eventsSize); + } + } +} + + +void FamilyHeader::applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands, Actor* filterActor, NvBlastLog logFn, NvBlastTimers* timers) +{ + NVBLASTLL_CHECK(commands != nullptr, logFn, "NvBlastActorApplyFracture: NULL commands pointer input.", return); + NVBLASTLL_CHECK(isValid(commands), logFn, "NvBlastActorApplyFracture: commands memory is NULL but size is > 0.", return); + NVBLASTLL_CHECK(eventBuffers == nullptr || isValid(eventBuffers), logFn, "NvBlastActorApplyFracture: eventBuffers memory is NULL but size is > 0.", + eventBuffers->bondFractureCount = 0; eventBuffers->chunkFractureCount = 0; return); + +#if NVBLASTLL_CHECK_PARAMS + if (eventBuffers != nullptr && eventBuffers->bondFractureCount == 0 && eventBuffers->chunkFractureCount == 0) + { + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorApplyFracture: eventBuffers do not provide any space."); + return; + } +#endif + +#if NV_PROFILE + Time time; +#else + NV_UNUSED(timers); +#endif + + // + // Chunk Fracture + // + + if (eventBuffers == nullptr || eventBuffers->chunkFractures == nullptr) + { + // immediate hierarchical fracture + fractureNoEvents(commands->chunkFractureCount, commands->chunkFractures, filterActor, logFn); + } + else if (eventBuffers->chunkFractures != commands->chunkFractures) + { + // immediate hierarchical fracture + uint32_t count = 0; + fractureWithEvents(commands->chunkFractureCount, commands->chunkFractures, eventBuffers->chunkFractures, eventBuffers->chunkFractureCount, &count, filterActor, logFn); + + if (count > eventBuffers->chunkFractureCount) + { + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorApplyFracture: eventBuffers too small. Chunk events were lost."); + } + else + { + eventBuffers->chunkFractureCount = count; + } + } + else if (eventBuffers->chunkFractures == commands->chunkFractures) + { + // compacting first + uint32_t count = 0; + fractureInPlaceEvents(commands->chunkFractureCount, commands->chunkFractures, eventBuffers->chunkFractureCount, &count, filterActor, logFn); + + if (count > eventBuffers->chunkFractureCount) + { + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorApplyFracture: eventBuffers too small. Chunk events were lost."); + } + else + { + eventBuffers->chunkFractureCount = count; + } + } + + // + // Bond Fracture + // + + uint32_t outCount = 0; + const uint32_t eventBufferSize = eventBuffers ? eventBuffers->bondFractureCount : 0; + + NvBlastBond* bonds = m_asset->getBonds(); + float* bondHealths = getBondHealths(); + const uint32_t* graphChunkIndices = m_asset->m_graph.getChunkIndices(); + for (uint32_t i = 0; i < commands->bondFractureCount; ++i) + { + const NvBlastBondFractureData& frac = commands->bondFractures[i]; + NVBLAST_ASSERT(frac.nodeIndex0 < m_asset->m_graph.m_nodeCount); + NVBLAST_ASSERT(frac.nodeIndex1 < m_asset->m_graph.m_nodeCount); + uint32_t chunkIndex0 = graphChunkIndices[frac.nodeIndex0]; + uint32_t chunkIndex1 = graphChunkIndices[frac.nodeIndex1]; + NVBLAST_ASSERT(!isInvalidIndex(chunkIndex0) || !isInvalidIndex(chunkIndex1)); + Actor* actor0 = !isInvalidIndex(chunkIndex0) ? getGetChunkActor(chunkIndex0) : nullptr; + Actor* actor1 = !isInvalidIndex(chunkIndex1) ? getGetChunkActor(chunkIndex1) : nullptr; + NVBLAST_ASSERT(actor0 != nullptr || actor1 != nullptr); + // If actors are not nullptr and different then bond is already broken + // One of actor can be nullptr which probably means it's 'world' node. + if (actor0 == actor1 || actor0 == nullptr || actor1 == nullptr) + { + Actor* actor = actor0 ? actor0 : actor1; + NVBLAST_ASSERT_WITH_MESSAGE(actor, "NvBlastActorApplyFracture: all actors in bond fracture command are nullptr, command will be safely ignored, but investigation is recommended."); + if (filterActor && filterActor != actor) + { + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorApplyFracture: bond fracture command corresponds to other actor, command is ignored."); + } + else if (actor) + { + const uint32_t bondIndex = actor->damageBond(frac.nodeIndex0, frac.nodeIndex1, frac.health); + if (!isInvalidIndex(bondIndex)) + { + if (eventBuffers && eventBuffers->bondFractures) + { + if (outCount < eventBufferSize) + { + NvBlastBondFractureData& outEvent = eventBuffers->bondFractures[outCount]; + outEvent.userdata = bonds[bondIndex].userData; + outEvent.nodeIndex0 = frac.nodeIndex0; + outEvent.nodeIndex1 = frac.nodeIndex1; + outEvent.health = bondHealths[bondIndex]; + } + } + outCount++; + } + } + } + } + + if (eventBuffers && eventBuffers->bondFractures) + { + if (outCount > eventBufferSize) + { + NVBLASTLL_LOG_WARNING(logFn, "NvBlastActorApplyFracture: eventBuffers too small. Bond events were lost."); + } + else + { + eventBuffers->bondFractureCount = outCount; + } + } + +#if NV_PROFILE + if (timers != nullptr) + { + timers->fracture += time.getElapsedTicks(); + } +#endif + +} + + } // namespace Blast } // namespace Nv @@ -167,22 +596,29 @@ NvBlastFamily* NvBlastAssetCreateFamily(void* mem, const NvBlastAsset* asset, Nv uint32_t NvBlastFamilyGetFormatVersion(const NvBlastFamily* family, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetFormatVersion: NULL family pointer input.", return UINT32_MAX); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyGetFormatVersion: NULL family pointer input.", return UINT32_MAX); return reinterpret_cast<const Nv::Blast::FamilyHeader*>(family)->formatVersion; } +const NvBlastAsset* NvBlastFamilyGetAsset(const NvBlastFamily* family, NvBlastLog logFn) +{ + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyGetAssetID: NULL family pointer input.", return nullptr); + return reinterpret_cast<const Nv::Blast::FamilyHeader*>(family)->m_asset; +} + + void NvBlastFamilySetAsset(NvBlastFamily* family, const NvBlastAsset* asset, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilySetAsset: NULL family pointer input.", return); - NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastFamilySetAsset: NULL asset pointer input.", return); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilySetAsset: NULL family pointer input.", return); + NVBLASTLL_CHECK(asset != nullptr, logFn, "NvBlastFamilySetAsset: NULL asset pointer input.", return); Nv::Blast::FamilyHeader* header = reinterpret_cast<Nv::Blast::FamilyHeader*>(family); const Nv::Blast::Asset* solverAsset = reinterpret_cast<const Nv::Blast::Asset*>(asset); if (memcmp(&header->m_assetID, &solverAsset->m_ID, sizeof(NvBlastID))) { - NVBLAST_LOG_ERROR(logFn, "NvBlastFamilySetAsset: wrong asset. Passed asset ID doesn't match family asset ID."); + NVBLASTLL_LOG_ERROR(logFn, "NvBlastFamilySetAsset: wrong asset. Passed asset ID doesn't match family asset ID."); return; } @@ -192,47 +628,35 @@ void NvBlastFamilySetAsset(NvBlastFamily* family, const NvBlastAsset* asset, NvB uint32_t NvBlastFamilyGetSize(const NvBlastFamily* family, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetSize: NULL family pointer input.", return 0); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyGetSize: NULL family pointer input.", return 0); return reinterpret_cast<const Nv::Blast::FamilyHeader*>(family)->size; } NvBlastID NvBlastFamilyGetAssetID(const NvBlastFamily* family, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetAssetID: NULL family pointer input.", return NvBlastID()); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyGetAssetID: NULL family pointer input.", return NvBlastID()); return reinterpret_cast<const Nv::Blast::FamilyHeader*>(family)->m_assetID; } uint32_t NvBlastFamilyGetActorCount(const NvBlastFamily* family, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetActorCount: NULL family pointer input.", return 0); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyGetActorCount: NULL family pointer input.", return 0); const Nv::Blast::FamilyHeader* header = reinterpret_cast<const Nv::Blast::FamilyHeader*>(family); - if (header->formatVersion != NvBlastFamilyDataFormat::Current) - { - NVBLAST_LOG_ERROR(logFn, "NvBlastFamilyGetActorCount: wrong family format. Family must be converted to current version."); - return 0; - } - return header->m_actorCount; } uint32_t NvBlastFamilyGetActors(NvBlastActor** actors, uint32_t actorsSize, const NvBlastFamily* family, NvBlastLog logFn) { - NVBLAST_CHECK(actors != nullptr, logFn, "NvBlastFamilyGetActors: NULL actors pointer input.", return 0); - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetActors: NULL family pointer input.", return 0); + NVBLASTLL_CHECK(actors != nullptr, logFn, "NvBlastFamilyGetActors: NULL actors pointer input.", return 0); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyGetActors: NULL family pointer input.", return 0); const Nv::Blast::FamilyHeader* header = reinterpret_cast<const Nv::Blast::FamilyHeader*>(family); - if (header->formatVersion != NvBlastFamilyDataFormat::Current) - { - NVBLAST_LOG_ERROR(logFn, "NvBlastFamilyGetActors: wrong family format. Family must be converted to current version."); - return 0; - } - // Iterate through active actors and write to supplied array const uint32_t familyActorCount = header->getActorBufferSize(); Nv::Blast::Actor* familyActor = header->getActors(); @@ -251,43 +675,20 @@ uint32_t NvBlastFamilyGetActors(NvBlastActor** actors, uint32_t actorsSize, cons NvBlastActor* NvBlastFamilyGetChunkActor(const NvBlastFamily* family, uint32_t chunkIndex, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetChunkActor: NULL family pointer input.", return nullptr); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyGetChunkActor: NULL family pointer input.", return nullptr); const Nv::Blast::FamilyHeader* header = reinterpret_cast<const Nv::Blast::FamilyHeader*>(family); - NVBLAST_CHECK(header->m_asset != nullptr, logFn, "NvBlastFamilyGetChunkActor: NvBlastFamily has null asset set.", return nullptr); - - const Nv::Blast::Asset& solverAsset = *static_cast<const Nv::Blast::Asset*>(header->m_asset); - NVBLAST_CHECK(chunkIndex < solverAsset.m_chunkCount, logFn, "NvBlastFamilyGetChunkActor: bad value of chunkIndex for the given family's asset.", return nullptr); - - // get actorIndex from chunkIndex - uint32_t actorIndex; - if (chunkIndex < solverAsset.getUpperSupportChunkCount()) - { - actorIndex = header->getChunkActorIndices()[chunkIndex]; - } - else - { - actorIndex = chunkIndex - (solverAsset.getUpperSupportChunkCount() - solverAsset.m_graph.m_nodeCount); - } + NVBLASTLL_CHECK(header->m_asset != nullptr, logFn, "NvBlastFamilyGetChunkActor: NvBlastFamily has null asset set.", return nullptr); + NVBLASTLL_CHECK(chunkIndex < header->m_asset->m_chunkCount, logFn, "NvBlastFamilyGetChunkActor: bad value of chunkIndex for the given family's asset.", return nullptr); - // get actor from actorIndex - if (!Nv::Blast::isInvalidIndex(actorIndex)) - { - NVBLAST_ASSERT(actorIndex < header->getActorBufferSize()); - Nv::Blast::Actor* actor = &header->getActors()[actorIndex]; - if (actor->isActive()) - { - return actor; - } - } - return nullptr; + return header->getGetChunkActor(chunkIndex); } uint32_t NvBlastFamilyGetMaxActorCount(const NvBlastFamily* family, NvBlastLog logFn) { - NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetMaxActorCount: NULL family pointer input.", return 0); + NVBLASTLL_CHECK(family != nullptr, logFn, "NvBlastFamilyGetMaxActorCount: NULL family pointer input.", return 0); const Nv::Blast::FamilyHeader* header = reinterpret_cast<const Nv::Blast::FamilyHeader*>(family); return header->getActorBufferSize(); } diff --git a/sdk/lowlevel/source/NvBlastFamily.h b/sdk/lowlevel/source/NvBlastFamily.h index d1cb069..99a7e98 100644 --- a/sdk/lowlevel/source/NvBlastFamily.h +++ b/sdk/lowlevel/source/NvBlastFamily.h @@ -1,18 +1,35 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTFAMILY_H #define NVBLASTFAMILY_H -#include "NvBlastPreprocessorInternal.h" #include "NvBlastAsset.h" #include "NvBlastPreprocessor.h" #include "NvBlastDLink.h" @@ -164,6 +181,139 @@ struct FamilyHeader : public NvBlastDataBlock \return true iff the indexed actor is active. */ bool isActorActive(uint32_t index) const; + + /** + Retrieve the actor from an index. If actor is inactive nullptr is returned. + + \param[in] index The index of an actor. + + \return A pointer to the indexed actor if the actor is active, nullptr otherwise. + */ + Actor* getActorByIndex(uint32_t index) const; + + /** + Retrieve the index of an actor associated with the given chunk. + + \param[in] chunkIndex The index of chunk. + + \return the index of associated actor in the FamilyHeader's getActors() array. + */ + uint32_t getGetChunkActorIndex(uint32_t chunkIndex) const; + + /** + Retrieve the index of an actor associated with the given node. + + \param[in] nodeIndex The index of node. + + \return the index of associated actor in the FamilyHeader's getActors() array. + */ + uint32_t getGetNodeActorIndex(uint32_t nodeIndex) const; + + /** + Retrieve an actor associated with the given chunk. + + \param[in] chunkIndex The index of chunk. + + \return A pointer to the actor if the actor is active, nullptr otherwise. + */ + Actor* getGetChunkActor(uint32_t chunkIndex) const; + + /** + Retrieve an actor associated with the given node. + + \param[in] nodeIndex The index of node. + + \return A pointer to the actor if the actor is active, nullptr otherwise. + */ + Actor* getGetNodeActor(uint32_t nodeIndex) const; + + + //////// Fracturing methods //////// + + /** + Hierarchically distribute damage to child chunks. + + \param chunkIndex asset chunk index to hierarchically damage + \param suboffset index of the first sub-support health + \param healthDamage damage strength to apply + \param chunkHealths instance chunk healths + \param chunks asset chunk collection + */ + void fractureSubSupportNoEvents(uint32_t chunkIndex, uint32_t suboffset, float healthDamage, float* chunkHealths, const NvBlastChunk* chunks); + + /** + Hierarchically distribute damage to child chunks, recording a fracture event for each health damage applied. + + If outBuffer is too small, events are dropped but the chunks are still damaged. + + \param chunkIndex asset chunk index to hierarchically damage + \param suboffset index of the first sub-support health + \param healthDamage damage strength to apply + \param chunkHealths instance chunk healths + \param chunks asset chunk collection + \param outBuffer target buffer for fracture events + \param currentIndex current position in outBuffer - returns the number of damaged chunks + \param maxCount capacity of outBuffer + \param[in] filterActor pointer to the actor to filter commands that target other actors. May be NULL to apply all commands + \param[in] logFn User-supplied message function (see NvBlastLog definition). May be NULL. + */ + void fractureSubSupport(uint32_t chunkIndex, uint32_t suboffset, float healthDamage, float* chunkHealths, const NvBlastChunk* chunks, NvBlastChunkFractureData* outBuffer, uint32_t* currentIndex, const uint32_t maxCount); + + /** + Apply chunk fracture commands hierarchically. + + \param chunkFractureCount number of chunk fracture commands to apply + \param chunkFractures array of chunk fracture commands + \param filterActor pointer to the actor to filter commands corresponding to other actors. May be NULL to apply all commands + \param[in] logFn User-supplied message function (see NvBlastLog definition). May be NULL. + */ + void fractureNoEvents(uint32_t chunkFractureCount, const NvBlastChunkFractureData* chunkFractures, Actor* filterActor, NvBlastLog logFn); + + /** + Apply chunk fracture commands hierarchically, recording a fracture event for each health damage applied. + + If events array is too small, events are dropped but the chunks are still damaged. + + \param chunkFractureCount number of chunk fracture commands to apply + \param commands array of chunk fracture commands + \param events target buffer for fracture events + \param eventsSize number of available entries in 'events' + \param count returns the number of damaged chunks + \param[in] filterActor pointer to the actor to filter commands that target other actors. May be NULL to apply all commands + \param[in] logFn User-supplied message function (see NvBlastLog definition). May be NULL. + + */ + void fractureWithEvents(uint32_t chunkFractureCount, const NvBlastChunkFractureData* commands, NvBlastChunkFractureData* events, uint32_t eventsSize, uint32_t* count, Actor* filterActor, NvBlastLog logFn); + + /** + Apply chunk fracture commands hierarchically, recording a fracture event for each health damage applied. + + In-Place version: fracture commands are replaced by fracture events. + + If inoutbuffer array is too small, events are dropped but the chunks are still damaged. + + \param chunkFractureCount number of chunk fracture commands to apply + \param inoutbuffer array of chunk fracture commands to be replaced by events + \param eventsSize number of available entries in inoutbuffer + \param count returns the number of damaged chunks + \param[in] filterActor pointer to the actor to filter commands that target other actors. May be NULL to apply all commands + \param[in] logFn User-supplied message function (see NvBlastLog definition). May be NULL. + + */ + void fractureInPlaceEvents(uint32_t chunkFractureCount, NvBlastChunkFractureData* inoutbuffer, uint32_t eventsSize, uint32_t* count, Actor* filterActor, NvBlastLog logFn); + + /** + See NvBlastActorApplyFracture + + \param[in,out] eventBuffers Target buffers to hold applied fracture events. May be NULL, in which case events are not reported. + To avoid data loss, provide an entry for every lower-support chunk and every bond in the original actor. + \param[in,out] actor The NvBlastActor to apply fracture to. + \param[in] commands The fracture commands to process. + \param[in] filterActor pointer to the actor to filter commands that target other actors. May be NULL to apply all commands + \param[in] logFn User-supplied message function (see NvBlastLog definition). May be NULL. + \param[in,out] timers If non-NULL this struct will be filled out with profiling information for the step, in profile build configurations. + */ + void applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands, Actor* filterActor, NvBlastLog logFn, NvBlastTimers* timers); }; } // namespace Blast @@ -221,6 +371,52 @@ NV_INLINE bool FamilyHeader::isActorActive(uint32_t index) const } +NV_INLINE Actor* FamilyHeader::getActorByIndex(uint32_t index) const +{ + NVBLAST_ASSERT(index < getActorBufferSize()); + Actor& actor = getActors()[index]; + return actor.isActive() ? &actor : nullptr; +} + + +NV_INLINE uint32_t FamilyHeader::getGetChunkActorIndex(uint32_t chunkIndex) const +{ + NVBLAST_ASSERT(m_asset); + NVBLAST_ASSERT(chunkIndex < m_asset->m_chunkCount); + if (chunkIndex < m_asset->getUpperSupportChunkCount()) + { + return getChunkActorIndices()[chunkIndex]; + } + else + { + return chunkIndex - (m_asset->getUpperSupportChunkCount() - m_asset->m_graph.m_nodeCount); + } +} + + +NV_INLINE uint32_t FamilyHeader::getGetNodeActorIndex(uint32_t nodeIndex) const +{ + NVBLAST_ASSERT(m_asset); + NVBLAST_ASSERT(nodeIndex < m_asset->m_graph.m_nodeCount); + const uint32_t chunkIndex = m_asset->m_graph.getChunkIndices()[nodeIndex]; + return isInvalidIndex(chunkIndex) ? chunkIndex : getChunkActorIndices()[chunkIndex]; +} + + +NV_INLINE Actor* FamilyHeader::getGetChunkActor(uint32_t chunkIndex) const +{ + uint32_t actorIndex = getGetChunkActorIndex(chunkIndex); + return !isInvalidIndex(actorIndex) ? getActorByIndex(actorIndex) : nullptr; +} + + +NV_INLINE Actor* FamilyHeader::getGetNodeActor(uint32_t nodeIndex) const +{ + uint32_t actorIndex = getGetNodeActorIndex(nodeIndex); + return !isInvalidIndex(actorIndex) ? getActorByIndex(actorIndex) : nullptr; +} + + //////// Global functions //////// /** diff --git a/sdk/lowlevel/source/NvBlastFamilyGraph.cpp b/sdk/lowlevel/source/NvBlastFamilyGraph.cpp index 08ed83d..9379a32 100644 --- a/sdk/lowlevel/source/NvBlastFamilyGraph.cpp +++ b/sdk/lowlevel/source/NvBlastFamilyGraph.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastFamilyGraph.h" diff --git a/sdk/lowlevel/source/NvBlastFamilyGraph.h b/sdk/lowlevel/source/NvBlastFamilyGraph.h index 9fa331a..1242487 100644 --- a/sdk/lowlevel/source/NvBlastFamilyGraph.h +++ b/sdk/lowlevel/source/NvBlastFamilyGraph.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTFAMILYGRAPH_H #define NVBLASTFAMILYGRAPH_H @@ -18,7 +36,6 @@ #include "NvBlastFixedBoolArray.h" #include "NvBlastMath.h" #include "NvBlastFixedPriorityQueue.h" -#include "NvBlastPreprocessorInternal.h" #include "NvBlastMemory.h" diff --git a/sdk/lowlevel/source/NvBlastSupportGraph.h b/sdk/lowlevel/source/NvBlastSupportGraph.h index 9ee3fc9..b8c2368 100644 --- a/sdk/lowlevel/source/NvBlastSupportGraph.h +++ b/sdk/lowlevel/source/NvBlastSupportGraph.h @@ -1,19 +1,36 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTSUPPORTGRAPH_H #define NVBLASTSUPPORTGRAPH_H #include "NvBlastIndexFns.h" -#include "NvBlastPreprocessorInternal.h" #include "NvBlastMemory.h" namespace Nv |