aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/module/destructible/include/DestructibleActorImpl.h
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/module/destructible/include/DestructibleActorImpl.h
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'APEX_1.4/module/destructible/include/DestructibleActorImpl.h')
-rw-r--r--APEX_1.4/module/destructible/include/DestructibleActorImpl.h975
1 files changed, 975 insertions, 0 deletions
diff --git a/APEX_1.4/module/destructible/include/DestructibleActorImpl.h b/APEX_1.4/module/destructible/include/DestructibleActorImpl.h
new file mode 100644
index 00000000..1b258347
--- /dev/null
+++ b/APEX_1.4/module/destructible/include/DestructibleActorImpl.h
@@ -0,0 +1,975 @@
+/*
+ * Copyright (c) 2008-2015, 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.
+ */
+
+
+#ifndef __DESTRUCTIBLEACTOR_IMPL_H__
+#define __DESTRUCTIBLEACTOR_IMPL_H__
+
+#include "Apex.h"
+#include "ApexActor.h"
+#include "DestructibleAssetProxy.h"
+#include "DestructibleActorState.h"
+#include "DestructibleActor.h"
+#include "DestructibleStructure.h"
+#include "RenderMeshAssetIntl.h"
+#include "ResourceProviderIntl.h"
+#include "DestructibleRenderableImpl.h"
+#if APEX_RUNTIME_FRACTURE
+#include "SimScene.h"
+#include "../fracture/Actor.h"
+#endif
+
+namespace nvidia
+{
+namespace apex
+{
+class PhysXObjectDescIntl;
+class EmitterActor;
+}
+namespace destructible
+{
+
+class DestructibleScene;
+class DestructibleActorProxy;
+class DestructibleActorJointImpl;
+
+struct PhysXActorFlags
+{
+ enum Enum
+ {
+ DEPTH_PARAM_USER_FLAG_0 = 0,
+ DEPTH_PARAM_USER_FLAG_1,
+ DEPTH_PARAM_USER_FLAG_2,
+ DEPTH_PARAM_USER_FLAG_3,
+ CREATED_THIS_FRAME,
+ IS_SLEEPING // external sleep state tracking to be in sync with mAwakeActorCount that is updated in onWake/onSleep callbacks
+ };
+};
+
+PX_INLINE void PxBounds3Transform(PxBounds3& b, const PxMat44& tm)
+{
+ b = PxBounds3::basisExtent(tm.transform(b.getCenter()), PxMat33(tm.getBasis(0), tm.getBasis(1), tm.getBasis(2)), b.getExtents());
+}
+
+class DestructibleActorImpl : public ApexResource
+ , public ApexActorSource
+ , public ApexActor
+ , public NvParameterized::SerializationCallback
+{
+public:
+
+ friend class DestructibleActorProxy;
+ friend class DestructibleRenderableImpl;
+ friend class DestructibleScopedReadLock;
+ friend class DestructibleScopedWriteLock;
+
+ enum
+ {
+ InvalidID = 0xFFFFFFFF
+ };
+
+ enum Flag
+ {
+ Dynamic = (1 << 0)
+ };
+
+ enum InternalFlag
+ {
+ IslandMarker = (1 << 15)
+ };
+
+public:
+
+ void setState(NvParameterized::Interface* state);
+ const DestructibleActorState* getState() const { return mState; }
+ const DestructibleActorChunks* getChunks() const { return mChunks; }
+ DestructibleActorChunks* getChunks() { return mChunks; }
+ const DestructibleActorParam* getParams() const { return mParams; }
+ DestructibleActorParam* getParams() { return mParams; }
+ const DestructibleParameters& getDestructibleParameters() const { return mDestructibleParameters; }
+ DestructibleParameters& getDestructibleParameters() { return mDestructibleParameters; }
+ void setDestructibleParameters(const DestructibleParameters& destructibleParameters);
+ const DestructibleScene* getDestructibleScene() const { return mDestructibleScene; }
+ DestructibleScene* getDestructibleScene() { return mDestructibleScene; }
+ const DestructibleActor* getAPI() const { return mAPI; }
+ DestructibleActor* getAPI() { return mAPI; }
+
+ void incrementWakeCount(void);
+ void decrementWakeCount(void);
+ void removeActorAtIndex(uint32_t index);
+
+ void setPhysXScene(PxScene*);
+ PxScene* getPhysXScene() const;
+
+ void release();
+ void destroy();
+ void reset();
+
+ virtual void getLodRange(float& min, float& max, bool& intOnly) const;
+ virtual float getActiveLod() const;
+ virtual void forceLod(float lod);
+
+ void cacheModuleData() const;
+ void removeSelfFromStructure();
+ void removeSelfFromScene();
+ bool isInitiallyDynamic() const { return 0 != (getFlags() & (uint32_t)Dynamic); }
+ uint16_t getFlags() const { return mFlags; }
+ uint16_t getInternalFlags() const { return mInternalFlags; }
+ uint16_t& getInternalFlags() { return mInternalFlags; }
+ DestructibleStructure* getStructure() { return mStructure; }
+ const DestructibleStructure*getStructure() const { return mStructure; }
+ void setStructure(DestructibleStructure* s) { mStructure = s; }
+ DestructibleAssetImpl* getDestructibleAsset() { return mAsset; }
+ const DestructibleAssetImpl* getDestructibleAsset() const { return mAsset; }
+ uint32_t getID() const { return mID; }
+ uint32_t& getIDRef() { return mID; }
+ const PxBounds3& getOriginalBounds() const { return mOriginalBounds; }
+ uint32_t getFirstChunkIndex() const { return mFirstChunkIndex; }
+ void setFirstChunkIndex(uint32_t i) { mFirstChunkIndex = i; }
+ const EmitterActor* getCrumbleEmitter() const { return mCrumbleEmitter; }
+ EmitterActor* getCrumbleEmitter() { return mCrumbleEmitter; }
+ float getCrumbleParticleSpacing() const;
+ const EmitterActor* getDustEmitter() const { return mDustEmitter; }
+ EmitterActor* getDustEmitter() { return mDustEmitter; }
+ float getDustParticleSpacing() const;
+ const PxMat44& getInitialGlobalPose() const { return mTM; }
+ void setInitialGlobalPose(const PxMat44& pose);
+ const PxVec3& getScale() const { return mParams->scale; }
+ void setCrumbleEmitterEnabled(bool enabled) { mState->enableCrumbleEmitter = enabled; }
+ bool isCrumbleEmitterEnabled() const { return mState->enableCrumbleEmitter; }
+ void setDustEmitterEnabled(bool enabled) { mState->enableDustEmitter = enabled; }
+ bool isDustEmitterEnabled() const { return mState->enableDustEmitter; }
+ void setCrumbleEmitterName(const char*);
+ const char* getCrumbleEmitterName() const;
+ void setDustEmitterName(const char*);
+ const char* getDustEmitterName() const;
+
+ uint32_t getSupportDepth() const { return mParams->supportDepth; }
+ bool formExtendedStructures() const { return mParams->formExtendedStructures; }
+ bool performDetailedOverlapTestForExtendedStructures() const { return mParams->performDetailedOverlapTestForExtendedStructures; }
+ bool useAssetDefinedSupport() const { return mParams->useAssetDefinedSupport; }
+ bool useWorldSupport() const { return mParams->useWorldSupport; }
+ bool drawStaticChunksInSeparateMesh() const { return mParams->renderStaticChunksSeparately; }
+ bool keepVisibleBonesPacked() const { return mParams->keepVisibleBonesPacked; }
+ bool createChunkEvents() const { return mParams->createChunkEvents; }
+ bool keepPreviousFrameBoneBuffer() const { return mParams->keepPreviousFrameBoneBuffer; }
+ float getSleepVelocityFrameDecayConstant() const { return mParams->sleepVelocityFrameDecayConstant; }
+ bool useHardSleeping() const { return mParams->useHardSleeping; }
+ bool useStressSolver() const { return mParams->structureSettings.useStressSolver; }
+ float getStressSolverTimeDelay() const { return mParams->structureSettings.stressSolverTimeDelay; }
+ float getStressSolverMassThreshold() const { return mParams->structureSettings.stressSolverMassThreshold; }
+
+ void enableHardSleeping();
+ void disableHardSleeping(bool wake);
+ bool setChunkPhysXActorAwakeState(uint32_t chunkIndex, bool awake);
+ bool addForce(uint32_t chunkIndex, const PxVec3& force, physx::PxForceMode::Enum mode, const PxVec3* position = NULL, bool wakeup = true);
+
+ uint32_t getLOD() const { return mState->lod; }
+
+ uint32_t getRenderSubmeshCount()
+ {
+ return mAsset->getRenderMeshAsset()->getSubmeshCount();
+ }
+ uint32_t getAwakeActorCount() const { return mAwakeActorCount; }
+#if APEX_RUNTIME_FRACTURE
+ ::nvidia::fracture::Actor* getRTActor()
+ {
+ return mRTActor;
+ }
+#endif
+
+ void setGlobalPose(const PxMat44& pose);
+ void setGlobalPoseForStaticChunks(const PxMat44& pose);
+ bool getGlobalPoseForStaticChunks(PxMat44& pose) const;
+
+ void setChunkPose(uint32_t index, PxTransform worldPose);
+ void setLinearVelocity(const PxVec3& linearVelocity);
+ void setAngularVelocity(const PxVec3& angularVelocity);
+
+ void setDynamic(int32_t chunkIndex = ModuleDestructibleConst::INVALID_CHUNK_INDEX, bool immediate = false);
+ bool getDynamic(int32_t chunkIndex) const
+ {
+ PX_ASSERT(mAsset != NULL && mStructure != NULL && chunkIndex >= 0 && chunkIndex < (int32_t)mAsset->getChunkCount());
+ DestructibleStructure::Chunk& chunk = mStructure->chunks[mFirstChunkIndex + chunkIndex];
+ return (chunk.state & ChunkDynamic) != 0;
+ }
+
+ void getChunkVisibilities(uint8_t* visibilityArray, uint32_t visibilityArraySize) const;
+ void setChunkVisibility(uint16_t index, bool visibility);
+
+ // Chunk event buffer API
+ bool acquireChunkEventBuffer(const DestructibleChunkEvent*& buffer, uint32_t& bufferSize);
+ bool releaseChunkEventBuffer(bool clearBuffer = true);
+
+ // PhysX actor buffer API
+ bool acquirePhysXActorBuffer(physx::PxRigidDynamic**& buffer, uint32_t& bufferSize, uint32_t flags);
+ bool releasePhysXActorBuffer();
+
+ float getContactReportThreshold(const DestructibleStructure::Chunk& chunk) const
+ {
+ const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = getBehaviorGroup(chunk.indexInAsset);
+ return getContactReportThreshold(behaviorGroup);
+ }
+
+ float getContactReportThreshold(const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup) const
+ {
+ float contactReportThreshold = PX_MAX_F32;
+ if (mDestructibleParameters.forceToDamage > 0)
+ {
+ const float maxEstimatedTimeStep = 0.1f;
+ const float thresholdFraction = 0.5f;
+ const float damageThreshold = behaviorGroup.damageThreshold;
+ contactReportThreshold = thresholdFraction * maxEstimatedTimeStep * damageThreshold / mDestructibleParameters.forceToDamage;
+ }
+
+ return contactReportThreshold;
+ }
+
+ float getAge(float elapsedTime) const { return elapsedTime - mStartTime; }
+
+ bool getUseLegacyChunkBoundsTesting() const;
+ bool getUseLegacyDamageRadiusSpread() const;
+
+ const IndexBank<uint16_t>& getStaticRoots() const { return mStaticRoots; }
+ IndexBank<uint16_t>& getStaticRoots() { return mStaticRoots; }
+
+ uint32_t getNumVisibleChunks() const { return mVisibleChunks.usedCount(); }
+ const uint16_t* getVisibleChunks() const { return mVisibleChunks.usedIndices(); }
+ bool initializedFromState() const { return mInitializedFromState; }
+
+ uint32_t getVisibleDynamicChunkShapeCount() const { return mVisibleDynamicChunkShapeCount; }
+ uint32_t getEssentialVisibleDynamicChunkShapeCount() const { return mEssentialVisibleDynamicChunkShapeCount; }
+
+ void increaseVisibleDynamicChunkShapeCount(const uint32_t number) { mVisibleDynamicChunkShapeCount += number; }
+ void increaseEssentialVisibleDynamicChunkShapeCount(const uint32_t number) { mEssentialVisibleDynamicChunkShapeCount += number; }
+
+ void initializeChunk(uint32_t index, DestructibleStructure::Chunk& chunk) const;
+ bool getInitialChunkDynamic(uint32_t index) const;
+ bool getInitialChunkVisible(uint32_t index) const;
+ bool getInitialChunkDestroyed(uint32_t index) const;
+ PxTransform getInitialChunkGlobalPose(uint32_t index) const;
+ PxTransform getInitialChunkLocalPose(uint32_t index) const;
+ PxVec3 getInitialChunkLinearVelocity(uint32_t index) const;
+ PxVec3 getInitialChunkAngularVelocity(uint32_t index) const;
+ PxTransform getChunkPose(uint32_t index) const;
+ PxTransform getChunkTransform(uint32_t index) const;
+ PxVec3 getChunkLinearVelocity(uint32_t index) const;
+ PxVec3 getChunkAngularVelocity(uint32_t index) const;
+ const PxRigidDynamic* getChunkActor(uint32_t index) const;
+ PxRigidDynamic* getChunkActor(uint32_t index);
+ uint32_t getChunkPhysXShapes(physx::PxShape**& shapes, uint32_t chunkIndex) const;
+ uint32_t getChunkCount() const { return getDestructibleAsset()->getChunkCount(); }
+ const DestructibleStructure::Chunk& getChunk(uint32_t index) const;
+
+ void setBenefit(float benefit) { mBenefit = benefit; }
+ float getBenefit() const { return mBenefit; }
+
+ float getChunkMass(uint32_t index) const
+ {
+ float volume = 0.0f;
+ for (uint32_t hullIndex = mAsset->getChunkHullIndexStart(index); hullIndex < mAsset->getChunkHullIndexStop(index); ++hullIndex)
+ {
+ volume += PxAbs(mAsset->chunkConvexHulls[hullIndex].mParams->volume);
+ }
+
+ // override actor descriptor if (behaviorGroup.density > 0)
+ const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = getBehaviorGroup(index);
+ float density = behaviorGroup.density;
+ if (density == 0)
+ {
+ density = physX3Template.data.density;
+ }
+ return volume * density * PxAbs(getScale().x * getScale().y * getScale().z);
+ }
+
+ const PxMat44 getChunkTM(uint32_t index) const
+ {
+ DestructibleActorMeshType::Enum typeN;
+ if (getDynamic((int32_t)index) || !drawStaticChunksInSeparateMesh())
+ {
+ typeN = DestructibleActorMeshType::Skinned;
+ }
+ else
+ {
+ typeN = DestructibleActorMeshType::Static;
+ index = 0; // Static rendering only has one transform
+ }
+ RenderMeshActor* rma = getRenderMeshActor(typeN);
+ if (rma != NULL)
+ {
+ return rma->getTM(mAsset->getPartIndex(index));
+ }
+ return PxMat44(PxIdentity);
+ }
+
+ int32_t getBehaviorGroupIndex(uint32_t chunkIndex) const
+ {
+ PX_ASSERT(chunkIndex < (uint16_t)mAsset->mParams->chunks.arraySizes[0]);
+ const DestructibleAssetParametersNS::Chunk_Type& sourceChunk = mAsset->mParams->chunks.buf[chunkIndex];
+
+ return (int32_t)sourceChunk.behaviorGroupIndex;
+ }
+
+ uint32_t getChunkActorFlags(uint32_t chunkIndex) const;
+
+ const DestructibleActorParamNS::BehaviorGroup_Type& getBehaviorGroupImp(int8_t behaviorGroupIndex) const
+ {
+ if (behaviorGroupIndex == -1)
+ {
+ return mParams->defaultBehaviorGroup;
+ }
+ else
+ {
+ PX_ASSERT(behaviorGroupIndex < (uint16_t)mParams->behaviorGroups.arraySizes[0]);
+ return mParams->behaviorGroups.buf[behaviorGroupIndex];
+ }
+ }
+
+ const DestructibleActorParamNS::BehaviorGroup_Type& getBehaviorGroup(uint32_t chunkIndex) const
+ {
+ PX_ASSERT(chunkIndex < (uint16_t)mAsset->mParams->chunks.arraySizes[0]);
+ const DestructibleAssetParametersNS::Chunk_Type& sourceChunk = mAsset->mParams->chunks.buf[chunkIndex];
+
+ return getBehaviorGroupImp(sourceChunk.behaviorGroupIndex);
+ }
+
+ const DestructibleActorParamNS::BehaviorGroup_Type& getRTFractureBehaviorGroup() const
+ {
+ return getBehaviorGroupImp(mAsset->mParams->RTFractureBehaviorGroup);
+ }
+
+ void setSkinnedOverrideMaterial(uint32_t index, const char* overrideMaterialName);
+ void setStaticOverrideMaterial(uint32_t index, const char* overrideMaterialName);
+ void setRuntimeFracturePattern(const char* fracturePatternName);
+
+ void updateRenderResources(bool rewriteBuffers, void* userRenderData);
+ void dispatchRenderResources(UserRenderer& renderer);
+
+ void applyDamage(float damage, float momentum, const PxVec3& position, const PxVec3& direction, int32_t chunkIndex = ModuleDestructibleConst::INVALID_CHUNK_INDEX, void* damageUserData = NULL);
+ void applyRadiusDamage(float damage, float momentum, const PxVec3& position, float radius, bool falloff, void* damageUserData = NULL);
+
+ void takeImpact(const PxVec3& force, const PxVec3& position, uint16_t chunkIndex, PxActor const* damageActor);
+ bool takesImpactDamageAtDepth(uint32_t depth)
+ {
+ if (depth < mDestructibleParameters.depthParametersCount)
+ {
+ if (mDestructibleParameters.depthParameters[depth].overrideImpactDamage())
+ {
+ return mDestructibleParameters.depthParameters[depth].overrideImpactDamageValue();
+ }
+ }
+ return (int32_t)depth <= mDestructibleParameters.impactDamageDefaultDepth;
+ }
+
+ bool isChunkSolitary(int32_t chunkIndex) const
+ {
+ PX_ASSERT(mAsset != NULL && mStructure != NULL && chunkIndex >= 0 && chunkIndex < (int32_t)mAsset->getChunkCount());
+ DestructibleStructure::Chunk& chunk = mStructure->chunks[mFirstChunkIndex + chunkIndex];
+ return mStructure->chunkIsSolitary( chunk );
+ }
+
+ bool isChunkDestroyed(uint32_t chunkIndex) const
+ {
+ PX_ASSERT(mAsset != NULL && mStructure != NULL && chunkIndex < mAsset->getChunkCount());
+ DestructibleStructure::Chunk& chunk = mStructure->chunks[mFirstChunkIndex + chunkIndex];
+ return chunk.isDestroyed();
+ }
+
+ PxBounds3 getChunkLocalBounds(uint32_t chunkIndex) const
+ {
+ PX_ASSERT(mAsset != NULL && mStructure != NULL && chunkIndex < mAsset->getChunkCount());
+
+ PxBounds3 localBounds = getDestructibleAsset()->getChunkShapeLocalBounds( chunkIndex );
+
+ PxVec3 boundsExtents = localBounds.getExtents();
+ PxVec3 scaledExtents( boundsExtents.x * getScale().x, boundsExtents.y * getScale().y, boundsExtents.z * getScale().z );
+
+ PxBounds3 scaledLocalBounds = PxBounds3::centerExtents( localBounds.getCenter(), scaledExtents );
+
+ return scaledLocalBounds;
+ }
+
+ PxBounds3 getChunkBounds(uint32_t chunkIndex) const
+ {
+ PX_ASSERT(mAsset != NULL && mStructure != NULL && chunkIndex < mAsset->getChunkCount());
+
+ DestructibleStructure::Chunk& chunk = mStructure->chunks[mFirstChunkIndex + chunkIndex];
+ PxMat44 chunkGlobalPose = mStructure->getChunkGlobalPose( chunk );
+
+ PxBounds3 chunkBounds = getDestructibleAsset()->getChunkShapeLocalBounds( chunkIndex );
+
+ // Apply scaling.
+ chunkGlobalPose.scale( PxVec4(getScale(), 1.f) );
+
+ // Transform into actor local space.
+ PxBounds3Transform( chunkBounds, chunkGlobalPose );
+
+ return chunkBounds;
+ }
+
+ uint32_t getSupportDepthChunkIndices(uint32_t* const OutChunkIndices, uint32_t MaxOutIndices) const
+ {
+ return mStructure->getSupportDepthChunkIndices( OutChunkIndices, MaxOutIndices );
+ }
+
+ PxBounds3 getLocalBounds() const
+ {
+ PxBounds3 bounds = getDestructibleAsset()->getBounds();
+ PxVec3 scale = getScale();
+
+ bounds.minimum.x *= scale.x;
+ bounds.minimum.y *= scale.y;
+ bounds.minimum.z *= scale.z;
+
+ bounds.maximum.x *= scale.x;
+ bounds.maximum.y *= scale.y;
+ bounds.maximum.z *= scale.z;
+
+ return bounds;
+ }
+
+ float getLinearSize() const { return mLinearSize; }
+
+ void applyDamage_immediate(struct DamageEvent& damageEvent);
+ void applyRadiusDamage_immediate(struct DamageEvent& damageEvent);
+
+ int32_t rayCast(float& time, PxVec3& normal, const PxVec3& worldRayOrig, const PxVec3& worldRayDir, const DestructibleActorRaycastFlags::Enum flags, int32_t parentChunkIndex = ModuleDestructibleConst::INVALID_CHUNK_INDEX) const
+ {
+ PX_ASSERT(worldRayOrig.isFinite() && worldRayDir.isFinite());
+
+ PxVec3 worldBoxCenter = worldRayOrig;
+ PxVec3 worldBoxExtents = PxVec3(0.0f, 0.0f, 0.0f);
+ PxMat33 worldBoxRT = PxMat33(PxIdentity);
+ int32_t chunk;
+ if (flags & DestructibleActorRaycastFlags::DynamicChunks)
+ {
+ chunk = pointOrOBBSweep(time, normal, worldBoxCenter, worldBoxExtents, worldBoxRT, worldRayDir, flags, parentChunkIndex);
+ }
+ else
+ {
+ chunk = pointOrOBBSweepStatic(time, normal, worldBoxCenter, worldBoxExtents, worldBoxRT, worldRayDir, flags, parentChunkIndex);
+ }
+#if APEX_RUNTIME_FRACTURE
+ if (mRTActor != NULL)
+ {
+ float rtTime = PX_MAX_F32;
+ // TODO: Refactor the runtime actor raycasting to use a more sensible approach
+ // (Perhaps we can re-use some of the existing pointOrOBBSweep code
+ if (mRTActor->rayCast(worldRayOrig, worldRayDir, rtTime) &&
+ (chunk == ModuleDestructibleConst::INVALID_CHUNK_INDEX || rtTime < time))
+ {
+ time = rtTime;
+ chunk = 0;
+ }
+ }
+#endif
+ return chunk;
+ }
+
+ int32_t obbSweep(float& time, PxVec3& normal, const PxVec3& worldBoxCenter, const PxVec3& worldBoxExtents, const PxMat33& worldBoxRT, const PxVec3& worldDisplacement, DestructibleActorRaycastFlags::Enum flags) const
+ {
+ if (flags & DestructibleActorRaycastFlags::DynamicChunks)
+ {
+ return pointOrOBBSweep(time, normal, worldBoxCenter, worldBoxExtents, worldBoxRT, worldDisplacement, flags, ModuleDestructibleConst::INVALID_CHUNK_INDEX);
+ }
+ else
+ {
+ return pointOrOBBSweepStatic(time, normal, worldBoxCenter, worldBoxExtents, worldBoxRT, worldDisplacement, flags, ModuleDestructibleConst::INVALID_CHUNK_INDEX);
+ }
+ }
+
+ void setActorObjDescFlags(class PhysXObjectDescIntl* actorObjDesc, uint32_t depth) const;
+
+ void fillInstanceBuffers();
+ void setRenderTMs(bool processChunkPoseForSyncing = false);
+ void setRelativeTMs();
+
+ virtual bool recreateApexEmitter(DestructibleEmitterType::Enum type);
+ bool initCrumbleSystem(const char* crumbleEmitterName);
+ bool initDustSystem(const char* dustEmitterName);
+ bool initFracturePattern(const char* fracturePatternName);
+
+ virtual void preSerialize(void *userData = NULL);
+
+ virtual void setPreferredRenderVolume(RenderVolume* volume, DestructibleEmitterType::Enum type);
+ virtual EmitterActor* getApexEmitter(DestructibleEmitterType::Enum type);
+
+ void spawnParticles(class EmitterActor* emitter, UserChunkParticleReport* report, DestructibleStructure::Chunk& chunk, physx::Array<PxVec3>& positions, bool deriveVelocitiesFromChunk = false, const PxVec3* overrideVelocity = NULL);
+
+ void setDeleteFracturedChunks(bool inDeleteChunkMode);
+
+ bool useDamageColoring()
+ {
+ return mUseDamageColoring;
+ }
+
+ /**
+ Return ture means these core data of Damage Event should be saved for the damage coloring
+ */
+ bool applyDamageColoring(uint16_t indexInAsset, const PxVec3& position, float damage, float damageRadius);
+ bool applyDamageColoringRecursive(uint16_t indexInAsset, const PxVec3& position, float damage, float damageRadius);
+
+ void fillBehaviorGroupDesc(DestructibleBehaviorGroupDesc& behaviorGroupDesc, const DestructibleActorParamNS::BehaviorGroup_Type behaviorGroup) const;
+
+ /*** Public behavior group functions ***/
+ uint32_t getCustomBehaviorGroupCount() const
+ {
+ return (uint32_t)mParams->behaviorGroups.arraySizes[0];
+ }
+
+ bool getBehaviorGroup(DestructibleBehaviorGroupDesc& behaviorGroupDesc, int32_t index) const
+ {
+ if (index == -1)
+ {
+ fillBehaviorGroupDesc(behaviorGroupDesc, mParams->defaultBehaviorGroup);
+ return true;
+ }
+ if (index >= 0 && index < (int32_t)mParams->behaviorGroups.arraySizes[0])
+ {
+ fillBehaviorGroupDesc(behaviorGroupDesc, mParams->behaviorGroups.buf[index]);
+ return true;
+ }
+ return false;
+ }
+
+ /*** DestructibleHitChunk operations ***/
+ bool setHitChunkTrackingParams(bool flushHistory, bool startTracking, uint32_t trackingDepth, bool trackAllChunks = true);
+ bool getHitChunkHistory(const DestructibleHitChunk *& hitChunkContainer, uint32_t & hitChunkCount) const;
+ bool forceChunkHits(const DestructibleHitChunk * hitChunkContainer, uint32_t hitChunkCount, bool removeChunks = true, bool deferredEvent = false, PxVec3 damagePosition = PxVec3(0.0f), PxVec3 damageDirection = PxVec3(0.0f));
+ void evaluateForHitChunkList(const FractureEvent & fractureEvent);
+
+ struct CachedHitChunk : public DestructibleHitChunk
+ {
+ CachedHitChunk(uint32_t chunkIndex_, uint32_t hitChunkFlags_)
+ {
+#if defined WIN32
+ extern char enforce[sizeof(*this) == sizeof(DestructibleHitChunk)?1:-1];
+#endif // WIN32
+ DestructibleHitChunk::chunkIndex = chunkIndex_;
+ DestructibleHitChunk::hitChunkFlags = hitChunkFlags_;
+ }
+ ~CachedHitChunk() {}
+ private:
+ CachedHitChunk();
+ };
+
+ /*** Damage Coloring ***/
+ bool getDamageColoringHistory(const DamageEventCoreData *& damageEventCoreDataContainer, uint32_t & damageEventCoreDataCount) const;
+ bool forceDamageColoring(const DamageEventCoreData * damageEventCoreDataContainer, uint32_t damageEventCoreDataCount);
+ void collectDamageColoring(const int32_t indexInAsset, const PxVec3& position, const float damage, const float damageRadius);
+ void applyDamageColoring_immediate(const int32_t indexInAsset, const PxVec3& position, const float damage, const float damageRadius);
+
+ struct CachedDamageEventCoreData : public DamageEventCoreData
+ {
+ CachedDamageEventCoreData(int32_t chunkIndex_, PxVec3 position_, float damage_, float radius_)
+ {
+#if defined WIN32
+ extern char enforce[sizeof(*this) == sizeof(DamageEventCoreData)?1:-1];
+#endif // WIN32
+ DamageEventCoreData::chunkIndexInAsset = chunkIndex_;
+ DamageEventCoreData::position = position_;
+ DamageEventCoreData::damage = damage_;
+ DamageEventCoreData::radius = radius_;
+ }
+ ~CachedDamageEventCoreData() {}
+ private:
+ CachedDamageEventCoreData();
+ };
+
+private:
+ struct HitChunkParams
+ {
+ public:
+ HitChunkParams():cacheChunkHits(false),cacheAllChunks(false),trackingDepth(0)
+ {
+ manualFractureEventInstance.position = PxVec3(0.0f);
+ manualFractureEventInstance.impulse = PxVec3(0.0f);
+ manualFractureEventInstance.hitDirection = PxVec3(0.0f);
+ }
+ ~HitChunkParams() {}
+ bool cacheChunkHits;
+ bool cacheAllChunks;
+ uint32_t trackingDepth;
+ physx::Array<CachedHitChunk> hitChunkContainer;
+ FractureEvent manualFractureEventInstance;
+ } hitChunkParams;
+
+ /*** structure for damage coloring ***/
+ struct DamageColoringParams
+ {
+ physx::Array<CachedDamageEventCoreData> damageEventCoreDataContainer;
+ SyncDamageEventCoreDataParams damageEventCoreDataInstance;
+ } damageColoringParams;
+
+
+ /*** DestructibleActor::SyncParams ***/
+public:
+ bool setSyncParams(uint32_t userActorID, uint32_t actorSyncFlags, const DestructibleActorSyncState * actorSyncState, const DestructibleChunkSyncState * chunkSyncState);
+public:
+ class SyncParams
+ {
+ friend bool DestructibleActorImpl::setSyncParams(uint32_t, uint32_t, const DestructibleActorSyncState *, const DestructibleChunkSyncState *);
+ public:
+ SyncParams();
+ ~SyncParams();
+ uint32_t getUserActorID() const;
+ bool isSyncFlagSet(DestructibleActorSyncFlags::Enum flag) const;
+ const DestructibleActorSyncState * getActorSyncState() const;
+ const DestructibleChunkSyncState * getChunkSyncState() const;
+
+ void pushDamageBufferIndex(uint32_t index);
+ void pushFractureBufferIndex(uint32_t index);
+ void pushCachedChunkTransform(const CachedChunk & cachedChunk);
+
+ const physx::Array<uint32_t> & getDamageBufferIndices() const;
+ const physx::Array<uint32_t> & getFractureBufferIndices() const;
+ const physx::Array<CachedChunk> & getCachedChunkTransforms() const;
+
+ template<typename Unit> void clear();
+ template<typename Unit> uint32_t getCount() const;
+ private:
+ DECLARE_DISABLE_COPY_AND_ASSIGN(SyncParams);
+ void onReset();
+ uint32_t userActorID;
+ uint32_t actorSyncFlags;
+ bool useActorSyncState;
+ DestructibleActorSyncState actorSyncState;
+ bool useChunkSyncState;
+ DestructibleChunkSyncState chunkSyncState;
+
+ physx::Array<uint32_t> damageBufferIndices;
+ physx::Array<uint32_t> fractureBufferIndices;
+ physx::Array<CachedChunk> cachedChunkTransforms;
+ };
+
+ const DestructibleActorImpl::SyncParams & getSyncParams() const;
+ DestructibleActorImpl::SyncParams & getSyncParamsMutable();
+private:
+ SyncParams mSyncParams;
+
+private:
+ DestructibleActorImpl(DestructibleActor* _api, DestructibleAssetImpl& _asset, DestructibleScene& scene);
+ virtual ~DestructibleActorImpl();
+
+ void initialize(NvParameterized::Interface* stateOrParams);
+ void initializeFromState(NvParameterized::Interface* state);
+ void initializeFromParams(NvParameterized::Interface* params);
+ void initializeCommon(void);
+ void createRenderable(void);
+ void initializeActor(void);
+ void initializeRTActor(void);
+ void initializeEmitters(void);
+ void deinitialize(void);
+
+ void setDestructibleParameters(const DestructibleActorParamNS::DestructibleParameters_Type& destructibleParameters,
+ const DestructibleActorParamNS::DestructibleDepthParameters_DynamicArray1D_Type& destructibleDepthParameters);
+
+ int32_t pointOrOBBSweep(float& time, PxVec3& normal, const PxVec3& worldBoxCenter, const PxVec3& worldBoxExtents, const PxMat33& worldBoxRT, const PxVec3& worldDisp,
+ DestructibleActorRaycastFlags::Enum flags, int32_t parentChunkIndex) const;
+
+ int32_t pointOrOBBSweepStatic(float& time, PxVec3& normal, const PxVec3& worldBoxCenter, const PxVec3& worldBoxExtents, const PxMat33& worldBoxRT, const PxVec3& pxWorldDisp,
+ DestructibleActorRaycastFlags::Enum flags, int32_t parentChunkIndex) const;
+
+ void wakeUp(void);
+ void putToSleep(void);
+
+ // Renderable support:
+public:
+ Renderable* getRenderable()
+ {
+ return static_cast<Renderable*>(mRenderable);
+ }
+ DestructibleRenderable* acquireRenderableReference();
+ RenderMeshActor* getRenderMeshActor(DestructibleActorMeshType::Enum type = DestructibleActorMeshType::Skinned) const;
+
+private:
+
+ DestructibleActorState* mState; // Destructible asset state, contains data for serialization
+
+ // Cached parameters
+ DestructibleActorParam* mParams; // Destructible actor params, this is just a convenient reference to the params in mState
+ DestructibleActorChunks* mChunks; // Destructible actor chunks, this is just a convenient reference to the chunks in mState
+
+ // Read-write cached parameters (require writeback on preSerialization)
+ DestructibleParameters mDestructibleParameters;
+ PxMat44 mTM;
+ PxMat44 mRelTM; // Relative transform between the actor
+
+ // Derived parameters
+ IndexBank<uint16_t> mStaticRoots;
+ IndexBank<uint16_t> mVisibleChunks;
+ uint32_t mVisibleDynamicChunkShapeCount;
+ uint32_t mEssentialVisibleDynamicChunkShapeCount;
+ DestructibleScene* mDestructibleScene;
+ DestructibleActor* mAPI;
+ uint16_t mFlags;
+ uint16_t mInternalFlags; // Internal flags, currently indicates whether the actor has been marked as being part of an 'island' or not.
+ DestructibleStructure* mStructure; // The destructible structure that this actor is a member of. Multiple destructible actors can belong to a single destructible structure.
+ DestructibleAssetImpl* mAsset; // The asset associated with this actor.
+ uint32_t mID; // A unique 32 bit GUID given to this actor.
+ float mLinearSize;
+ PxBounds3 mOriginalBounds;
+ PxBounds3 mNonInstancedBounds; // Recording this separately, since instanced buffers get updated separately
+ PxBounds3 mInstancedBounds; // Recording this separately, since instanced buffers get updated separately
+ uint32_t mFirstChunkIndex; // This first chunk index used from the destructible structure
+ EmitterActor* mCrumbleEmitter; // The crumble emitter associated with this actor.
+ EmitterActor* mDustEmitter; // The dust emitter associated with this actor.
+ RenderVolume* mCrumbleRenderVolume; // The render volume to use for crumble effects.
+ RenderVolume* mDustRenderVolume; // The render volume to use for dust effects.
+ float mStartTime; // Time the actor became "alive."
+ float mBenefit;
+ bool mInitializedFromState; // Whether the actor was initialized from state
+ physx::Array<DestructibleChunkEvent> mChunkEventBuffer;
+ nvidia::Mutex mChunkEventBufferLock;
+
+ physx::Array<physx::PxRigidDynamic*> mPhysXActorBuffer;
+
+ nvidia::Mutex mPhysXActorBufferLock;
+
+ DestructibleRenderableImpl* mRenderable;
+
+ physx::Array< physx::Array<ColorRGBA> > mDamageColorArrays;
+ bool mUseDamageColoring;
+
+ uint32_t mDescOverrideSkinnedMaterialCount;
+ const char** mDescOverrideSkinnedMaterials;
+ uint32_t mDescOverrideStaticMaterialCount;
+ const char** mDescOverrideStaticMaterials;
+ bool mPhysXActorBufferAcquired;
+public:
+ bool mInDeleteChunkMode;
+
+ uint32_t mAwakeActorCount; // number of awake PxActors.
+ uint32_t mActiveFrames; // Bit representation of active frame history. Only used when mDestructibleScene->mUsingActiveTransforms == true
+
+ uint32_t mDamageEventReportIndex;
+
+#if USE_DESTRUCTIBLE_RWLOCK
+ shdfnd::ReadWriteLock* mLock;
+#endif
+
+#if APEX_RUNTIME_FRACTURE
+ ::nvidia::fracture::Actor* mRTActor;
+#endif
+
+ bool mWakeForEvent;
+
+ physx::Array<PxRigidDynamic*> mReferencingActors;
+
+public:
+ void referencedByActor(PxRigidDynamic* actor);
+ void unreferencedByActor(PxRigidDynamic* actor);
+
+ PxRigidDynamic** getReferencingActors(uint32_t& count)
+ {
+ count = mReferencingActors.size();
+ return count ? &mReferencingActors[0] : NULL;
+ }
+
+ void wakeForEvent();
+ void resetWakeForEvent();
+
+public:
+
+ PxConvexMesh* getConvexMesh(uint32_t hullIndex)
+ {
+ if (mAsset->mCollisionMeshes == NULL)
+ {
+ mAsset->mCollisionMeshes = mAsset->module->mCachedData->getConvexMeshesForScale(*mAsset, mAsset->module->getChunkCollisionHullCookingScale());
+ PX_ASSERT(mAsset->mCollisionMeshes != NULL);
+ if (mAsset->mCollisionMeshes == NULL)
+ {
+ return NULL;
+ }
+ }
+ return (*mAsset->mCollisionMeshes)[hullIndex];
+ }
+};
+
+
+struct DamageEvent : public DamageEventCoreData
+{
+ // Default constructor for a damage event.
+ DamageEvent() :
+ destructibleID((uint32_t)DestructibleActorImpl::InvalidID),
+ momentum(0.0f),
+ direction(PxVec3(0.0f, 0.0f, 1.0f)),
+ flags(0),
+ impactDamageActor(NULL),
+ appliedDamageUserData(NULL),
+ minDepth(0),
+ maxDepth(0),
+ processDepth(0)
+ {
+ DamageEventCoreData::chunkIndexInAsset = 0;
+ DamageEventCoreData::damage = 0.0f;
+ DamageEventCoreData::radius = 0.0f;
+ DamageEventCoreData::position = PxVec3(0.0f);
+
+ for (uint32_t i = 0; i <= MaxDepth; ++i)
+ {
+ cost[i] = benefit[i] = 0;
+ new(fractures + i) physx::Array<FractureEvent>();
+ }
+ }
+
+ // Copy constructor for a damage event.
+ DamageEvent(const DamageEvent& that)
+ {
+ destructibleID = that.destructibleID;
+ damage = that.damage;
+ momentum = that.momentum;
+ radius = that.radius;
+ position = that.position;
+ direction = that.direction;
+ chunkIndexInAsset = that.chunkIndexInAsset;
+ flags = that.flags;
+
+ minDepth = that.minDepth;
+ maxDepth = that.maxDepth;
+ processDepth = that.processDepth;
+
+ impactDamageActor = that.impactDamageActor;
+ appliedDamageUserData = that.appliedDamageUserData;
+
+ for (uint32_t i = 0; i < MaxDepth + 1; i++)
+ {
+ cost[i] = that.cost[i];
+ benefit[i] = that.benefit[i];
+ fractures[i] = that.fractures[i];
+ }
+ }
+
+ ~DamageEvent()
+ {
+ for (uint32_t i = MaxDepth + 1; i--;)
+ {
+ fractures[i].reset();
+ }
+ }
+
+ // Deep copy of one damage event to another.
+ DamageEvent& operator=(const DamageEvent& that)
+ {
+ if (this != &that)
+ {
+ destructibleID = that.destructibleID;
+ damage = that.damage;
+ momentum = that.momentum;
+ radius = that.radius;
+ position = that.position;
+ direction = that.direction;
+ chunkIndexInAsset = that.chunkIndexInAsset;
+ flags = that.flags;
+
+ minDepth = that.minDepth;
+ maxDepth = that.maxDepth;
+ processDepth = that.processDepth;
+
+ impactDamageActor = that.impactDamageActor;
+ appliedDamageUserData = that.appliedDamageUserData;
+
+ for (uint32_t i = 0; i < MaxDepth + 1; i++)
+ {
+ cost[i] = that.cost[i];
+ benefit[i] = that.benefit[i];
+ fractures[i] = that.fractures[i];
+ }
+ }
+ return *this;
+
+ }
+
+ enum Flag
+ {
+ UseRadius = (1U << 0), // Indicates whether or not to process the damage event as a radius based effect
+ HasFalloff = (1U << 1), // Indicates whether or not the damage amount (for radius damage) falls off with distance from the impact.
+ IsFromImpact = (1U << 2), // Indicates that this is an impact event, where damage is applied to specific chunk rather than radius based damage.
+ SyncDirect = (1U << 3), // Indicates whether this is a sync-ed damage event
+ DeleteChunkModeUnused = (1U << 30), // Indicates whether or not to delete the chunk instead of breaking it off. Propagates down to FractureEvent.
+
+ Invalid = (1U << 31) // Indicates that this event is invalid (can occur when a destructible is removed)
+ };
+
+ uint32_t destructibleID; // The ID of the destructible actor that is being damaged.
+ float momentum; // The inherited momentum of the damage event.
+ PxVec3 direction; // The direction of the damage event.
+ uint32_t flags; // Flags which indicate whether this damage event is radius based and if we use a fall off computation for the amount of damage.
+ physx::PxActor const* impactDamageActor;// Other PhysX actor that caused damage to ApexDamageEventReportData.
+
+ void* appliedDamageUserData; // User data from applyDamage or applyRadiusDamage.
+
+ enum
+ {
+ MaxDepth = 5
+ };
+
+ PX_INLINE uint32_t getMinDepth() const
+ {
+ return minDepth;
+ }
+ PX_INLINE uint32_t getMaxDepth() const
+ {
+ return maxDepth;
+ }
+ PX_INLINE uint32_t getProcessDepth() const
+ {
+ return processDepth;
+ }
+ PX_INLINE float getCost(uint32_t depth = 0xFFFFFFFF) const
+ {
+ return cost[depth <= MaxDepth ? depth : processDepth];
+ }
+ PX_INLINE float getBenefit(uint32_t depth = 0xFFFFFFFF) const
+ {
+ return benefit[depth <= MaxDepth ? depth : processDepth];
+ }
+ PX_INLINE bool isFromImpact(void) const
+ {
+ return flags & IsFromImpact ? true : false;
+ };
+
+ void resetFracturesInternal()
+ {
+ for(uint32_t index = DamageEvent::MaxDepth + 1; index--; )
+ {
+ fractures[index].reset();
+ }
+ }
+private:
+ uint32_t minDepth; // The minimum structure depth that this damage event can apply to.
+ uint32_t maxDepth; // The maximum structure depth that this damage event can apply to.
+ uint32_t processDepth; // The exact depth that the damage event applies to.
+ float cost[MaxDepth + 1]; // The LOD 'cost' at each depth for this damage event.
+ float benefit[MaxDepth + 1]; // The LOD 'benefit' at each depth for this damage event.
+ physx::Array<FractureEvent> fractures[MaxDepth + 1]; // The array of fracture events associated with this damage event.
+
+ friend class DestructibleScene;
+ friend class DestructibleActorImpl;
+};
+
+#if USE_DESTRUCTIBLE_RWLOCK
+class DestructibleScopedReadLock : public physx::ScopedReadLock
+{
+public:
+ DestructibleScopedReadLock(DestructibleActorImpl& destructible) : physx::ScopedReadLock(*destructible.mLock) {}
+};
+
+class DestructibleScopedWriteLock : public physx::ScopedWriteLock
+{
+public:
+ DestructibleScopedWriteLock(DestructibleActorImpl& destructible) : physx::ScopedWriteLock(*destructible.mLock) {}
+};
+#endif
+
+}
+} // end namespace nvidia
+
+#endif // __DESTRUCTIBLEACTOR_IMPL_H__