aboutsummaryrefslogtreecommitdiff
path: root/sdk/toolkit/source/NvBlastTkFamilyImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/toolkit/source/NvBlastTkFamilyImpl.cpp')
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkFamilyImpl.cpp1116
1 files changed, 558 insertions, 558 deletions
diff --git a/sdk/toolkit/source/NvBlastTkFamilyImpl.cpp b/sdk/toolkit/source/NvBlastTkFamilyImpl.cpp
index 50b3266..26133f0 100644..100755
--- a/sdk/toolkit/source/NvBlastTkFamilyImpl.cpp
+++ b/sdk/toolkit/source/NvBlastTkFamilyImpl.cpp
@@ -1,558 +1,558 @@
-// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvBlastTkFrameworkImpl.h"
-#include "NvBlastTkFamilyImpl.h"
-#include "NvBlastTkGroupImpl.h"
-#include "NvBlastTkAssetImpl.h"
-#include "NvBlastTkActorImpl.h"
-#include "NvBlastTkJointImpl.h"
-
-#include "NvBlastIndexFns.h"
-#include "NvBlastMemory.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-//////// Static data ////////
-
-NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(Family);
-
-
-//////// Member functions ////////
-
-TkFamilyImpl::TkFamilyImpl() : m_familyLL(nullptr), m_internalJointCount(0), m_asset(nullptr)
-{
-}
-
-
-TkFamilyImpl::TkFamilyImpl(const NvBlastID& id) : TkFamilyType(id), m_familyLL(nullptr), m_internalJointCount(0), m_asset(nullptr)
-{
-}
-
-
-TkFamilyImpl::~TkFamilyImpl()
-{
- if (m_familyLL != nullptr)
- {
- uint32_t familyActorCount = NvBlastFamilyGetActorCount(m_familyLL, logLL);
- if (familyActorCount != 0)
- {
- NVBLAST_LOG_WARNING("TkFamilyImpl::~TkFamilyImpl(): family actor count is not 0.");
- }
- NVBLAST_FREE(m_familyLL);
- }
-}
-
-
-void TkFamilyImpl::release()
-{
- for (TkActorImpl& actor : m_actors)
- {
- if (actor.isActive())
- {
- actor.release();
- }
- }
-
- m_actors.clear();
-
- NVBLAST_DELETE(this, TkFamilyImpl);
-}
-
-
-const NvBlastFamily* TkFamilyImpl::getFamilyLL() const
-{
- return m_familyLL;
-}
-
-
-TkActorImpl* TkFamilyImpl::addActor(NvBlastActor* actorLL)
-{
- TkActorImpl* actor = getActorByActorLL(actorLL);
- NVBLAST_ASSERT(actor);
- actor->m_actorLL = actorLL;
- actor->m_family = this;
- return actor;
-}
-
-
-void TkFamilyImpl::removeActor(TkActorImpl* actor)
-{
- NVBLAST_ASSERT(actor != nullptr && actor->m_family == this);
- //actor->m_family = nullptr;
- actor->m_actorLL = nullptr;
-}
-
-
-uint32_t TkFamilyImpl::getActorCount() const
-{
- return getActorCountInternal();
-}
-
-
-uint32_t TkFamilyImpl::getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart /*= 0*/) const
-{
- uint32_t actorCount = getActorCount();
- if (actorCount <= indexStart)
- {
- NVBLAST_LOG_WARNING("TkFamilyImpl::getActors: indexStart beyond end of actor list.");
- return 0;
- }
-
- actorCount -= indexStart;
- if (actorCount > bufferSize)
- {
- actorCount = static_cast<uint32_t>(bufferSize);
- }
-
- uint32_t index = 0;
- for (const TkActorImpl& actor : m_actors)
- {
- if (actor.isActive())
- {
- if (index >= indexStart)
- {
- if ((index - indexStart) >= actorCount)
- {
- break;
- }
- else
- {
- *buffer++ = const_cast<TkActorImpl*>(&actor);
- }
- }
- index++;
- }
- }
-
- return actorCount;
-}
-
-
-NV_INLINE bool areLLActorsEqual(const NvBlastActor* actor0, const NvBlastActor* actor1, Array<uint32_t>::type& scratch)
-{
- if (NvBlastActorGetGraphNodeCount(actor0, logLL) != NvBlastActorGetGraphNodeCount(actor1, logLL))
- {
- return false;
- }
-
- const uint32_t chunkCount = NvBlastActorGetVisibleChunkCount(actor0, logLL);
- if (chunkCount != NvBlastActorGetVisibleChunkCount(actor1, logLL))
- {
- return false;
- }
-
- scratch.resize(chunkCount * 2);
- NvBlastActorGetVisibleChunkIndices(scratch.begin(), chunkCount, actor0, logLL);
- NvBlastActorGetVisibleChunkIndices(scratch.begin() + chunkCount, chunkCount, actor1, logLL);
- return memcmp(scratch.begin(), scratch.begin() + chunkCount, chunkCount * sizeof(uint32_t)) == 0;
-}
-
-
-void TkFamilyImpl::reinitialize(const NvBlastFamily* newFamily, TkGroup* group)
-{
- NVBLAST_ASSERT(newFamily);
-#if NV_ENABLE_ASSERTS
- NvBlastID id0 = NvBlastFamilyGetAssetID(m_familyLL, logLL);
- NvBlastID id1 = NvBlastFamilyGetAssetID(newFamily, logLL);
- NVBLAST_ASSERT(TkGUIDsEqual(&id0, &id1));
-#endif
- NVBLAST_ASSERT(NvBlastFamilyGetSize(m_familyLL, logLL) == NvBlastFamilyGetSize(newFamily, logLL));
-
- // alloc and init new family
- const uint32_t blockSize = NvBlastFamilyGetSize(newFamily, logLL);
- NvBlastFamily* newFamilyCopy = (NvBlastFamily*)NVBLAST_ALLOC_NAMED(blockSize, "TkFamilyImpl::reinitialize");
- memcpy(newFamilyCopy, newFamily, blockSize);
- NvBlastFamilySetAsset(newFamilyCopy, m_asset->getAssetLL(), logLL);
-
- // get actors from new family
- Array<NvBlastActor*>::type newLLActors(NvBlastFamilyGetActorCount(newFamilyCopy, logLL));
- uint32_t actorCount = NvBlastFamilyGetActors(newLLActors.begin(), newLLActors.size(), newFamilyCopy, logLL);
-
- // reset actor families to nullptr (we use it as a flag later)
- for (TkActorImpl& actor : m_actors)
- {
- if (actor.isActive())
- {
- actor.m_family = nullptr;
- }
- }
-
- // prepare split event with new actors
- auto newActorsSplitEvent = getQueue().allocData<TkSplitEvent>();
- Array<TkActor*>::type children(actorCount);
- children.resizeUninitialized(0);
- newActorsSplitEvent->children = children.begin();
-
- // scratch
- Array<uint32_t>::type scratch(m_asset->getChunkCount());
-
- for (uint32_t i = 0; i < actorCount; ++i)
- {
- NvBlastActor* newLLActor = newLLActors[i];
- uint32_t actorIndex = NvBlastActorGetIndex(newLLActor, logLL);
- TkActorImpl& tkActor = *getActorByIndex(actorIndex);
-
- tkActor.m_family = this;
-
- if (!tkActor.isActive() || !areLLActorsEqual(newLLActor, tkActor.m_actorLL, scratch))
- {
- if (tkActor.isActive())
- {
- auto removeSplitEvent = getQueue().allocData<TkSplitEvent>();
- removeSplitEvent->parentData.family = this;
- removeSplitEvent->numChildren = 0;
- removeSplitEvent->parentData.userData = tkActor.userData;
- removeSplitEvent->parentData.index = tkActor.getIndex();
- getQueue().addEvent(removeSplitEvent);
- }
-
- tkActor.m_actorLL = newLLActor;
-
- // switch groups
- TkGroupImpl* prevGroup = tkActor.m_group;
- if (prevGroup != group)
- {
- if (prevGroup)
- {
- prevGroup->removeActor(tkActor);
- }
- if (group)
- {
- group->addActor(tkActor);
- }
- }
-
- children.pushBack(&tkActor);
- }
- else
- {
- tkActor.m_actorLL = newLLActor;
- }
- }
-
- // if m_family is still nullptr for an active actor -> remove it. It doesn't exist in new family.
- for (TkActorImpl& tkActor : m_actors)
- {
- if (tkActor.isActive() && tkActor.m_family == nullptr)
- {
- tkActor.m_family = this;
- if (tkActor.m_group)
- {
- tkActor.m_group->removeActor(tkActor);
- }
-
- auto removeSplitEvent = getQueue().allocData<TkSplitEvent>();
- removeSplitEvent->parentData.family = this;
- removeSplitEvent->numChildren = 0;
- removeSplitEvent->parentData.userData = tkActor.userData;
- removeSplitEvent->parentData.index = tkActor.getIndex();
- getQueue().addEvent(removeSplitEvent);
-
- tkActor.m_actorLL = nullptr;
- }
- }
-
- // add split event with all new actors
- newActorsSplitEvent->parentData.family = this;
- newActorsSplitEvent->parentData.userData = 0;
- newActorsSplitEvent->parentData.index = invalidIndex<uint32_t>();
- newActorsSplitEvent->numChildren = children.size();
- if (newActorsSplitEvent->numChildren > 0)
- {
- getQueue().addEvent(newActorsSplitEvent);
- }
-
- // replace family
- NVBLAST_FREE(m_familyLL);
- m_familyLL = newFamilyCopy;
-
- // update joints
- for (TkActorImpl& tkActor : m_actors)
- {
- if (!tkActor.m_jointList.isEmpty())
- {
- updateJoints(&tkActor);
- }
- }
-
- getQueue().dispatch();
-}
-
-
-TkActorImpl* TkFamilyImpl::getActorByChunk(uint32_t chunk)
-{
- if (chunk >= NvBlastAssetGetChunkCount(m_asset->getAssetLLInternal(), logLL))
- {
- NVBLAST_LOG_WARNING("TkFamilyImpl::getActorByChunk: invalid chunk index. Returning NULL.");
- return nullptr;
- }
-
- NvBlastActor* actorLL = NvBlastFamilyGetChunkActor(m_familyLL, chunk, logLL);
- return actorLL ? getActorByActorLL(actorLL) : nullptr;
-}
-
-
-void TkFamilyImpl::applyFractureInternal(const NvBlastFractureBuffers* commands)
-{
- NvBlastSupportGraph graph = getAsset()->getGraph();
-
- // apply bond fracture commands on relevant actors
- {
- TkActorImpl* currActor = nullptr;
- NvBlastBondFractureData* bondFractures = commands->bondFractures;
- uint32_t bondFracturesCount = 0;
-
- auto applyFracture = [&]()
- {
- if (bondFracturesCount > 0)
- {
- if (currActor != nullptr && currActor->isActive())
- {
- NvBlastFractureBuffers newCommands;
- newCommands.bondFractures = bondFractures;
- newCommands.bondFractureCount = bondFracturesCount;
- newCommands.chunkFractures = nullptr;
- newCommands.chunkFractureCount = 0;
- currActor->applyFracture(nullptr, &newCommands);
- }
-
- bondFractures += bondFracturesCount;
- bondFracturesCount = 0;
- }
- };
-
- for (uint32_t i = 0; i < commands->bondFractureCount; ++i, ++bondFracturesCount)
- {
- const NvBlastBondFractureData& command = commands->bondFractures[i];
- uint32_t chunk0 = graph.chunkIndices[command.nodeIndex0];
- uint32_t chunk1 = graph.chunkIndices[command.nodeIndex1];
- TkActorImpl* actor0 = getActorByChunk(chunk0);
- TkActorImpl* actor1 = getActorByChunk(chunk1);
- if (actor0 != actor1)
- {
- // skipping this event, bond already broken
- actor0 = nullptr;
- }
- if (actor0 != currActor)
- {
- applyFracture();
- currActor = actor0;
- }
- }
-
- if (bondFracturesCount > 0)
- {
- applyFracture();
- }
- }
-
- // apply chunk fracture commands on relevant actors
- {
- TkActorImpl* currActor = nullptr;
- NvBlastChunkFractureData* chunkFractures = commands->chunkFractures;
- uint32_t chunkFracturesCount = 0;
-
- auto applyFracture = [&]()
- {
- if (chunkFracturesCount > 0)
- {
- if (currActor != nullptr && currActor->isActive())
- {
- NvBlastFractureBuffers newCommands;
- newCommands.bondFractures = nullptr;
- newCommands.bondFractureCount = 0;
- newCommands.chunkFractures = chunkFractures;
- newCommands.chunkFractureCount = chunkFracturesCount;
- currActor->applyFracture(nullptr, &newCommands);
- }
-
- chunkFractures += chunkFracturesCount;
- chunkFracturesCount = 0;
- }
- };
-
- for (uint32_t i = 0; i < commands->chunkFractureCount; ++i, ++chunkFracturesCount)
- {
- const NvBlastChunkFractureData& command = commands->chunkFractures[i];
- TkActorImpl* actor = getActorByChunk(command.chunkIndex);
- if (actor != currActor)
- {
- applyFracture();
- currActor = actor;
- }
- }
- if (chunkFracturesCount > 0)
- {
- applyFracture();
- }
- }
-}
-
-
-void TkFamilyImpl::updateJoints(TkActorImpl* actor, TkEventQueue* alternateQueue)
-{
- // Copy joint array for safety against implementation of joint->setActor
- TkJointImpl** joints = reinterpret_cast<TkJointImpl**>(NvBlastAlloca(sizeof(TkJointImpl*)*actor->getJointCountInternal()));
- TkJointImpl** stop = joints + actor->getJointCountInternal();
- TkJointImpl** jointHandle = joints;
- for (TkActorImpl::JointIt j(*actor); (bool)j; ++j)
- {
- *jointHandle++ = *j;
- }
- jointHandle = joints;
- while (jointHandle < stop)
- {
- TkJointImpl* joint = *jointHandle++;
-
- const TkJointData& data = joint->getDataInternal();
-
- TkActorImpl* actor0 = data.actors[0] != nullptr ?
- static_cast<TkActorImpl&>(*data.actors[0]).getFamilyImpl().getActorByChunk(data.chunkIndices[0]) : nullptr;
-
- TkActorImpl* actor1 = data.actors[1] != nullptr ?
- static_cast<TkActorImpl&>(*data.actors[1]).getFamilyImpl().getActorByChunk(data.chunkIndices[1]) : nullptr;
-
- joint->setActors(actor0, actor1, alternateQueue);
- }
-}
-
-
-const TkAsset* TkFamilyImpl::getAsset() const
-{
- return m_asset;
-}
-
-
-//////// Static functions ////////
-
-TkFamilyImpl* TkFamilyImpl::create(const TkAssetImpl* asset)
-{
- TkFamilyImpl* family = NVBLAST_NEW(TkFamilyImpl);
- family->m_asset = asset;
- void* mem = NVBLAST_ALLOC_NAMED(NvBlastAssetGetFamilyMemorySize(asset->getAssetLL(), logLL), "TkFamilyImpl::create");
- family->m_familyLL = NvBlastAssetCreateFamily(mem, asset->getAssetLL(), logLL);
- //family->addListener(*TkFrameworkImpl::get());
-
- if (family->m_familyLL == nullptr)
- {
- NVBLAST_LOG_ERROR("TkFamilyImpl::create: low-level family could not be created.");
- family->release();
- return nullptr;
- }
-
- uint32_t maxActorCount = NvBlastFamilyGetMaxActorCount(family->m_familyLL, logLL);
- family->m_actors.resize(maxActorCount);
-
- family->m_internalJointBuffer.resize(asset->getJointDescCountInternal() * sizeof(TkJointImpl), 0);
- family->m_internalJointCount = asset->getJointDescCountInternal();
-
- return family;
-}
-
-
-TkJointImpl** TkFamilyImpl::createExternalJointHandle(const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1)
-{
- JointSet* jointSet;
- const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(otherFamilyID);
- uint32_t otherFamilyIndex;
- if (jointSetIndexEntry != nullptr)
- {
- otherFamilyIndex = jointSetIndexEntry->second;
- jointSet = m_jointSets[otherFamilyIndex];
- }
- else
- {
- jointSet = NVBLAST_NEW(JointSet);
- NVBLAST_CHECK_ERROR(jointSet != nullptr, "TkFamilyImpl::addExternalJoint: failed to create joint set for other family ID.", return nullptr);
- jointSet->m_familyID = otherFamilyID;
- otherFamilyIndex = m_jointSets.size();
- m_familyIDMap[otherFamilyID] = otherFamilyIndex;
- m_jointSets.pushBack(jointSet);
- }
-
- const ExternalJointKey key(chunkIndex0, chunkIndex1);
- const bool jointExists = jointSet->m_joints.find(key) != nullptr;
- NVBLAST_CHECK_WARNING(!jointExists, "TkFamilyImpl::addExternalJoint: joint already added.", return nullptr);
-
- return &jointSet->m_joints[key];
-}
-
-
-bool TkFamilyImpl::deleteExternalJointHandle(TkJointImpl*& joint, const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1)
-{
- const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(otherFamilyID);
- if (jointSetIndexEntry != nullptr)
- {
- const uint32_t jointSetIndex = jointSetIndexEntry->second;
- HashMap<ExternalJointKey, TkJointImpl*>::type::Entry e;
- if (m_jointSets[jointSetIndex]->m_joints.erase(ExternalJointKey(chunkIndex0, chunkIndex1), e))
- {
- // Delete the joint set if it is empty
- if (m_jointSets[jointSetIndex]->m_joints.size() == 0)
- {
- NVBLAST_DELETE(m_jointSets[jointSetIndex], JointSet);
- m_jointSets.replaceWithLast(jointSetIndex);
- m_familyIDMap.erase(otherFamilyID);
- if (jointSetIndex < m_jointSets.size())
- {
- m_familyIDMap[m_jointSets[jointSetIndex]->m_familyID] = jointSetIndex;
- }
- }
-
- // Return value that was stored
- joint = e.second;
- return true;
- }
- }
-
- return false;
-}
-
-
-TkJointImpl* TkFamilyImpl::findExternalJoint(const TkFamilyImpl* otherFamily, ExternalJointKey key) const
-{
- const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(getFamilyID(otherFamily));
- if (jointSetIndexEntry != nullptr)
- {
- const HashMap<ExternalJointKey, TkJointImpl*>::type::Entry* e = m_jointSets[jointSetIndexEntry->second]->m_joints.find(key);
- if (e != nullptr)
- {
- return e->second;
- }
- }
-
- return nullptr;
-}
-
-} // namespace Blast
-} // namespace Nv
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastTkFamilyImpl.h"
+#include "NvBlastTkGroupImpl.h"
+#include "NvBlastTkAssetImpl.h"
+#include "NvBlastTkActorImpl.h"
+#include "NvBlastTkJointImpl.h"
+
+#include "NvBlastIndexFns.h"
+#include "NvBlastMemory.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+//////// Static data ////////
+
+NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(Family);
+
+
+//////// Member functions ////////
+
+TkFamilyImpl::TkFamilyImpl() : m_familyLL(nullptr), m_internalJointCount(0), m_asset(nullptr)
+{
+}
+
+
+TkFamilyImpl::TkFamilyImpl(const NvBlastID& id) : TkFamilyType(id), m_familyLL(nullptr), m_internalJointCount(0), m_asset(nullptr)
+{
+}
+
+
+TkFamilyImpl::~TkFamilyImpl()
+{
+ if (m_familyLL != nullptr)
+ {
+ uint32_t familyActorCount = NvBlastFamilyGetActorCount(m_familyLL, logLL);
+ if (familyActorCount != 0)
+ {
+ NVBLAST_LOG_WARNING("TkFamilyImpl::~TkFamilyImpl(): family actor count is not 0.");
+ }
+ NVBLAST_FREE(m_familyLL);
+ }
+}
+
+
+void TkFamilyImpl::release()
+{
+ for (TkActorImpl& actor : m_actors)
+ {
+ if (actor.isActive())
+ {
+ actor.release();
+ }
+ }
+
+ m_actors.clear();
+
+ NVBLAST_DELETE(this, TkFamilyImpl);
+}
+
+
+const NvBlastFamily* TkFamilyImpl::getFamilyLL() const
+{
+ return m_familyLL;
+}
+
+
+TkActorImpl* TkFamilyImpl::addActor(NvBlastActor* actorLL)
+{
+ TkActorImpl* actor = getActorByActorLL(actorLL);
+ NVBLAST_ASSERT(actor);
+ actor->m_actorLL = actorLL;
+ actor->m_family = this;
+ return actor;
+}
+
+
+void TkFamilyImpl::removeActor(TkActorImpl* actor)
+{
+ NVBLAST_ASSERT(actor != nullptr && actor->m_family == this);
+ //actor->m_family = nullptr;
+ actor->m_actorLL = nullptr;
+}
+
+
+uint32_t TkFamilyImpl::getActorCount() const
+{
+ return getActorCountInternal();
+}
+
+
+uint32_t TkFamilyImpl::getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart /*= 0*/) const
+{
+ uint32_t actorCount = getActorCount();
+ if (actorCount <= indexStart)
+ {
+ NVBLAST_LOG_WARNING("TkFamilyImpl::getActors: indexStart beyond end of actor list.");
+ return 0;
+ }
+
+ actorCount -= indexStart;
+ if (actorCount > bufferSize)
+ {
+ actorCount = static_cast<uint32_t>(bufferSize);
+ }
+
+ uint32_t index = 0;
+ for (const TkActorImpl& actor : m_actors)
+ {
+ if (actor.isActive())
+ {
+ if (index >= indexStart)
+ {
+ if ((index - indexStart) >= actorCount)
+ {
+ break;
+ }
+ else
+ {
+ *buffer++ = const_cast<TkActorImpl*>(&actor);
+ }
+ }
+ index++;
+ }
+ }
+
+ return actorCount;
+}
+
+
+NV_INLINE bool areLLActorsEqual(const NvBlastActor* actor0, const NvBlastActor* actor1, Array<uint32_t>::type& scratch)
+{
+ if (NvBlastActorGetGraphNodeCount(actor0, logLL) != NvBlastActorGetGraphNodeCount(actor1, logLL))
+ {
+ return false;
+ }
+
+ const uint32_t chunkCount = NvBlastActorGetVisibleChunkCount(actor0, logLL);
+ if (chunkCount != NvBlastActorGetVisibleChunkCount(actor1, logLL))
+ {
+ return false;
+ }
+
+ scratch.resize(chunkCount * 2);
+ NvBlastActorGetVisibleChunkIndices(scratch.begin(), chunkCount, actor0, logLL);
+ NvBlastActorGetVisibleChunkIndices(scratch.begin() + chunkCount, chunkCount, actor1, logLL);
+ return memcmp(scratch.begin(), scratch.begin() + chunkCount, chunkCount * sizeof(uint32_t)) == 0;
+}
+
+
+void TkFamilyImpl::reinitialize(const NvBlastFamily* newFamily, TkGroup* group)
+{
+ NVBLAST_ASSERT(newFamily);
+#if NV_ENABLE_ASSERTS
+ NvBlastID id0 = NvBlastFamilyGetAssetID(m_familyLL, logLL);
+ NvBlastID id1 = NvBlastFamilyGetAssetID(newFamily, logLL);
+ NVBLAST_ASSERT(TkGUIDsEqual(&id0, &id1));
+#endif
+ NVBLAST_ASSERT(NvBlastFamilyGetSize(m_familyLL, logLL) == NvBlastFamilyGetSize(newFamily, logLL));
+
+ // alloc and init new family
+ const uint32_t blockSize = NvBlastFamilyGetSize(newFamily, logLL);
+ NvBlastFamily* newFamilyCopy = (NvBlastFamily*)NVBLAST_ALLOC_NAMED(blockSize, "TkFamilyImpl::reinitialize");
+ memcpy(newFamilyCopy, newFamily, blockSize);
+ NvBlastFamilySetAsset(newFamilyCopy, m_asset->getAssetLL(), logLL);
+
+ // get actors from new family
+ Array<NvBlastActor*>::type newLLActors(NvBlastFamilyGetActorCount(newFamilyCopy, logLL));
+ uint32_t actorCount = NvBlastFamilyGetActors(newLLActors.begin(), newLLActors.size(), newFamilyCopy, logLL);
+
+ // reset actor families to nullptr (we use it as a flag later)
+ for (TkActorImpl& actor : m_actors)
+ {
+ if (actor.isActive())
+ {
+ actor.m_family = nullptr;
+ }
+ }
+
+ // prepare split event with new actors
+ auto newActorsSplitEvent = getQueue().allocData<TkSplitEvent>();
+ Array<TkActor*>::type children(actorCount);
+ children.resizeUninitialized(0);
+ newActorsSplitEvent->children = children.begin();
+
+ // scratch
+ Array<uint32_t>::type scratch(m_asset->getChunkCount());
+
+ for (uint32_t i = 0; i < actorCount; ++i)
+ {
+ NvBlastActor* newLLActor = newLLActors[i];
+ uint32_t actorIndex = NvBlastActorGetIndex(newLLActor, logLL);
+ TkActorImpl& tkActor = *getActorByIndex(actorIndex);
+
+ tkActor.m_family = this;
+
+ if (!tkActor.isActive() || !areLLActorsEqual(newLLActor, tkActor.m_actorLL, scratch))
+ {
+ if (tkActor.isActive())
+ {
+ auto removeSplitEvent = getQueue().allocData<TkSplitEvent>();
+ removeSplitEvent->parentData.family = this;
+ removeSplitEvent->numChildren = 0;
+ removeSplitEvent->parentData.userData = tkActor.userData;
+ removeSplitEvent->parentData.index = tkActor.getIndex();
+ getQueue().addEvent(removeSplitEvent);
+ }
+
+ tkActor.m_actorLL = newLLActor;
+
+ // switch groups
+ TkGroupImpl* prevGroup = tkActor.m_group;
+ if (prevGroup != group)
+ {
+ if (prevGroup)
+ {
+ prevGroup->removeActor(tkActor);
+ }
+ if (group)
+ {
+ group->addActor(tkActor);
+ }
+ }
+
+ children.pushBack(&tkActor);
+ }
+ else
+ {
+ tkActor.m_actorLL = newLLActor;
+ }
+ }
+
+ // if m_family is still nullptr for an active actor -> remove it. It doesn't exist in new family.
+ for (TkActorImpl& tkActor : m_actors)
+ {
+ if (tkActor.isActive() && tkActor.m_family == nullptr)
+ {
+ tkActor.m_family = this;
+ if (tkActor.m_group)
+ {
+ tkActor.m_group->removeActor(tkActor);
+ }
+
+ auto removeSplitEvent = getQueue().allocData<TkSplitEvent>();
+ removeSplitEvent->parentData.family = this;
+ removeSplitEvent->numChildren = 0;
+ removeSplitEvent->parentData.userData = tkActor.userData;
+ removeSplitEvent->parentData.index = tkActor.getIndex();
+ getQueue().addEvent(removeSplitEvent);
+
+ tkActor.m_actorLL = nullptr;
+ }
+ }
+
+ // add split event with all new actors
+ newActorsSplitEvent->parentData.family = this;
+ newActorsSplitEvent->parentData.userData = 0;
+ newActorsSplitEvent->parentData.index = invalidIndex<uint32_t>();
+ newActorsSplitEvent->numChildren = children.size();
+ if (newActorsSplitEvent->numChildren > 0)
+ {
+ getQueue().addEvent(newActorsSplitEvent);
+ }
+
+ // replace family
+ NVBLAST_FREE(m_familyLL);
+ m_familyLL = newFamilyCopy;
+
+ // update joints
+ for (TkActorImpl& tkActor : m_actors)
+ {
+ if (!tkActor.m_jointList.isEmpty())
+ {
+ updateJoints(&tkActor);
+ }
+ }
+
+ getQueue().dispatch();
+}
+
+
+TkActorImpl* TkFamilyImpl::getActorByChunk(uint32_t chunk)
+{
+ if (chunk >= NvBlastAssetGetChunkCount(m_asset->getAssetLLInternal(), logLL))
+ {
+ NVBLAST_LOG_WARNING("TkFamilyImpl::getActorByChunk: invalid chunk index. Returning NULL.");
+ return nullptr;
+ }
+
+ NvBlastActor* actorLL = NvBlastFamilyGetChunkActor(m_familyLL, chunk, logLL);
+ return actorLL ? getActorByActorLL(actorLL) : nullptr;
+}
+
+
+void TkFamilyImpl::applyFractureInternal(const NvBlastFractureBuffers* commands)
+{
+ NvBlastSupportGraph graph = getAsset()->getGraph();
+
+ // apply bond fracture commands on relevant actors
+ {
+ TkActorImpl* currActor = nullptr;
+ NvBlastBondFractureData* bondFractures = commands->bondFractures;
+ uint32_t bondFracturesCount = 0;
+
+ auto applyFracture = [&]()
+ {
+ if (bondFracturesCount > 0)
+ {
+ if (currActor != nullptr && currActor->isActive())
+ {
+ NvBlastFractureBuffers newCommands;
+ newCommands.bondFractures = bondFractures;
+ newCommands.bondFractureCount = bondFracturesCount;
+ newCommands.chunkFractures = nullptr;
+ newCommands.chunkFractureCount = 0;
+ currActor->applyFracture(nullptr, &newCommands);
+ }
+
+ bondFractures += bondFracturesCount;
+ bondFracturesCount = 0;
+ }
+ };
+
+ for (uint32_t i = 0; i < commands->bondFractureCount; ++i, ++bondFracturesCount)
+ {
+ const NvBlastBondFractureData& command = commands->bondFractures[i];
+ uint32_t chunk0 = graph.chunkIndices[command.nodeIndex0];
+ uint32_t chunk1 = graph.chunkIndices[command.nodeIndex1];
+ TkActorImpl* actor0 = getActorByChunk(chunk0);
+ TkActorImpl* actor1 = getActorByChunk(chunk1);
+ if (actor0 != actor1)
+ {
+ // skipping this event, bond already broken
+ actor0 = nullptr;
+ }
+ if (actor0 != currActor)
+ {
+ applyFracture();
+ currActor = actor0;
+ }
+ }
+
+ if (bondFracturesCount > 0)
+ {
+ applyFracture();
+ }
+ }
+
+ // apply chunk fracture commands on relevant actors
+ {
+ TkActorImpl* currActor = nullptr;
+ NvBlastChunkFractureData* chunkFractures = commands->chunkFractures;
+ uint32_t chunkFracturesCount = 0;
+
+ auto applyFracture = [&]()
+ {
+ if (chunkFracturesCount > 0)
+ {
+ if (currActor != nullptr && currActor->isActive())
+ {
+ NvBlastFractureBuffers newCommands;
+ newCommands.bondFractures = nullptr;
+ newCommands.bondFractureCount = 0;
+ newCommands.chunkFractures = chunkFractures;
+ newCommands.chunkFractureCount = chunkFracturesCount;
+ currActor->applyFracture(nullptr, &newCommands);
+ }
+
+ chunkFractures += chunkFracturesCount;
+ chunkFracturesCount = 0;
+ }
+ };
+
+ for (uint32_t i = 0; i < commands->chunkFractureCount; ++i, ++chunkFracturesCount)
+ {
+ const NvBlastChunkFractureData& command = commands->chunkFractures[i];
+ TkActorImpl* actor = getActorByChunk(command.chunkIndex);
+ if (actor != currActor)
+ {
+ applyFracture();
+ currActor = actor;
+ }
+ }
+ if (chunkFracturesCount > 0)
+ {
+ applyFracture();
+ }
+ }
+}
+
+
+void TkFamilyImpl::updateJoints(TkActorImpl* actor, TkEventQueue* alternateQueue)
+{
+ // Copy joint array for safety against implementation of joint->setActor
+ TkJointImpl** joints = reinterpret_cast<TkJointImpl**>(NvBlastAlloca(sizeof(TkJointImpl*)*actor->getJointCountInternal()));
+ TkJointImpl** stop = joints + actor->getJointCountInternal();
+ TkJointImpl** jointHandle = joints;
+ for (TkActorImpl::JointIt j(*actor); (bool)j; ++j)
+ {
+ *jointHandle++ = *j;
+ }
+ jointHandle = joints;
+ while (jointHandle < stop)
+ {
+ TkJointImpl* joint = *jointHandle++;
+
+ const TkJointData& data = joint->getDataInternal();
+
+ TkActorImpl* actor0 = data.actors[0] != nullptr ?
+ static_cast<TkActorImpl&>(*data.actors[0]).getFamilyImpl().getActorByChunk(data.chunkIndices[0]) : nullptr;
+
+ TkActorImpl* actor1 = data.actors[1] != nullptr ?
+ static_cast<TkActorImpl&>(*data.actors[1]).getFamilyImpl().getActorByChunk(data.chunkIndices[1]) : nullptr;
+
+ joint->setActors(actor0, actor1, alternateQueue);
+ }
+}
+
+
+const TkAsset* TkFamilyImpl::getAsset() const
+{
+ return m_asset;
+}
+
+
+//////// Static functions ////////
+
+TkFamilyImpl* TkFamilyImpl::create(const TkAssetImpl* asset)
+{
+ TkFamilyImpl* family = NVBLAST_NEW(TkFamilyImpl);
+ family->m_asset = asset;
+ void* mem = NVBLAST_ALLOC_NAMED(NvBlastAssetGetFamilyMemorySize(asset->getAssetLL(), logLL), "TkFamilyImpl::create");
+ family->m_familyLL = NvBlastAssetCreateFamily(mem, asset->getAssetLL(), logLL);
+ //family->addListener(*TkFrameworkImpl::get());
+
+ if (family->m_familyLL == nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkFamilyImpl::create: low-level family could not be created.");
+ family->release();
+ return nullptr;
+ }
+
+ uint32_t maxActorCount = NvBlastFamilyGetMaxActorCount(family->m_familyLL, logLL);
+ family->m_actors.resize(maxActorCount);
+
+ family->m_internalJointBuffer.resize(asset->getJointDescCountInternal() * sizeof(TkJointImpl), 0);
+ family->m_internalJointCount = asset->getJointDescCountInternal();
+
+ return family;
+}
+
+
+TkJointImpl** TkFamilyImpl::createExternalJointHandle(const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1)
+{
+ JointSet* jointSet;
+ const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(otherFamilyID);
+ uint32_t otherFamilyIndex;
+ if (jointSetIndexEntry != nullptr)
+ {
+ otherFamilyIndex = jointSetIndexEntry->second;
+ jointSet = m_jointSets[otherFamilyIndex];
+ }
+ else
+ {
+ jointSet = NVBLAST_NEW(JointSet);
+ NVBLAST_CHECK_ERROR(jointSet != nullptr, "TkFamilyImpl::addExternalJoint: failed to create joint set for other family ID.", return nullptr);
+ jointSet->m_familyID = otherFamilyID;
+ otherFamilyIndex = m_jointSets.size();
+ m_familyIDMap[otherFamilyID] = otherFamilyIndex;
+ m_jointSets.pushBack(jointSet);
+ }
+
+ const ExternalJointKey key(chunkIndex0, chunkIndex1);
+ const bool jointExists = jointSet->m_joints.find(key) != nullptr;
+ NVBLAST_CHECK_WARNING(!jointExists, "TkFamilyImpl::addExternalJoint: joint already added.", return nullptr);
+
+ return &jointSet->m_joints[key];
+}
+
+
+bool TkFamilyImpl::deleteExternalJointHandle(TkJointImpl*& joint, const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1)
+{
+ const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(otherFamilyID);
+ if (jointSetIndexEntry != nullptr)
+ {
+ const uint32_t jointSetIndex = jointSetIndexEntry->second;
+ HashMap<ExternalJointKey, TkJointImpl*>::type::Entry e;
+ if (m_jointSets[jointSetIndex]->m_joints.erase(ExternalJointKey(chunkIndex0, chunkIndex1), e))
+ {
+ // Delete the joint set if it is empty
+ if (m_jointSets[jointSetIndex]->m_joints.size() == 0)
+ {
+ NVBLAST_DELETE(m_jointSets[jointSetIndex], JointSet);
+ m_jointSets.replaceWithLast(jointSetIndex);
+ m_familyIDMap.erase(otherFamilyID);
+ if (jointSetIndex < m_jointSets.size())
+ {
+ m_familyIDMap[m_jointSets[jointSetIndex]->m_familyID] = jointSetIndex;
+ }
+ }
+
+ // Return value that was stored
+ joint = e.second;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+TkJointImpl* TkFamilyImpl::findExternalJoint(const TkFamilyImpl* otherFamily, ExternalJointKey key) const
+{
+ const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(getFamilyID(otherFamily));
+ if (jointSetIndexEntry != nullptr)
+ {
+ const HashMap<ExternalJointKey, TkJointImpl*>::type::Entry* e = m_jointSets[jointSetIndexEntry->second]->m_joints.find(key);
+ if (e != nullptr)
+ {
+ return e->second;
+ }
+ }
+
+ return nullptr;
+}
+
+} // namespace Blast
+} // namespace Nv