aboutsummaryrefslogtreecommitdiff
path: root/NvBlast/sdk/toolkit/source/NvBlastTkActorImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NvBlast/sdk/toolkit/source/NvBlastTkActorImpl.cpp')
-rw-r--r--NvBlast/sdk/toolkit/source/NvBlastTkActorImpl.cpp434
1 files changed, 434 insertions, 0 deletions
diff --git a/NvBlast/sdk/toolkit/source/NvBlastTkActorImpl.cpp b/NvBlast/sdk/toolkit/source/NvBlastTkActorImpl.cpp
new file mode 100644
index 0000000..028e0f1
--- /dev/null
+++ b/NvBlast/sdk/toolkit/source/NvBlastTkActorImpl.cpp
@@ -0,0 +1,434 @@
+/*
+* 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.
+*/
+
+#include "NvBlastPreprocessor.h"
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastTkActorImpl.h"
+#include "NvBlastTkGroupImpl.h"
+#include "NvBlastTkAssetImpl.h"
+#include "NvBlastTkFamilyImpl.h"
+#include "NvBlastTkJointImpl.h"
+
+#include "NvBlast.h"
+#include "NvBlastAssert.h"
+#include "NvBlastMemory.h"
+
+#include "Px.h"
+#include "PxFileBuf.h"
+#include "PxAllocatorCallback.h"
+#include "PxTransform.h"
+
+using namespace physx::general_PxIOStream2;
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+TkActorImpl* TkActorImpl::create(const TkActorDesc& desc)
+{
+ const TkAssetImpl* asset = static_cast<const TkAssetImpl*>(desc.asset);
+
+ TkFamilyImpl* family = TkFamilyImpl::create(asset);
+
+ NvBlastFamily* familyLL = family->getFamilyLLInternal();
+ TkArray<char>::type scratch((uint32_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(familyLL, TkFrameworkImpl::get()->log));
+ NvBlastActor* actorLL = NvBlastFamilyCreateFirstActor(familyLL, &desc, scratch.begin(), TkFrameworkImpl::get()->log);
+ if (actorLL == nullptr)
+ {
+ NVBLASTTK_LOG_ERROR("TkActorImpl::create: low-level actor could not be created.");
+ return nullptr;
+ }
+
+ TkActorImpl* actor = family->addActor(actorLL);
+
+ // Add internal joints
+ if (actor != nullptr)
+ {
+ const uint32_t internalJointCount = asset->getJointDescCountInternal();
+ const TkAssetJointDesc* jointDescs = asset->getJointDescsInternal();
+ const NvBlastSupportGraph graph = asset->getGraph();
+ TkJointImpl* joints = family->getInternalJoints();
+ for (uint32_t jointNum = 0; jointNum < internalJointCount; ++jointNum)
+ {
+ const TkAssetJointDesc& assetJointDesc = jointDescs[jointNum];
+ NVBLAST_ASSERT(assetJointDesc.nodeIndices[0] < graph.nodeCount && assetJointDesc.nodeIndices[1] < graph.nodeCount);
+ TkJointDesc jointDesc;
+ jointDesc.families[0] = jointDesc.families[1] = family;
+ jointDesc.chunkIndices[0] = graph.chunkIndices[assetJointDesc.nodeIndices[0]];
+ jointDesc.chunkIndices[1] = graph.chunkIndices[assetJointDesc.nodeIndices[1]];
+ jointDesc.attachPositions[0] = assetJointDesc.attachPositions[0];
+ jointDesc.attachPositions[1] = assetJointDesc.attachPositions[1];
+ TkJointImpl* joint = new (joints + jointNum) TkJointImpl(jointDesc, family);
+ actor->addJoint(joint->m_links[0]);
+ }
+ }
+
+ return actor;
+}
+
+
+//////// Member functions ////////
+
+TkActorImpl::TkActorImpl()
+ : m_actorLL(nullptr)
+ , m_family(nullptr)
+ , m_group(nullptr)
+ , m_groupJobIndex(invalidIndex<uint32_t>())
+ , m_flags(0)
+ , m_jointCount(0)
+{
+#if NV_PROFILE
+ NvBlastTimersReset(&m_timers);
+#endif
+}
+
+
+TkActorImpl::~TkActorImpl()
+{
+}
+
+
+void TkActorImpl::release()
+{
+ // Disassoaciate all joints
+
+ // Copy joint array for safety against implementation of joint->setActor
+ TkJointImpl** joints = reinterpret_cast<TkJointImpl**>(NvBlastAlloca(sizeof(TkJointImpl*)*getJointCountInternal()));
+ TkJointImpl** stop = joints + getJointCountInternal();
+ TkJointImpl** jointHandle = joints;
+ for (JointIt j(*this); (bool)j; ++j)
+ {
+ *jointHandle++ = *j;
+ }
+ jointHandle = joints;
+ while (jointHandle < stop)
+ {
+ NVBLAST_ASSERT(*jointHandle != nullptr);
+ NVBLAST_ASSERT((*jointHandle)->getDataInternal().actors[0] == this || (*jointHandle)->getDataInternal().actors[1] == this);
+ (*jointHandle++)->setActors(nullptr, nullptr);
+ }
+ NVBLAST_ASSERT(getJointCountInternal() == 0);
+
+ if (m_group != nullptr)
+ {
+ m_group->removeActor(*this);
+ }
+
+ if (m_actorLL != nullptr)
+ {
+ NvBlastActorDeactivate(m_actorLL, TkFrameworkImpl::get()->log);
+ }
+
+ if (m_family != nullptr)
+ {
+ m_family->removeActor(this);
+
+ // Make sure we dispatch any remaining events when this family is emptied, since it will no longer be done by any group
+ if (m_family->getActorCountInternal() == 0)
+ {
+ m_family->getQueue().dispatch();
+ }
+ }
+}
+
+
+const NvBlastActor* TkActorImpl::getActorLL() const
+{
+ return m_actorLL;
+}
+
+
+TkFamily& TkActorImpl::getFamily() const
+{
+ return getFamilyImpl();
+}
+
+
+uint32_t TkActorImpl::getIndex() const
+{
+ return getIndexInternal();
+}
+
+
+TkGroup* TkActorImpl::getGroup() const
+{
+ return getGroupImpl();
+}
+
+
+TkGroup* TkActorImpl::removeFromGroup()
+{
+ if (m_group == nullptr)
+ {
+ NVBLASTTK_LOG_WARNING("TkActorImpl::removeFromGroup: actor not in a group.");
+ return nullptr;
+ }
+
+ if (m_group->isProcessing())
+ {
+ NVBLASTTK_LOG_ERROR("TkActorImpl::removeFromGroup: cannot alter Group while processing.");
+ return nullptr;
+ }
+
+ TkGroup* group = m_group;
+
+ return m_group->removeActor(*this) ? group : nullptr;
+}
+
+
+NvBlastFamily* TkActorImpl::getFamilyLL() const
+{
+ return m_family->getFamilyLLInternal();
+}
+
+
+const TkAsset* TkActorImpl::getAsset() const
+{
+ return m_family->getAssetImpl();
+}
+
+
+uint32_t TkActorImpl::getVisibleChunkCount() const
+{
+ return NvBlastActorGetVisibleChunkCount(m_actorLL, TkFrameworkImpl::get()->log);
+}
+
+
+uint32_t TkActorImpl::getVisibleChunkIndices(uint32_t* visibleChunkIndices, uint32_t visibleChunkIndicesSize) const
+{
+ return NvBlastActorGetVisibleChunkIndices(visibleChunkIndices, visibleChunkIndicesSize, m_actorLL, TkFrameworkImpl::get()->log);
+}
+
+
+uint32_t TkActorImpl::getGraphNodeCount() const
+{
+ return NvBlastActorGetGraphNodeCount(m_actorLL, TkFrameworkImpl::get()->log);
+}
+
+
+uint32_t TkActorImpl::getGraphNodeIndices(uint32_t* graphNodeIndices, uint32_t graphNodeIndicesSize) const
+{
+ return NvBlastActorGetGraphNodeIndices(graphNodeIndices, graphNodeIndicesSize, m_actorLL, TkFrameworkImpl::get()->log);
+}
+
+
+const float* TkActorImpl::getBondHealths() const
+{
+ return NvBlastActorGetBondHealths(m_actorLL, TkFrameworkImpl::get()->log);
+}
+
+
+uint32_t TkActorImpl::getSplitMaxActorCount() const
+{
+ return NvBlastActorGetMaxActorCountForSplit(m_actorLL, TkFrameworkImpl::get()->log);
+}
+
+
+bool TkActorImpl::isDamaged() const
+{
+ NVBLAST_ASSERT(!m_flags.isSet(TkActorFlag::DAMAGED) || (m_flags.isSet(TkActorFlag::DAMAGED) && m_flags.isSet(TkActorFlag::PENDING)));
+ return m_flags.isSet(TkActorFlag::DAMAGED);
+}
+
+
+void TkActorImpl::markAsDamaged()
+{
+ m_flags |= TkActorFlag::DAMAGED;
+ makePending();
+}
+
+
+void TkActorImpl::makePending()
+{
+ if (m_group != nullptr && !isPending())
+ {
+ m_group->enqueue(this);
+ }
+
+ m_flags |= TkActorFlag::PENDING;
+}
+
+
+TkActorImpl::operator Nv::Blast::TkActorData() const
+{
+ TkActorData data = { m_family, userData, getIndex() };
+ return data;
+}
+
+
+void TkActorImpl::damage(const NvBlastDamageProgram& program, const NvBlastProgramParams* programParams)
+{
+ PERF_SCOPE_L("TkActor::damage");
+
+ if (m_group == nullptr)
+ {
+ NVBLASTTK_LOG_WARNING("TkActor::damage: actor is not in a group, cannot fracture.");
+ return;
+ }
+
+ if (m_group->isProcessing())
+ {
+ NVBLASTTK_LOG_WARNING("TkActor::damage: group is being processed, cannot fracture this actor.");
+ return;
+ }
+
+ if (NvBlastActorCanFracture(m_actorLL, TkFrameworkImpl::get()->log))
+ {
+ m_damageBuffer.pushBack(DamageData(program, programParams));
+ makePending();
+ }
+}
+
+
+void TkActorImpl::damage(const NvBlastDamageProgram& program, const void* damageDesc, uint32_t descSize)
+{
+ damage(program, damageDesc, descSize, m_family->getMaterial());
+}
+
+
+void TkActorImpl::damage(const NvBlastDamageProgram& program, const void* damageDesc, uint32_t descSize, const void* material)
+{
+ PERF_SCOPE_L("TkActor::damage");
+
+ if (m_group == nullptr)
+ {
+ NVBLASTTK_LOG_WARNING("TkActor::damage: actor is not in a group, cannot fracture.");
+ return;
+ }
+
+ if (m_group->isProcessing())
+ {
+ NVBLASTTK_LOG_WARNING("TkActor::damage: group is being processed, cannot fracture this actor.");
+ return;
+ }
+
+ if (NvBlastActorCanFracture(m_actorLL, TkFrameworkImpl::get()->log))
+ {
+ bool appended = false;
+ for (auto& damageData : m_damageBuffer)
+ {
+ if (damageData.tryAppend(program, material, damageDesc, descSize))
+ {
+ appended = true;
+ break;
+ }
+ }
+
+ if (!appended)
+ {
+ m_damageBuffer.pushBack(DamageData(program, material, damageDesc, descSize));
+ }
+
+ makePending();
+ }
+}
+
+
+void TkActorImpl::generateFracture(NvBlastFractureBuffers* commands, const NvBlastDamageProgram& program, const NvBlastProgramParams* programParams) const
+{
+ PERF_SCOPE_L("TkActor::generateFracture");
+
+ if (m_group && m_group->isProcessing())
+ {
+ NVBLASTTK_LOG_WARNING("TkActor::generateFracture: group is being processed, cannot fracture this actor.");
+ return;
+ }
+
+ // const context, must make m_timers mutable otherwise
+ NvBlastActorGenerateFracture(commands, m_actorLL, program, programParams, TkFrameworkImpl::get()->log, const_cast<NvBlastTimers*>(&m_timers));
+}
+
+
+void TkActorImpl::applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands)
+{
+ PERF_SCOPE_L("TkActor::applyFracture");
+
+ if (m_group && m_group->isProcessing())
+ {
+ NVBLASTTK_LOG_WARNING("TkActor::applyFracture: group is being processed, cannot fracture this actor.");
+ return;
+ }
+
+ NvBlastActorApplyFracture(eventBuffers, m_actorLL, commands, TkFrameworkImpl::get()->log, &m_timers);
+
+ if (commands->chunkFractureCount > 0 || commands->bondFractureCount > 0)
+ {
+ markAsDamaged();
+
+ TkFractureCommands* fevt = getFamilyImpl().getQueue().allocData<TkFractureCommands>();
+ fevt->tkActorData = *this;
+ fevt->buffers = *commands;
+ getFamilyImpl().getQueue().addEvent(fevt);
+ getFamilyImpl().getQueue().dispatch();
+ }
+}
+
+
+uint32_t TkActorImpl::getJointCount() const
+{
+ return getJointCountInternal();
+}
+
+
+uint32_t TkActorImpl::getJoints(TkJoint** joints, uint32_t jointsSize) const
+{
+ uint32_t jointsWritten = 0;
+
+ for (JointIt j(*this); (bool)j && jointsWritten < jointsSize; ++j)
+ {
+ joints[jointsWritten++] = *j;
+ }
+
+ return jointsWritten;
+}
+
+
+//////// TkActorImpl::DamageData methods ////////
+
+static bool operator==(const NvBlastDamageProgram& lhs, const NvBlastDamageProgram& rhs)
+{
+ return lhs.graphShaderFunction == rhs.graphShaderFunction && lhs.subgraphShaderFunction == rhs.subgraphShaderFunction;
+}
+
+
+TkActorImpl::DamageData::DamageData(const NvBlastDamageProgram& program, const NvBlastProgramParams* params)
+ : m_program(program), m_programParams(params), m_damageDescCount(0)
+{
+}
+
+
+TkActorImpl::DamageData::DamageData(const NvBlastDamageProgram& program, const void* material, const void* desc, uint32_t descSize)
+ : m_program(program), m_material(material), m_damageDescs((char*)desc, (char*)desc + descSize), m_damageDescCount(1)
+{
+}
+
+
+bool TkActorImpl::DamageData::tryAppend(const NvBlastDamageProgram& program, const void* material, const void* desc, uint32_t descSize)
+{
+ if (getType() == Buffered && m_program == program && m_material == material)
+ {
+ const uint32_t currentDescSize = m_damageDescs.size() / m_damageDescCount;
+ if (descSize == currentDescSize)
+ {
+ const uint32_t s = m_damageDescs.size();
+ m_damageDescs.resizeUninitialized(s + static_cast<uint32_t>(descSize));
+ memcpy(m_damageDescs.begin() + s, desc, descSize);
+ m_damageDescCount++;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace Blast
+} // namespace Nv