aboutsummaryrefslogtreecommitdiff
path: root/sdk/lowlevel/source/NvBlastFamily.cpp
diff options
context:
space:
mode:
authorAnton Novoselov <[email protected]>2017-08-01 12:53:38 +0300
committerAnton Novoselov <[email protected]>2017-08-01 12:53:38 +0300
commit236f03c0b9a4982328ed1201978f7f69d192d9b2 (patch)
treee486f2fa39dba203563895541e92c60ed3e25759 /sdk/lowlevel/source/NvBlastFamily.cpp
parentAdded screens to welcome page (diff)
downloadblast-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/NvBlastFamily.cpp')
-rw-r--r--sdk/lowlevel/source/NvBlastFamily.cpp535
1 files changed, 468 insertions, 67 deletions
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();
}