diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/module/destructible | |
| download | physx-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')
117 files changed, 63155 insertions, 0 deletions
diff --git a/APEX_1.4/module/destructible/fracture/Actor.cpp b/APEX_1.4/module/destructible/fracture/Actor.cpp new file mode 100644 index 00000000..1eb12b66 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Actor.cpp @@ -0,0 +1,292 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include <DestructibleActorImpl.h> +#include <RenderMeshAsset.h> +#include <DestructibleStructure.h> + +#include "../fracture/Actor.h" + +#include "FracturePattern.h" +#include "SimScene.h" +#include "Compound.h" +#include "Mesh.h" + +namespace nvidia +{ +namespace fracture +{ + +Actor::Actor(base::SimScene* scene, DestructibleActorImpl* actor): + base::Actor(scene), + mActor(actor), + mRenderResourcesDirty(false), + mMinRadius(0.f), + mRadiusMultiplier(1.f), + mImpulseScale(1.f), + mSheetFracture(true) +{ + if(actor == NULL) + { + const uint32_t numSectors = 10; + const float sectorRand = 0.3f; + const float firstSegmentSize = 0.06f; + const float segmentScale = 1.4f; + const float segmentRand = 0.3f; + const float size = 10.f; + const float radius = size; + const float thickness = size; + mDefaultFracturePattern = (FracturePattern*)mScene->createFracturePattern(); + mDefaultFracturePattern->createGlass(radius,thickness,numSectors,sectorRand,firstSegmentSize,segmentScale,segmentRand); + } + else + { + // create fracture pattern + const nvidia::destructible::DestructibleActorParamNS::RuntimeFracture_Type& params = actor->getParams()->destructibleParameters.runtimeFracture; + const uint32_t numSectors = params.glass.numSectors; + const float sectorRand = params.glass.sectorRand; + const float firstSegmentSize = params.glass.firstSegmentSize; + const float segmentScale = params.glass.segmentScale; + const float segmentRand = params.glass.segmentRand; + const float size = actor->getBounds().getDimensions().maxElement(); + const float radius = size; + const float thickness = size; + mDefaultFracturePattern = (FracturePattern*)mScene->createFracturePattern(); + mDefaultFracturePattern->createGlass(radius,thickness,(int32_t)numSectors,sectorRand,firstSegmentSize,segmentScale,segmentRand); + // attachment + mAttachmentFlags.posX = (uint32_t)params.attachment.posX; + mAttachmentFlags.negX = (uint32_t)params.attachment.negX; + mAttachmentFlags.posY = (uint32_t)params.attachment.posY; + mAttachmentFlags.negY = (uint32_t)params.attachment.negY; + mAttachmentFlags.posZ = (uint32_t)params.attachment.posZ; + mAttachmentFlags.negZ = (uint32_t)params.attachment.negZ; + // other + mDepthLimit = params.depthLimit; + mDestroyIfAtDepthLimit = params.destroyIfAtDepthLimit; + mImpulseScale = params.impulseScale; + mMinConvexSize = params.minConvexSize; + mSheetFracture = params.sheetFracture; + } +} + +Actor::~Actor() +{ + PX_DELETE(mDefaultFracturePattern); + mDefaultFracturePattern = NULL; +} + +Compound* Actor::createCompound() +{ + base::Compound* c = mScene->createCompound((base::FracturePattern*)mDefaultFracturePattern); + addCompound(c); + return (Compound*)c; +} + +Compound* Actor::createCompoundFromChunk(const destructible::DestructibleActorImpl& actor, uint32_t partIndex) +{ + Mesh RTmesh; + RTmesh.loadFromRenderMesh(*actor.getDestructibleAsset()->getRenderMeshAsset(),partIndex); + + // Fix texture v's (different between right hand and left hand) + RTmesh.flipV(); + + PxTransform pose(actor.getChunkPose(partIndex)); + pose.p = actor.getStructure()->getChunkWorldCentroid(actor.getChunk(partIndex)); + + Compound* c = createCompound(); + + c->createFromMesh(&RTmesh,pose,actor.getChunkLinearVelocity(partIndex),actor.getChunkAngularVelocity(partIndex),-1,actor.getScale()); + + const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = actor.getBehaviorGroup(partIndex); + mMinRadius = behaviorGroup.damageSpread.minimumRadius; + mRadiusMultiplier = behaviorGroup.damageSpread.radiusMultiplier; + + // attachment + //const DestructibleActorParamNS::RuntimeFracture_Type& params = mActor->getParams()->destructibleParameters.runtimeFracture; + DestructibleParameters& params = mActor->getDestructibleParameters(); + mAttachmentFlags.posX |= params.rtFractureParameters.attachment.posX; + mAttachmentFlags.negX |= params.rtFractureParameters.attachment.negX; + mAttachmentFlags.posY |= params.rtFractureParameters.attachment.posY; + mAttachmentFlags.negY |= params.rtFractureParameters.attachment.negY; + mAttachmentFlags.posZ |= params.rtFractureParameters.attachment.posZ; + mAttachmentFlags.negZ |= params.rtFractureParameters.attachment.negZ; + + attachBasedOnFlags(c); + + mRenderResourcesDirty = true; + + return c; +} + +bool Actor::patternFracture(const PxVec3& hitLocation, const PxVec3& dirIn, float scale, float vel, float radiusIn) +{ + int compoundNr = -1; + int convexNr = -1; + PxVec3 normal; + float dist; + bool ret = false; + PxVec3 dir = dirIn; + + mScene->getScene()->lockWrite(); + + bool hit = false; + if (dir.magnitudeSquared() < 0.5f) + { + dir = PxVec3(1.f,0.f,0.f); + hit = base::Actor::rayCast(hitLocation-dir,dir,dist,compoundNr,convexNr,normal); + if(!hit) + { + dir = PxVec3(0.f,1.f,0.f); + hit = base::Actor::rayCast(hitLocation-dir,dir,dist,compoundNr,convexNr,normal); + if(!hit) + { + dir = PxVec3(0.f,0.f,1.f); + hit = base::Actor::rayCast(hitLocation-dir,dir,dist,compoundNr,convexNr,normal); + } + } + } + else + { + hit = base::Actor::rayCast(hitLocation-dir,dir,dist,compoundNr,convexNr,normal); + } + if (hit) + { + float radius = mMinRadius + mRadiusMultiplier*radiusIn; + float impulseMagn = scale*vel*mImpulseScale; + + if (mSheetFracture) + { + normal = ((Compound*)mCompounds[(uint32_t)compoundNr])->mNormal; + } + PxVec3 a(0.f,0.f,1.f); + normal.normalize(); + a -= a.dot(normal)*normal; + if( a.magnitudeSquared() < 0.1f ) + { + a = PxVec3(0.f,1.f,0.f); + a -= a.dot(normal)*normal; + } + a.normalize(); + PxVec3 b(normal.cross(a)); + PxMat33 trans(a,b,normal); + ret = base::Actor::patternFracture(hitLocation,dir,compoundNr,trans,radius,impulseMagn,impulseMagn); + } + + mScene->getScene()->unlockWrite(); + + mRenderResourcesDirty = true; + + return ret; +} + +bool Actor::patternFracture(const DamageEvent& damageEvent) +{ + mDamageEvent.position = damageEvent.position; + mDamageEvent.direction = damageEvent.direction; + mDamageEvent.damage = damageEvent.damage; + mDamageEvent.radius = damageEvent.radius; + return patternFracture(damageEvent.position, damageEvent.direction, 1.f, damageEvent.damage, damageEvent.radius); +} + +bool Actor::patternFracture(const FractureEvent& fractureEvent, bool fractureOnLoad) +{ + createCompoundFromChunk(*mActor,fractureEvent.chunkIndexInAsset); + if(fractureOnLoad) + { + patternFracture(mDamageEvent.position, mDamageEvent.direction, 1.f, mDamageEvent.damage, mDamageEvent.radius); + //patternFracture(fractureEvent.position,fractureEvent.hitDirection,1.f,fractureEvent.impulse.magnitude()/mActor->getChunkMass(fractureEvent.chunkIndexInAsset),1); + } + return true; +} + +bool Actor::rayCast(const PxVec3& orig, const PxVec3& dir, float &dist) const +{ + int compoundNr = 0; + int convexNr = 0; + PxVec3 n; + bool ret = false; + + mScene->getScene()->lockRead(); + ret = base::Actor::rayCast(orig,dir,dist,compoundNr,convexNr,n); + mScene->getScene()->unlockRead(); + + return ret; +} + +void Actor::attachBasedOnFlags(base::Compound* c) +{ + PxBounds3 b; + c->getLocalBounds(b); + // Determine sheet face + if (mSheetFracture) + { + PxVec3 dim = b.getDimensions(); + if ( dim.x < dim.y && dim.x < dim.z ) + { + ((Compound*)c)->mNormal = PxVec3(1.f,0.f,0.f); + } + else if ( dim.y < dim.x && dim.y < dim.z ) + { + ((Compound*)c)->mNormal = PxVec3(0.f,1.f,0.f); + } + else + { + ((Compound*)c)->mNormal = PxVec3(0.f,0.f,1.f); + } + } + // Attach + const float w = 0.01f*b.getDimensions().maxElement(); + nvidia::Array<PxBounds3> bounds; + bounds.reserve(6); + if (mAttachmentFlags.posX) + { + PxBounds3 a(b); + a.minimum.x = a.maximum.x-w; + bounds.pushBack(a); + } + if (mAttachmentFlags.negX) + { + PxBounds3 a(b); + a.maximum.x = a.minimum.x+w; + bounds.pushBack(a); + } + if (mAttachmentFlags.posY) + { + PxBounds3 a(b); + a.minimum.y = a.maximum.y-w; + bounds.pushBack(a); + } + if (mAttachmentFlags.negY) + { + PxBounds3 a(b); + a.maximum.y = a.minimum.y+w; + bounds.pushBack(a); + } + if (mAttachmentFlags.posZ) + { + PxBounds3 a(b); + a.minimum.z = a.maximum.z-w; + bounds.pushBack(a); + } + if (mAttachmentFlags.negZ) + { + PxBounds3 a(b); + a.maximum.z = a.minimum.z+w; + bounds.pushBack(a); + } + c->attachLocal(bounds); +} + +} +} +#endif diff --git a/APEX_1.4/module/destructible/fracture/Actor.h b/APEX_1.4/module/destructible/fracture/Actor.h new file mode 100644 index 00000000..f23e4b88 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Actor.h @@ -0,0 +1,97 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef RT_ACTOR_H +#define RT_ACTOR_H + +#include "ActorBase.h" + +namespace nvidia +{ +namespace destructible +{ + class DestructibleActorImpl; + struct DamageEvent; + struct FractureEvent; +} + +using namespace destructible; +namespace fracture +{ + +class Compound; +class FracturePattern; +class Renderable; + +class Actor : public base::Actor +{ + friend class SimScene; + friend class Renderable; +protected: + Actor(base::SimScene* scene, DestructibleActorImpl* actor); +public: + virtual ~Actor(); + + Compound* createCompound(); + + Compound* createCompoundFromChunk(const destructible::DestructibleActorImpl& destructibleActor, uint32_t partIndex); + + bool patternFracture(const PxVec3& hitLocation, const PxVec3& dir, float scale = 1.f, float vel = 0.f, float radius = 0.f); + bool patternFracture(const DamageEvent& damageEvent); + bool patternFracture(const FractureEvent& fractureEvent, bool fractureOnLoad = true); + + bool rayCast(const PxVec3& orig, const PxVec3& dir, float &dist) const; + + DestructibleActorImpl* getDestructibleActor() {return mActor;} + +protected: + void attachBasedOnFlags(base::Compound* c); + + FracturePattern* mDefaultFracturePattern; + DestructibleActorImpl* mActor; + bool mRenderResourcesDirty; + + float mMinRadius; + float mRadiusMultiplier; + float mImpulseScale; + bool mSheetFracture; + + struct AttachmentFlags + { + AttachmentFlags() : + posX(0), negX(0), posY(0), negY(0), posZ(0), negZ(0) {} + + uint32_t posX : 1; + uint32_t negX : 1; + uint32_t posY : 1; + uint32_t negY : 1; + uint32_t posZ : 1; + uint32_t negZ : 1; + }mAttachmentFlags; + + struct MyDamageEvent + { + PxVec3 position; + PxVec3 direction; + float damage; + float radius; + }; + MyDamageEvent mDamageEvent; + +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Compound.cpp b/APEX_1.4/module/destructible/fracture/Compound.cpp new file mode 100644 index 00000000..2d49f19d --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Compound.cpp @@ -0,0 +1,51 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "ApexActor.h" +#include "DestructibleScene.h" +#include "DestructibleActorImpl.h" +#include "SimScene.h" +#include "Actor.h" +#include "PxShape.h" + +#include "Compound.h" + +namespace nvidia +{ + +namespace fracture +{ + +void Compound::applyShapeTemplate(PxShape* shape) +{ + if( shape && mActor) + { + DestructibleActorImpl* dactor = ((Actor*)mActor)->getDestructibleActor(); + { + PhysX3DescTemplateImpl physX3Template; + dactor->getPhysX3Template(physX3Template); + physX3Template.apply(shape); + } + } +} + +::nvidia::destructible::DestructibleActorImpl* Compound::getDestructibleActor() const +{ + ::nvidia::destructible::DestructibleActorImpl* dactor = NULL; + if(mActor) + dactor = ((Actor*)mActor)->getDestructibleActor(); + return dactor; +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Compound.h b/APEX_1.4/module/destructible/fracture/Compound.h new file mode 100644 index 00000000..8f07c393 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Compound.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef COMPOUND_H +#define COMPOUND_H + +#include "CompoundBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class Compound : public base::Compound +{ + friend class SimScene; + friend class Actor; +protected: + Compound(SimScene* scene, const base::FracturePattern *pattern, const base::FracturePattern *secondaryPattern = NULL, float contactOffset = 0.005f, float restOffset = -0.001f): + nvidia::fracture::base::Compound((base::SimScene*)scene,pattern,secondaryPattern,contactOffset,restOffset) {} +public: + virtual void applyShapeTemplate(PxShape* shape); + virtual ::nvidia::destructible::DestructibleActorImpl* getDestructibleActor() const; +}; + +} +} + + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/CompoundCreator.cpp b/APEX_1.4/module/destructible/fracture/CompoundCreator.cpp new file mode 100644 index 00000000..14a29b7b --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/CompoundCreator.cpp @@ -0,0 +1,23 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "CompoundCreator.h" + +namespace nvidia +{ +namespace fracture +{ + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/CompoundCreator.h b/APEX_1.4/module/destructible/fracture/CompoundCreator.h new file mode 100644 index 00000000..40198fe6 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/CompoundCreator.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef COMPOUND_CREATOR_H +#define COMPOUND_CREATOR_H + +#include <PxVec3.h> +#include <PxTransform.h> +#include <PsArray.h> + +#include "CompoundCreatorBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class CompoundCreator : public base::CompoundCreator +{ + friend class SimScene; +protected: + CompoundCreator(base::SimScene* scene): base::CompoundCreator((base::SimScene*)scene) {} +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/CompoundGeometry.cpp b/APEX_1.4/module/destructible/fracture/CompoundGeometry.cpp new file mode 100644 index 00000000..9429174a --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/CompoundGeometry.cpp @@ -0,0 +1,23 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "CompoundGeometry.h" + +namespace nvidia +{ +namespace fracture +{ + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/CompoundGeometry.h b/APEX_1.4/module/destructible/fracture/CompoundGeometry.h new file mode 100644 index 00000000..689be78c --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/CompoundGeometry.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef COMPOUND_GEOMETRY +#define COMPOUND_GEOMETRY + +#include <PxVec3.h> +#include <PxPlane.h> +#include <PsArray.h> + +#include "CompoundGeometryBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class CompoundGeometry : public nvidia::fracture::base::CompoundGeometry +{ +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Convex.cpp b/APEX_1.4/module/destructible/fracture/Convex.cpp new file mode 100644 index 00000000..4fc5de4c --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Convex.cpp @@ -0,0 +1,24 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "Convex.h" + +namespace nvidia +{ +namespace fracture +{ + +} +} + +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Convex.h b/APEX_1.4/module/destructible/fracture/Convex.h new file mode 100644 index 00000000..40717e67 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Convex.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef CONVEX +#define CONVEX + +#include "ConvexBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class Convex : public base::Convex +{ + friend class SimScene; +protected: + Convex(base::SimScene* scene): base::Convex(scene) {} +public: +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/ActorBase.cpp b/APEX_1.4/module/destructible/fracture/Core/ActorBase.cpp new file mode 100644 index 00000000..2c88a262 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/ActorBase.cpp @@ -0,0 +1,270 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "ActorBase.h" + +#include <PxMat44.h> +#include "PxRigidBodyExt.h" +#include "PxScene.h" + +#include "SimSceneBase.h" +#include "CompoundBase.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace nvidia; + +Actor::Actor(SimScene* scene): + mScene(scene), + mMinConvexSize(scene->mMinConvexSize), + mDepthLimit(100), + mDestroyIfAtDepthLimit(false) +{ + +} + +Actor::~Actor() +{ + PxScene* pxScene = mScene->getScene(); + if(pxScene != NULL) + { + pxScene->lockWrite(); + } + clear(); + if(pxScene != NULL) + { + pxScene->unlockWrite(); + } + mScene->removeActor(this); +} + +void Actor::clear() +{ + for (uint32_t i = 0; i < mCompounds.size(); i++) { + PX_DELETE(mCompounds[i]); + } + mCompounds.clear(); +} + +void Actor::addCompound(Compound *c) +{ + mCompounds.pushBack(c); + PxRigidDynamic *a = c->getPxActor(); + if (a) { +// a->setContactReportFlags(Px_NOTIFY_ON_TOUCH_FORCE_THRESHOLD | Px_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD); + a->setContactReportThreshold(mScene->mFractureForceThreshold); + } + c->mActor = this; + ++(mScene->mSceneVersion); +} + +void Actor::removeCompound(Compound *c) +{ + uint32_t num = 0; + for (uint32_t i = 0; i < mCompounds.size(); i++) { + if (mCompounds[i] != c) { + mCompounds[num] = mCompounds[i]; + num++; + } + } + if (mScene->mPickActor == c->getPxActor()) + mScene->mPickActor = NULL; + + c->clear(); + //delCompoundList.push_back(c); + //delete c; + mScene->delCompoundList.pushBack(c); + mCompounds.resize(num); + ++mScene->mSceneVersion; +} + +void Actor::preSim(float dt) +{ + uint32_t num = 0; + for (uint32_t i = 0; i < (uint32_t)mCompounds.size(); i++) { + mCompounds[i]->step(dt); + if (mCompounds[i]->getLifeFrames() == 0) { + mCompounds[i]->clear(); + //delCompoundList.push_back(mCompounds[i]); + //delete mCompounds[i]; + mScene->delCompoundList.pushBack(mCompounds[i]); + } + else { + mCompounds[num] = mCompounds[i]; + num++; + } + } + mCompounds.resize(num); +} + +void Actor::postSim(float /*dt*/) +{ +} + +bool Actor::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &compoundNr, int &convexNr, PxVec3 &normal) const +{ + dist = PX_MAX_F32; + compoundNr = -1; + convexNr = -1; + + for (uint32_t i = 0; i < mCompounds.size(); i++) { + float d; + int cNr; + PxVec3 n; + if (mCompounds[i]->rayCast(orig, dir, d, cNr, n)) { + if (d < dist) { + dist = d; + compoundNr = (int)i; + convexNr = cNr; + normal = n; + } + } + } + return compoundNr >= 0; +} + +bool Actor::patternFracture(const PxVec3 &orig, const PxVec3 &dir, const PxMat33 patternTransform, float impactRadius, float radialImpulse, float directionalImpulse) +{ + float dist; + float objectSize = 0.0f; + int actorNr; + int compoundNr; + int convexNr; + PxVec3 normal; + + // do global rayCast. + if (!mScene->rayCast(orig, dir, dist, actorNr, compoundNr, convexNr, normal)) + return false; + if (mScene->mActors[(uint32_t)actorNr] != this) + return false; + + mScene->debugPoints.clear(); + nvidia::Array<Compound*> compounds; + + mScene->profileBegin("patternFracture"); + bool OK = mCompounds[(uint32_t)compoundNr]->patternFracture(orig + dir * dist, mMinConvexSize, + compounds, patternTransform, mScene->debugPoints, impactRadius, radialImpulse, normal * directionalImpulse); + mScene->profileEnd("patternFracture"); + if (!OK) + return false; + + if (compounds.empty()) + return false; + + if (mCompounds[(uint32_t)compoundNr]->getPxActor() == mScene->mPickActor) + mScene->mPickActor = NULL; + + PxBounds3 bounds; + mCompounds[(uint32_t)compoundNr]->getWorldBounds(bounds); + objectSize = bounds.getDimensions().magnitude(); + + //delCompoundList.push_back( mCompounds[compoundNr]); + mScene->delCompoundList.pushBack( mCompounds[(uint32_t)compoundNr]); + mCompounds[(uint32_t)compoundNr]->clear(); + //delete mCompounds[compoundNr]; + + mCompounds[(uint32_t)compoundNr] = compounds[0]; + + for (uint32_t i = 1; i < compounds.size(); i++) + mCompounds.pushBack(compounds[i]); + + ++mScene->mSceneVersion; + + + // playShatterSound(objectSize); + //if (fluidSim) + //fluidSim->mistPS->seedDustParticles((PxVec3*)&debugPoints[0], debugPoints.size(), seedDustRadius, seedDustNumPerSite, dustMinLife, dustMaxLife, 0.0f, 1.0f); + + uint32_t numConvexes = 0; + for (uint32_t i = 0; i < mCompounds.size(); i++) + numConvexes += mCompounds[i]->getConvexes().size(); + + //printf("\n------- pattern fracture------\n"); + //printf("i compounds, %i convexes after fracture\n", mCompounds.size(), numConvexes); + + return true; +} + +bool Actor::patternFracture(const PxVec3 &hitLocation, const PxVec3 &normal, const int &compoundNr, const PxMat33 patternTransform, float impactRadius, float radialImpulse, float directionalImpulse) +{ + float objectSize = 0.0f; + + mScene->debugPoints.clear(); + nvidia::Array<Compound*> compounds; + + mScene->profileBegin("patternFracture"); + bool OK = mCompounds[(uint32_t)compoundNr]->patternFracture(hitLocation, mMinConvexSize, + compounds, patternTransform, mScene->debugPoints, impactRadius, radialImpulse, normal * directionalImpulse); + mScene->profileEnd("patternFracture"); + if (!OK) + return false; + + if (compounds.empty()) + return false; + + if (mCompounds[(uint32_t)compoundNr]->getPxActor() == mScene->mPickActor) + mScene->mPickActor = NULL; + + PxBounds3 bounds; + mCompounds[(uint32_t)compoundNr]->getWorldBounds(bounds); + objectSize = bounds.getDimensions().magnitude(); + + //delCompoundList.push_back( mCompounds[compoundNr]); + mScene->delCompoundList.pushBack( mCompounds[(uint32_t)compoundNr]); + mCompounds[(uint32_t)compoundNr]->clear(); + //delete mCompounds[compoundNr]; + + mCompounds[(uint32_t)compoundNr] = compounds[0]; + + for (uint32_t i = 1; i < compounds.size(); i++) + mCompounds.pushBack(compounds[i]); + + ++mScene->mSceneVersion; + + + // playShatterSound(objectSize); + //if (fluidSim) + //fluidSim->mistPS->seedDustParticles((PxVec3*)&debugPoints[0], debugPoints.size(), seedDustRadius, seedDustNumPerSite, dustMinLife, dustMaxLife, 0.0f, 1.0f); + + uint32_t numConvexes = 0; + for (uint32_t i = 0; i < mCompounds.size(); i++) + numConvexes += mCompounds[i]->getConvexes().size(); + + //printf("\n------- pattern fracture------\n"); + //printf("i compounds, %i convexes after fracture\n", mCompounds.size(), numConvexes); + + return true; +} + +bool Actor::findCompound(const Compound* c, int& compoundNr) +{ + for(uint32_t i = 0; i < mCompounds.size(); i++) + { + if(mCompounds[i] == c) + { + compoundNr = (int32_t)i; + return true; + } + } + return false; +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/ActorBase.h b/APEX_1.4/module/destructible/fracture/Core/ActorBase.h new file mode 100644 index 00000000..38fc4843 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/ActorBase.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef ACTOR_BASE_H +#define ACTOR_BASE_H + +#include <PsArray.h> +#include <PsUserAllocated.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +class SimScene; +class Compound; + +class Actor : public UserAllocated +{ + friend class SimScene; + friend class Compound; +protected: + Actor(SimScene* scene); +public: + virtual ~Actor(); + + void clear(); + void addCompound(Compound *m); + void removeCompound(Compound *m); + + bool findCompound(const Compound* c, int& compoundNr); + + void preSim(float dt); + void postSim(float dt); + + bool rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &compoundNr, int &convexNr, PxVec3 &normal) const; + + // performs raycast + bool patternFracture(const PxVec3 &orig, const PxVec3 &dir, + const PxMat33 patternTransform, float impactRadius = 0.0f, float radialImpulse = 0.0f, float directionalImpulse = 0.0f); + + // take in raycast results + bool patternFracture(const PxVec3 &hitLocation, const PxVec3 &normal, const int &compoundNr, + const PxMat33 patternTransform, float impactRadius = 0.0f, float radialImpulse = 0.0f, float directionalImpulse = 0.0f); + + nvidia::Array<Compound*> getCompounds() { return mCompounds; } + +protected: + SimScene* mScene; + nvidia::Array<Compound*> mCompounds; + + float mMinConvexSize; + uint32_t mDepthLimit; + bool mDestroyIfAtDepthLimit; +}; + +} +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/CompoundBase.cpp b/APEX_1.4/module/destructible/fracture/Core/CompoundBase.cpp new file mode 100644 index 00000000..8e273564 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/CompoundBase.cpp @@ -0,0 +1,686 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "FracturePatternBase.h" +#include "MeshBase.h" +#include "CompoundGeometryBase.h" +#include "CompoundCreatorBase.h" +#include "PxConvexMeshGeometry.h" +#include "PxRigidBodyExt.h" +#include "PxMat44.h" +#include "PxScene.h" +#include "PxShape.h" + +#include "SimSceneBase.h" +#include "CompoundBase.h" +#include "ActorBase.h" +#include "ConvexBase.h" +#include "PsMathUtils.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace physx; + +//vector<PxVec3> tmpPoints; +void Compound::appendUniformSamplesOfConvexPolygon(PxVec3* vertices, int numV, float area, nvidia::Array<PxVec3>& samples, nvidia::Array<PxVec3>* normals) { + using namespace physx::shdfnd; + PxVec3& p0 = vertices[0]; + PxVec3 normal; + if (numV < 3) { + normal = PxVec3(0.0f,1.0f,0.0f); + } else { + normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); + normal.normalize(); + } + for (int i = 1; i < numV-1; i++) { + PxVec3& p1 = vertices[i]; + PxVec3& p2 = vertices[i+1]; + float tarea = 0.5f*((p1-p0).cross(p2-p0)).magnitude(); + float aa = tarea / area; + int np = (int)physx::shdfnd::floor(aa); + + if (rand(0.0f,1.0f) <= aa-np) np++; + + for (int j = 0; j < np; j++) { + float r1 = rand(0.0f,1.0f); + float sr1 = PxSqrt(r1); + float r2 = rand(0.0f, 1.0f); + + PxVec3 p = (1 - sr1) * p0 + (sr1 * (1 - r2)) * p1 + (sr1 * r2) * p2; + samples.pushBack(p); + if (normals) normals->pushBack(normal); + + } + } +} + +// -------------------------------------------------------------------------------------------- +Compound::Compound(SimScene *scene, const FracturePattern *pattern, const FracturePattern *secondaryPattern, float contactOffset, float restOffset) +{ + mScene = scene; + mActor = NULL; + mPxActor = NULL; + mFracturePattern = pattern; + mSecondardFracturePattern = secondaryPattern; + mContactOffset = contactOffset; + mRestOffset = restOffset; + mLifeFrames = -1; // live forever + mDepth = 0; + clear(); +} + +// -------------------------------------------------------------------------------------------- +Compound::~Compound() +{ + clear(); +} + +// -------------------------------------------------------------------------------------------- +#define SHAPE_BUFFER_SIZE 100 + +void Compound::clear() +{ + if (mPxActor != NULL) { + // Unmap all shapes for this actor + const uint32_t shapeCount = mPxActor->getNbShapes(); + physx::PxShape* shapeBuffer[SHAPE_BUFFER_SIZE]; + for (uint32_t shapeStartIndex = 0; shapeStartIndex < shapeCount; shapeStartIndex += SHAPE_BUFFER_SIZE) + { + uint32_t shapesRead = mPxActor->getShapes(shapeBuffer, SHAPE_BUFFER_SIZE, shapeStartIndex); + for (uint32_t shapeBufferIndex = 0; shapeBufferIndex < shapesRead; ++shapeBufferIndex) + { + mScene->unmapShape(*shapeBuffer[shapeBufferIndex]); + } + } + // release the actor + mPxActor->release(); + mPxActor = NULL; + } + for (uint32_t i = 0; i < mConvexes.size(); i++) { + if (mConvexes[i]->decreaseRefCounter() <= 0) { + convexRemoved(mConvexes[i]); //mScene->getConvexRenderer().remove(mConvexes[i]); + PX_DELETE(mConvexes[i]); + } + } + + mConvexes.clear(); + mEdges.clear(); + + //mShader = NULL; + //mShaderMat.init(); + + mKinematicVel = PxVec3(0.0f, 0.0f, 0.0f); + mAttachmentBounds.clear(); + + mAdditionalImpactNormalImpulse = 0.0f; + mAdditionalImpactRadialImpulse = 0.0f; +} + +// -------------------------------------------------------------------------------------------- +void Compound::setKinematic(const PxVec3 &vel) +{ + if (mPxActor == NULL) + return; + + mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); + mKinematicVel = vel; +} + +// -------------------------------------------------------------------------------------------- +void Compound::step(float dt) +{ + //if (mPxActor == NULL) + // return; + + if (!mKinematicVel.isZero()) { + PxTransform pose = mPxActor->getGlobalPose(); + pose.p += mKinematicVel * dt; + mPxActor->setKinematicTarget(pose); + } + + if (mLifeFrames > 0) + mLifeFrames--; +} + +// -------------------------------------------------------------------------------------------- +bool Compound::createFromConvex(Convex* convex, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes) +{ + return createFromConvexes(&convex, 1, pose, vel, omega, copyConvexes); +} + +// -------------------------------------------------------------------------------------------- +bool Compound::createFromConvexes(Convex** convexes, int numConvexes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes) +{ + if (numConvexes == 0) + return false; + + clear(); + PxVec3 center(0.0f, 0.0f, 0.0f); + for (int i = 0; i < numConvexes; i++) + center += convexes[i]->getCenter(); + center /= (float)numConvexes; + + nvidia::Array<PxShape*> shapes; + + for (int i = 0; i < numConvexes; i++) { + Convex *c; + if (copyConvexes) { + c = mScene->createConvex(); + c->createFromConvex(convexes[i]); + } + else + c = convexes[i]; + + c->increaseRefCounter(); + mConvexes.pushBack(c); + + PxVec3 off = c->centerAtZero(); + c->setMaterialOffset(c->getMaterialOffset() + off); + c->setLocalPose(PxTransform(off - center)); + + if (convexes[i]->isGhostConvex()) + continue; + + bool reused = c->getPxConvexMesh() != NULL; + + mScene->profileBegin("cook convex meshes"); //Profiler::getInstance()->begin("cook convex meshes"); + PxConvexMesh* mesh = c->createPxConvexMesh(this, mScene->getPxPhysics(), mScene->getPxCooking()); + mScene->profileEnd("cook convex meshes"); //Profiler::getInstance()->end("cook convex meshes"); + + if (mesh == NULL) { + if (c->decreaseRefCounter() <= 0) + PX_DELETE(c); + mConvexes.popBack(); + continue; + } + + if (!c->hasExplicitVisMesh()) + c->createVisMeshFromConvex(); + + if (!reused) + convexAdded(c); //mScene->getConvexRenderer().add(c); + +#if (PX_PHYSICS_VERSION_MAJOR == 3) && (PX_PHYSICS_VERSION_MINOR < 3) + PxShape *shape = mScene->getPxPhysics()->createShape( + PxConvexMeshGeometry(mesh), + *mScene->getPxDefaultMaterial(), + true, + c->getLocalPose()); +#else + PxShape *shape = mScene->getPxPhysics()->createShape( + PxConvexMeshGeometry(mesh), + *mScene->getPxDefaultMaterial(), + true + ); + shape->setLocalPose(c->getLocalPose()); +#endif + + shape->setContactOffset(mContactOffset); + shape->setRestOffset(mRestOffset); + + mScene->mapShapeToConvex(*shape, *c); + + shapes.pushBack(shape); + } + + if (shapes.empty()) + { + return false; + } + + createPxActor(shapes, pose, vel, omega); + //if (!createPxActor(shapes, pose, vel, omega)) + /*int foo = 0*/; + + //createPointSamples(applyForcePointAreaPerSample); + + return true; +} + +// -------------------------------------------------------------------------------------------- +bool Compound::createFromGeometry(const CompoundGeometry &geom, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega) +{ + clear(); + + nvidia::Array<PxShape*> shapes; + + for (int i = 0; i < (int)geom.convexes.size(); i++) { + Convex *c = mScene->createConvex(); + c->createFromGeometry(geom, i); + c->increaseRefCounter(); + mConvexes.pushBack(c); + + PxVec3 off = c->centerAtZero(); + c->setMaterialOffset(c->getMaterialOffset() + off); + c->createVisMeshFromConvex(); + c->setLocalPose(PxTransform(off)); + + bool reused = c->getPxConvexMesh() != NULL; + + PxConvexMesh* mesh = c->createPxConvexMesh(this, mScene->getPxPhysics(), mScene->getPxCooking()); + if (mesh == NULL) { + if (c->decreaseRefCounter() <= 0) + PX_DELETE(c); + mConvexes.popBack(); + continue; + } + + if (!reused) + convexAdded(c); //mScene->getConvexRenderer().add(c); + +#if (PX_PHYSICS_VERSION_MAJOR == 3) && (PX_PHYSICS_VERSION_MINOR < 3) + PxShape *shape = mScene->getPxPhysics()->createShape( + PxConvexMeshGeometry(mesh), + *mScene->getPxDefaultMaterial(), + true, + c->getLocalPose()); +#else + PxShape *shape = mScene->getPxPhysics()->createShape( + PxConvexMeshGeometry(mesh), + *mScene->getPxDefaultMaterial(), + true + ); + shape->setLocalPose(c->getLocalPose()); +#endif + + shape->setContactOffset(mContactOffset); + shape->setRestOffset(mRestOffset); + + mScene->mapShapeToConvex(*shape, *c); + + shapes.pushBack(shape); + } + + if (shapes.empty()) + return false; + + createPxActor(shapes, pose, vel, omega); + return true; +} + +// -------------------------------------------------------------------------------------------- +void Compound::createFromMesh(const Mesh *mesh, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, int submeshNr, const PxVec3& scale) +{ + const nvidia::Array<PxVec3> &verts = mesh->getVertices(); + const nvidia::Array<PxVec3> &normals = mesh->getNormals(); + const nvidia::Array<PxVec2> &texcoords = mesh->getTexCoords(); + const nvidia::Array<uint32_t> &indices = mesh->getIndices(); + + if (verts.empty() || indices.empty()) + return; + + if (submeshNr >= 0 && submeshNr >= (int)mesh->getSubMeshes().size()) + return; + + PxBounds3 bounds; + mesh->getBounds(bounds, submeshNr); + PxMat33 scaleMat(PxMat33::createDiagonal(scale)); + bounds = PxBounds3::transformSafe(scaleMat, bounds); + + PxVec3 dims = bounds.getDimensions() * 1.01f; + PxVec3 center = bounds.getCenter(); + + mScene->getCompoundCreator()->createBox(dims); + createFromGeometry(mScene->getCompoundCreator()->getGeometry(), pose, vel, omega); + PxTransform trans(-center); + + if (submeshNr < 0) + mConvexes[0]->setExplicitVisMeshFromTriangles((int32_t)verts.size(), &verts[0], &normals[0], &texcoords[0], (int32_t)indices.size(), &indices[0], &trans, &scale); + else { + const Mesh::SubMesh &sm = mesh->getSubMeshes()[(uint32_t)submeshNr]; + mConvexes[0]->setExplicitVisMeshFromTriangles((int32_t)verts.size(), &verts[0], &normals[0], &texcoords[0], sm.numIndices, &indices[(uint32_t)sm.firstIndex], &trans, &scale); + } +} + +// -------------------------------------------------------------------------------------------- +bool Compound::createPxActor(nvidia::Array<PxShape*> &shapes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega) +{ + if (shapes.empty()) + return false; + + for(uint32_t i = 0; i < shapes.size(); i++) + { + applyShapeTemplate(shapes[i]); + } + + PxRigidDynamic* body = mScene->getPxPhysics()->createRigidDynamic(pose); + if (body == NULL) + return false; + + body->setSleepThreshold(getSleepingThresholdRB()); + + physx::PxActorFlags actorFlags = body->getActorFlags(); + actorFlags |= physx::PxActorFlag::eSEND_SLEEP_NOTIFIES; + body->setActorFlags(actorFlags); + + mScene->getScene()->addActor(*body); + + for (uint32_t i = 0; i < shapes.size(); i++) + body->attachShape(*shapes[i]); + + //KS - we clamp the mass in the range [minMass, maxMass]. This helps to improve stability + PxRigidBodyExt::updateMassAndInertia(*body, 1000.0f); +/* + const float maxMass = 50.f; + const float minMass = 1.f; + + float mass = PxMax(PxMin(maxMass, body->getMass()), minMass); + PxRigidBodyExt::setMassAndUpdateInertia(*body, mass); +*/ + + + body->setLinearVelocity(vel); + body->setAngularVelocity(omega); + + mPxActor = body; + for (uint32_t i = 0; i < mConvexes.size(); i++) + mConvexes[i]->setPxActor(mPxActor); + return true; +} + +// -------------------------------------------------------------------------------------------- +bool Compound::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &convexNr, PxVec3 &normal) +{ + dist = PX_MAX_F32; + convexNr = -1; + + for (uint32_t i = 0; i < mConvexes.size(); i++) { + float d; + PxVec3 n; + if (mConvexes[i]->rayCast(orig, dir, d, n)) { + if (d < dist) { + dist = d; + convexNr = (int32_t)i; + normal = n; + } + } + } + return convexNr >= 0; +} + +// -------------------------------------------------------------------------------------------- +void Compound::getRestBounds(PxBounds3 &bounds) const +{ + bounds.setEmpty(); + PxBounds3 bi; + for (uint32_t i = 0; i < mConvexes.size(); i++) { + Convex *c = mConvexes[i]; + PxBounds3 bi = c->getBounds(); + bi = PxBounds3::transformSafe(c->getLocalPose(), bi); + bounds.include(bi); + } +} + +// -------------------------------------------------------------------------------------------- +void Compound::getWorldBounds(PxBounds3 &bounds) const +{ + bounds.setEmpty(); + PxBounds3 bi; + for (uint32_t i = 0; i < mConvexes.size(); i++) { + mConvexes[i]->getWorldBounds(bi); + bounds.include(bi); + } +} + +// -------------------------------------------------------------------------------------------- +void Compound::getLocalBounds(PxBounds3 &bounds) const +{ + bounds.setEmpty(); + PxBounds3 bi; + for (uint32_t i = 0; i < mConvexes.size(); i++) { + mConvexes[i]->getLocalBounds(bi); + bounds.include(bi); + } +} + +// -------------------------------------------------------------------------------------------- +bool Compound::isAttached() +{ + if (mAttachmentBounds.empty()) + return false; + + PxBounds3 b; + for (uint32_t i = 0; i < mConvexes.size(); i++) { + Convex *c = mConvexes[i]; + b = c->getBounds(); + b.minimum += c->getMaterialOffset(); + b.maximum += c->getMaterialOffset(); + for (uint32_t j = 0; j < mAttachmentBounds.size(); j++) { + if (b.intersects(mAttachmentBounds[j])) + return true; + } + } + return false; +} + +// -------------------------------------------------------------------------------------------- +bool Compound::patternFracture(const PxVec3 &pos, float minConvexSize, nvidia::Array<Compound*> &compounds, + const PxMat33 &patternTransform, nvidia::Array<PxVec3>& debugPoints, float impactRadius, + float radialImpulse, const PxVec3 &directedImpulse) +{ + if (mFracturePattern == NULL) + return false; + + if (mDepth >= mActor->mDepthLimit) + { + if (mActor->mDestroyIfAtDepthLimit) + { + mActor->removeCompound(this); + } + else + { + PxTransform pose = mPxActor->getGlobalPose(); + // additional impulse + PxVec3 imp(0.0f, 0.0f, 0.0f); + PxVec3 n = pose.p - pos; + n.normalize(); + imp += n * radialImpulse; + imp += directedImpulse; + // prevent small pieces from getting too fast + const float minMass = 1.0f; + float mass = getPxActor()->getMass(); + if (mass < minMass) + imp *= mass / minMass; + PxRigidBodyExt::addForceAtPos(*getPxActor(), imp, pos, PxForceMode::eIMPULSE); + } + return false; + } + + compounds.clear(); + + //Profiler *p = Profiler::getInstance(); + + PxVec3 hit = pos; + PxTransform pose = mPxActor->getGlobalPose(); + PxVec3 localHit = pose.transformInv(hit); + PxVec3 lv = mPxActor->getLinearVelocity(); + PxVec3 av = mPxActor->getAngularVelocity(); + +// localHit = -pose.t; // foo + + nvidia::Array<Convex*> newConvexes; + nvidia::Array<int> compoundSizes; + nvidia::Array<PxVec3>& crackNormals = mScene->getCrackNormals(); + crackNormals.clear(); + + mScene->profileBegin("getCompoundIntersection"); //Profiler::getInstance()->begin("getCompoundIntersection"); + mFracturePattern->getCompoundIntersection(this, PxMat44(patternTransform, localHit), impactRadius, minConvexSize, compoundSizes, newConvexes); + mScene->profileEnd("getCompoundIntersection"); //Profiler::getInstance()->end("getCompoundIntersection"); + + if (compoundSizes.empty()) + { + return false; + } + + int debugPointsStart = (int32_t)debugPoints.size(); + + uint32_t convexNr = 0; + for (uint32_t i = 0; i < compoundSizes.size(); i++) { + uint32_t num = (uint32_t)compoundSizes[i]; + + PxVec3 off(0.0f, 0.0f, 0.0f); + for (uint32_t j = 0; j < num; j++) { + off += newConvexes[convexNr+j]->getCenter(); + + //PxVec3 pp = pose.p + pose.rotate(newConvexes[convexNr+j]->getCenter()); + //debugPoints.push_back(pp); + } + off /= (float)num; + + addDust(newConvexes,debugPoints,(int32_t&)convexNr,(int32_t&)num); + + mScene->profileBegin("create new compounds"); //Profiler::getInstance()->begin("create new compounds"); + + Compound *m = mScene->createCompound(mSecondardFracturePattern ? mSecondardFracturePattern : mFracturePattern); + + m->mActor = mActor; + m->mDepth = mDepth+1; + m->mNormal = mNormal; + + PxVec3 v = lv + av.cross(pose.rotate(off)); + PxTransform posei = pose; + posei.p += pose.rotate(off); + + if (m->createFromConvexes(&newConvexes[convexNr], (int32_t)num, posei, v, av, false)) { + m->mAttachmentBounds = mAttachmentBounds; + if (m->isAttached()) + { + m->getPxActor()->setActorFlag(physx::PxActorFlag::eSEND_SLEEP_NOTIFIES, false); + m->getPxActor()->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); + } + compounds.pushBack(m); + } + else + { + PX_DELETE(m); + return false; + } + + // decrement depth if outside fracture radius + if (impactRadius > 0.f) + { + const nvidia::Array<Convex*>& convexes = m->getConvexes(); + for (uint32_t i = 0; i < convexes.size(); i++) + { + if (convexes[i]->getIsFarConvex()) + { + m->mDepth--; + break; + } + } + } + + // additional impulse + PxVec3 imp(0.0f, 0.0f, 0.0f); + PxVec3 n = posei.p - hit; + n.normalize(); + imp += n * radialImpulse; + imp += directedImpulse; + + // prevent small pieces from getting too fast + const float minMass = 1.0f; + float mass = m->getPxActor()->getMass(); + if (mass < minMass) + imp *= mass / minMass; + + if (!m->isAttached()) + PxRigidBodyExt::addForceAtPos(*m->getPxActor(), imp, hit, PxForceMode::eIMPULSE); +// m->getPxActor()->addForce(imp / mass, PxForceMode::PxForceMode::eIMPULSE); + + copyShaders(m); + + mScene->profileEnd("create new compounds"); //Profiler::getInstance()->end("create new compounds"); + + convexNr += num; + } + + spawnParticles(crackNormals,debugPoints,debugPointsStart,radialImpulse); + + return true; +} + +// -------------------------------------------------------------------------------------------- +void Compound::attach(const nvidia::Array<PxBounds3> &bounds) +{ + mAttachmentBounds.resize(bounds.size()); + + PxTransform t = getPxActor()->getGlobalPose().getInverse(); + for (uint32_t i = 0; i < bounds.size(); i++) { + PxVec3 a = t.transform(bounds[i].minimum); + PxVec3 b = t.transform(bounds[i].maximum); + mAttachmentBounds[i].minimum = PxVec3(PxMin(a.x,b.x),PxMin(a.y,b.y),PxMin(a.z,b.z)); + mAttachmentBounds[i].maximum = PxVec3(PxMax(a.x,b.x),PxMax(a.y,b.y),PxMax(a.z,b.z)); + } + + if (isAttached()) + mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); +} + +// -------------------------------------------------------------------------------------------- +void Compound::attachLocal(const nvidia::Array<PxBounds3> &bounds) +{ + mAttachmentBounds.resize(bounds.size()); + + for (uint32_t i = 0; i < bounds.size(); i++) { + mAttachmentBounds[i] = bounds[i]; + } + + if (isAttached()) + mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); +} + +void Compound::createPointSamples(float area) { + + pointSamples.clear(); + for (uint32_t i = 0; i < mConvexes.size(); i++) { + Convex* c = mConvexes[i]; + const nvidia::Array<Convex::Face> &faces = c->getFaces(); + const nvidia::Array<int> &indices = c->getIndices(); + const nvidia::Array<PxVec3> &verts = c->getVertices(); + + + + for (uint32_t k = 0; k < faces.size(); k++) { + const Convex::Face& f = faces[k]; + /*int nv = f.numIndices;*/ + + /* + PxVec3 avg(0.0f); + for (int q = 0; q < f.numIndices; q++) { + avg += verts[indices[f.firstIndex+q]]; + } + avg /= f.numIndices; + pointSamples.pushBack(avg); + */ + nvidia::Array<PxVec3>& tmpPoints = mScene->getTmpPoints(); + tmpPoints.clear(); + for (int q = 0; q < f.numIndices; q++) { + tmpPoints.pushBack(verts[(uint32_t)indices[uint32_t(f.firstIndex+q)]]); + } + appendUniformSamplesOfConvexPolygon(&tmpPoints[0], (int32_t)tmpPoints.size(), area, pointSamples); + + } + + } +} + + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/CompoundBase.h b/APEX_1.4/module/destructible/fracture/Core/CompoundBase.h new file mode 100644 index 00000000..d21f2edc --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/CompoundBase.h @@ -0,0 +1,160 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef COMPOUNDBASE +#define COMPOUNDBASE + +#define DEMO_MODE 1 +#define TECHNICAL_MODE 0 + +#include <PxVec3.h> +#include <PxPlane.h> +#include <PxBounds3.h> +#include <PxTransform.h> +#include <PsArray.h> +#include <PxRigidDynamic.h> +#include <PsUserAllocated.h> + + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +class Convex; +class FracturePattern; +class Mesh; +class SimScene; +class CompoundGeometry; +class Actor; + +// ----------------------------------------------------------------------------------- +class Compound : public UserAllocated +{ + friend class SimScene; + friend class Actor; +protected: + Compound(SimScene* scene, const FracturePattern *pattern, const FracturePattern *secondaryPattern = NULL, float contactOffset = 0.005f, float restOffset = -0.001f); +public: + virtual ~Compound(); + + virtual bool createFromConvexes(Convex** convexes, int numConvexes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes = true); + bool createFromConvex(Convex* convex, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes = true); + bool createFromGeometry(const CompoundGeometry &geom, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega); + void createFromMesh(const Mesh *mesh, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, int submeshNr = -1, const PxVec3& scale = PxVec3(1.f)); + //bool createFromXml(XMLParser *p, float scale, const PxTransform &trans, bool ignoreVisualMesh = false); + + virtual void applyShapeTemplate(PxShape* /*shape*/) {} + + bool rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &convexNr, PxVec3 &normal); + void setLifeFrames(int frames) { mLifeFrames = frames == 0 ? 1 : frames; } + int getLifeFrames() { return mLifeFrames; } + + bool patternFracture(const PxVec3 &pos, float minConvexSize, nvidia::Array<Compound*> &compounds, + const PxMat33 &patternTransform, nvidia::Array<PxVec3>& debugPoints, float impactRadius, float radialImpulse, const PxVec3 &directedImpulse); + // impactRadius controls partial fracture. For impactRadius == 0.0f the fracture is global + + // event notification + virtual void spawnParticles(nvidia::Array<PxVec3>& /*crackNormals*/,nvidia::Array<PxVec3>& /*debugPoints*/,int /*debugPointsStart*/, float /*radialImpulse*/) {} + virtual void convexAdded(Convex* /*c*/) {} + virtual void convexRemoved(Convex* /*c*/) {} + + bool decompose(FracturePattern *pattern, nvidia::Array<Compound*> &compounds); + void attach(const nvidia::Array<PxBounds3> &bounds); + void attachLocal(const nvidia::Array<PxBounds3> &bounds); + + const nvidia::Array<Convex*>& getConvexes() const { return mConvexes; } + const nvidia::Array<PxBounds3>& getAttachmentBounds() const { return mAttachmentBounds; } + + PxRigidDynamic* getPxActor() { return mPxActor; } + void getWorldBounds(PxBounds3 &bounds) const; + void getLocalBounds(PxBounds3 &bounds) const; + void getRestBounds(PxBounds3 &bounds) const; + + //void setShader(Shader* shader, const ShaderMaterial &mat) { mShader = shader; mShaderMat = mat; } + //Shader* getShader() const { return mShader; } + //const ShaderMaterial& getShaderMat() { return mShaderMat; } + + void setKinematic(const PxVec3 &vel); + void step(float dt); + + virtual void draw(bool /*useShader*/, bool /*debug*/ = false) {} + + virtual void clear(); + + void setAdditionalImpactImpulse(float radial, float normal) { + mAdditionalImpactRadialImpulse = radial; mAdditionalImpactNormalImpulse = normal; + } + float getAdditionalImpactRadialImpulse() const { return mAdditionalImpactRadialImpulse; } + float getAdditionalImpactNormalImpulse() const { return mAdditionalImpactNormalImpulse; } + + virtual void copyShaders(Compound*) {} + +protected: + void createPointSamples(float area); + + bool isAttached(); + + bool createPxActor(nvidia::Array<PxShape*> &shapes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega); + + virtual void addDust(nvidia::Array<Convex*>& /*newConvexes*/,nvidia::Array<PxVec3>& /*debugPoints*/,int& /*convexNr*/,int& /*num*/) {} + + static void appendUniformSamplesOfConvexPolygon(PxVec3* vertices, int numV, float area, nvidia::Array<PxVec3>& samples, nvidia::Array<PxVec3>* normals = NULL); + + virtual float getSleepingThresholdRB() {return 0.1f;} + + struct Edge { + void init(int c0, int c1) { + this->c0 = c0; this->c1 = c1; + restLen = 0.0f; + deleted = false; + } + int c0, c1; + float restLen; + bool deleted; + }; + + nvidia::Array<Convex*> mConvexes; + nvidia::Array<Edge> mEdges; + + SimScene *mScene; + Actor *mActor; + PxRigidDynamic *mPxActor; + const FracturePattern *mFracturePattern; + const FracturePattern *mSecondardFracturePattern; + PxVec3 mKinematicVel; + nvidia::Array<PxBounds3> mAttachmentBounds; + + //Shader *mShader; + //ShaderMaterial mShaderMat; + + float mContactOffset; + float mRestOffset; + + int mLifeFrames; + + float mAdditionalImpactNormalImpulse; + float mAdditionalImpactRadialImpulse; + + nvidia::Array<PxVec3> pointSamples; + + uint32_t mDepth; // fracture depth + PxVec3 mNormal; // normal use with mSheetFracture +}; + +}}} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/CompoundCreatorBase.cpp b/APEX_1.4/module/destructible/fracture/Core/CompoundCreatorBase.cpp new file mode 100644 index 00000000..d68df78f --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/CompoundCreatorBase.cpp @@ -0,0 +1,805 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "CompoundCreatorBase.h" +#include <algorithm> +#include <PxAssert.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace nvidia; + +int CompoundCreator::tetFaceIds[4][3] = {{0,1,3},{1,2,3},{2,0,3},{0,2,1}}; +int CompoundCreator::tetEdgeVerts[6][2] = {{0,1},{1,2},{2,0},{0,3},{1,3},{2,3}}; +int CompoundCreator::tetFaceEdges[4][3] = {{0,4,3},{1,5,4},{2,3,5},{0,2,1}}; + +#define CONVEX_THRESHOLD (PxPi + 0.05f) + +// ----------------------------------------------------------------------------- +void CompoundCreator::createTorus(float r0, float r1, int numSegs0, int numSegs1, const PxTransform *trans) +{ + mGeom.clear(); + CompoundGeometry::Convex c; + PxVec3 nr0,nr1,nz; + nz = PxVec3(0.0f, 0.0f, 1.0f); + PxVec3 p,n; + PxTransform t = PxTransform(PxIdentity); + if (trans) + t = *trans; + + nvidia::Array<PxVec3> normals; + + float dphi0 = PxTwoPi / (float)numSegs0; + float dphi1 = PxTwoPi / (float)numSegs1; + for (int i = 0; i < numSegs0; i++) { + nr0 = PxVec3(PxCos(i*dphi0), PxSin(i*dphi0), 0.0f); + nr1 = PxVec3(PxCos((i+1)*dphi0), PxSin((i+1)*dphi0), 0.0f); + mGeom.initConvex(c); + c.numVerts = 2*numSegs1; + normals.clear(); + for (int j = 0; j < numSegs1; j++) { + p = nr0 * (r0 + r1 * PxCos(j*dphi1)) + nz * r1 * PxSin(j*dphi1); + mGeom.vertices.pushBack(t.transform(p)); + n = nr0 * (PxCos(j*dphi1)) + nz * PxSin(j*dphi1); + normals.pushBack(t.rotate(n)); + + p = nr1 * (r0 + r1 * PxCos(j*dphi1)) + nz * r1 * PxSin(j*dphi1); + mGeom.vertices.pushBack(t.transform(p)); + n = nr1 * (PxCos(j*dphi1)) + nz * PxSin(j*dphi1); + normals.pushBack(t.rotate(n)); + } + + c.numFaces = 2 + numSegs1; + mGeom.indices.pushBack(numSegs1); // face size + mGeom.indices.pushBack(CompoundGeometry::FF_INVISIBLE); // face flags + for (int j = 0; j < numSegs1; j++) + mGeom.indices.pushBack(2*j); + mGeom.indices.pushBack(numSegs1); // face size + mGeom.indices.pushBack(CompoundGeometry::FF_INVISIBLE); // face flags + for (int j = 0; j < numSegs1; j++) { + mGeom.indices.pushBack(2*(numSegs1-1-j) + 1); + } + for (int j = 0; j < numSegs1; j++) { + int k = (j+1)%numSegs1; + mGeom.indices.pushBack(4); // face size + mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE | CompoundGeometry::FF_HAS_NORMALS); + int i0 = 2*j; + int i1 = 2*j+1; + int i2 = 2*k+1; + int i3 = 2*k; + mGeom.indices.pushBack(i0); + mGeom.indices.pushBack(i1); + mGeom.indices.pushBack(i2); + mGeom.indices.pushBack(i3); + mGeom.normals.pushBack(normals[(uint32_t)i0]); + mGeom.normals.pushBack(normals[(uint32_t)i1]); + mGeom.normals.pushBack(normals[(uint32_t)i2]); + mGeom.normals.pushBack(normals[(uint32_t)i3]); + } + c.numNeighbors = 2; + mGeom.neighbors.pushBack((i + (numSegs0-1)) % numSegs0); + mGeom.neighbors.pushBack((i + 1) % numSegs0); + mGeom.convexes.pushBack(c); + } +} + +// ----------------------------------------------------------------------------- +void CompoundCreator::createCylinder(float r, float h, int numSegs, const PxTransform *trans) +{ + PxTransform t = PxTransform(PxIdentity); + if (trans) + t = *trans; + + mGeom.clear(); + CompoundGeometry::Convex c; + mGeom.initConvex(c); + + float dphi = PxTwoPi / (float)numSegs; + c.numVerts = 2*numSegs; + mGeom.vertices.resize((uint32_t)c.numVerts); + + for (int i = 0; i < numSegs; i++) { + PxVec3 p0(r * PxCos(i*dphi), r * PxSin(i*dphi), -0.5f * h); + PxVec3 p1(r * PxCos(i*dphi), r * PxSin(i*dphi), 0.5f * h); + mGeom.vertices[2*(uint32_t)i] = t.transform(p0); + mGeom.vertices[2*(uint32_t)i+1] = t.transform(p1); + } + + c.numFaces = 2 + numSegs; + + mGeom.indices.pushBack(numSegs); + mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE); + for (int i = 0; i < numSegs; i++) + mGeom.indices.pushBack(2*(numSegs-1-i)); + mGeom.indices.pushBack(numSegs); + mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE); + for (int i = 0; i < numSegs; i++) + mGeom.indices.pushBack(2*i+1); + + for (int i = 0; i < numSegs; i++) { + int j = (i+1) % numSegs; + + PxVec3 n0(PxCos(i*dphi),PxSin(i*dphi),0.0f); + PxVec3 n1(PxCos(j*dphi),PxSin(j*dphi),0.0f); + + n0 = t.rotate(n0); + n1 = t.rotate(n1); + //n0*=-1; + //n1*=-1; + mGeom.indices.pushBack(4); + mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE | CompoundGeometry::FF_HAS_NORMALS); + mGeom.indices.pushBack(2*i); + mGeom.indices.pushBack(2*j); + mGeom.indices.pushBack(2*j+1); + mGeom.indices.pushBack(2*i+1); + mGeom.normals.pushBack(n0); + mGeom.normals.pushBack(n1); + mGeom.normals.pushBack(n1); + mGeom.normals.pushBack(n0); + } + mGeom.convexes.pushBack(c); +} + +// ----------------------------------------------------------------------------- +void CompoundCreator::createBox(const PxVec3 &dims, const PxTransform *trans) +{ + PxTransform t = PxTransform(PxIdentity); + if (trans) + t = *trans; + + mGeom.clear(); + CompoundGeometry::Convex c; + mGeom.initConvex(c); + + c.numVerts = 8; + mGeom.vertices.clear(); + mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, -0.5f * dims.y, -0.5f * dims.z))); + mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, -0.5f * dims.y, -0.5f * dims.z))); + mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, 0.5f * dims.y, -0.5f * dims.z))); + mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, 0.5f * dims.y, -0.5f * dims.z))); + mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, -0.5f * dims.y, 0.5f * dims.z))); + mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, -0.5f * dims.y, 0.5f * dims.z))); + mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, 0.5f * dims.y, 0.5f * dims.z))); + mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, 0.5f * dims.y, 0.5f * dims.z))); + + static int faceIds[6][4] = {{0,1,5,4},{1,2,6,5},{2,3,7,6},{3,0,4,7},{0,3,2,1},{4,5,6,7}}; + + c.numFaces = 6; + for (int i = 0; i < 6; i++) { + mGeom.indices.pushBack(4); + mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE); + for (int j = 0; j < 4; j++) + mGeom.indices.pushBack(faceIds[i][j]); + } + mGeom.convexes.pushBack(c); +} + +// ----------------------------------------------------------------------------- +void CompoundCreator::createSphere(const PxVec3 &dims, int resolution, const PxTransform *trans) +{ + PxTransform t = PxTransform(PxIdentity); + if (trans) + t = *trans; + + if (resolution < 2) resolution = 2; + int numSegs0 = 2*resolution; + int numSegs1 = resolution; + + float rx = 0.5f * dims.x; + float ry = 0.5f * dims.y; + float rz = 0.5f * dims.z; + + mGeom.clear(); + CompoundGeometry::Convex c; + mGeom.initConvex(c); + + float dphi = PxTwoPi / (float)numSegs0; + float dteta = PxPi / (float)numSegs1; + PxVec3 p, n; + + for (int i = 1; i < numSegs1; i++) { + for (int j = 0; j < numSegs0; j++) { + float phi = j * dphi; + float teta = -PxHalfPi + i * dteta; + p = PxVec3(PxCos(phi)*PxCos(teta), PxSin(phi)*PxCos(teta), PxSin(teta)); + mGeom.vertices.pushBack(PxVec3(p.x * rx, p.y * ry, p.z * rz)); + } + } + int bottomNr = (int32_t)mGeom.vertices.size(); + mGeom.vertices.pushBack(PxVec3(0.0f, 0.0f, -rz)); + int topNr = (int32_t)mGeom.vertices.size(); + mGeom.vertices.pushBack(PxVec3(0.0f, 0.0f, +rz)); + + c.numVerts = (int32_t)mGeom.vertices.size(); + + for (int i = 0; i < numSegs1-2; i++) { + for (int j = 0; j < numSegs0; j++) { + mGeom.indices.pushBack(4); // face size + mGeom.indices.pushBack(CompoundGeometry::FF_HAS_NORMALS | CompoundGeometry::FF_OBJECT_SURFACE); + int i0 = i*numSegs0 + j; + int i1 = i*numSegs0 + (j+1)%numSegs0; + int i2 = (i+1)*numSegs0 + (j+1)%numSegs0; + int i3 = (i+1)*numSegs0 + j; + mGeom.indices.pushBack(i0); + mGeom.indices.pushBack(i1); + mGeom.indices.pushBack(i2); + mGeom.indices.pushBack(i3); + n = mGeom.vertices[(uint32_t)i0]; n.normalize(); mGeom.normals.pushBack(n); + n = mGeom.vertices[(uint32_t)i1]; n.normalize(); mGeom.normals.pushBack(n); + n = mGeom.vertices[(uint32_t)i2]; n.normalize(); mGeom.normals.pushBack(n); + n = mGeom.vertices[(uint32_t)i3]; n.normalize(); mGeom.normals.pushBack(n); + c.numFaces++; + } + } + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < numSegs0; j++) { + mGeom.indices.pushBack(3); // face size + mGeom.indices.pushBack(CompoundGeometry::FF_HAS_NORMALS | CompoundGeometry::FF_OBJECT_SURFACE); + int i0,i1,i2; + if (i == 0) { + i0 = j; + i1 = bottomNr; + i2 = (j+1)%numSegs0; + } + else { + i0 = (numSegs1-2)*numSegs0 + j; + i1 = (numSegs1-2)*numSegs0 + (j+1)%numSegs0; + i2 = topNr; + } + mGeom.indices.pushBack(i0); + mGeom.indices.pushBack(i1); + mGeom.indices.pushBack(i2); + n = mGeom.vertices[(uint32_t)i0]; n.normalize(); mGeom.normals.pushBack(n); + n = mGeom.vertices[(uint32_t)i1]; n.normalize(); mGeom.normals.pushBack(n); + n = mGeom.vertices[(uint32_t)i2]; n.normalize(); mGeom.normals.pushBack(n); + c.numFaces++; + } + } + mGeom.convexes.pushBack(c); +} + +// ----------------------------------------------------------------------------- +void CompoundCreator::fromTetraMesh(const nvidia::Array<PxVec3> &tetVerts, const nvidia::Array<int> &tetIndices) +{ + mTetVertices = tetVerts; + mTetIndices = tetIndices; + deleteColors(); + + computeTetNeighbors(); + computeTetEdges(); + colorTets(); + colorsToConvexes(); +} + +// ----------------------------------------------------------------------------- +void CompoundCreator::computeTetNeighbors() +{ + uint32_t numTets = mTetIndices.size() / 4; + + struct TetFace { + void init(int i0, int i1, int i2, int faceNr, int tetNr) { + if (i0 > i1) { int i = i0; i0 = i1; i1 = i; } + if (i1 > i2) { int i = i1; i1 = i2; i2 = i; } + if (i0 > i1) { int i = i0; i0 = i1; i1 = i; } + this->i0 = i0; this->i1 = i1; this->i2 = i2; + this->faceNr = faceNr; this->tetNr = tetNr; + } + bool operator < (const TetFace &f) const { + if (i0 < f.i0) return true; + if (i0 > f.i0) return false; + if (i1 < f.i1) return true; + if (i1 > f.i1) return false; + return i2 < f.i2; + } + bool operator == (const TetFace &f) const { + return i0 == f.i0 && i1 == f.i1 && i2 == f.i2; + } + int i0,i1,i2; + int faceNr, tetNr; + }; + nvidia::Array<TetFace> faces(numTets * 4); + + for (uint32_t i = 0; i < numTets; i++) { + int ids[4]; + ids[0] = mTetIndices[4*i]; + ids[1] = mTetIndices[4*i+1]; + ids[2] = mTetIndices[4*i+2]; + ids[3] = mTetIndices[4*i+3]; + for (uint32_t j = 0; j < 4; j++) { + int i0 = ids[(uint32_t)tetFaceIds[j][0]]; + int i1 = ids[(uint32_t)tetFaceIds[j][1]]; + int i2 = ids[(uint32_t)tetFaceIds[j][2]]; + faces[4*i+j].init(i0,i1,i2, (int32_t)j, (int32_t)i); + } + } + std::sort(faces.begin(), faces.end()); + + mTetNeighbors.clear(); + mTetNeighbors.resize(numTets * 4, -1); + uint32_t i = 0; + while (i < faces.size()) { + TetFace &f0 = faces[i]; + i++; + if (i < faces.size() && faces[i] == f0) { + TetFace &f1 = faces[i]; + mTetNeighbors[uint32_t(4*f0.tetNr + f0.faceNr)] = f1.tetNr; + mTetNeighbors[uint32_t(4*f1.tetNr + f1.faceNr)] = f0.tetNr; + while (i < faces.size() && faces[i] == f0) + i++; + } + } +} + +// ----------------------------------------------------------------------------- +void CompoundCreator::computeTetEdges() +{ + uint32_t numTets = mTetIndices.size() / 4; + + struct SortEdge { + void init(int i0, int i1, int edgeNr, int tetNr) { + if (i0 < i1) { this->i0 = i0; this->i1 = i1; } + else { this->i0 = i1; this->i1 = i0; } + this->edgeNr = edgeNr; this->tetNr = tetNr; + } + bool operator < (const SortEdge &e) const { + if (i0 < e.i0) return true; + if (i0 > e.i0) return false; + return i1 < e.i1; + } + bool operator == (const SortEdge &e) const { + return i0 == e.i0 && i1 == e.i1; + } + int i0,i1; + int edgeNr, tetNr; + }; + nvidia::Array<SortEdge> edges(numTets * 6); + + for (uint32_t i = 0; i < numTets; i++) { + int ids[4]; + ids[0] = mTetIndices[4*i]; + ids[1] = mTetIndices[4*i+1]; + ids[2] = mTetIndices[4*i+2]; + ids[3] = mTetIndices[4*i+3]; + for (uint32_t j = 0; j < 6; j++) { + int i0 = ids[(uint32_t)tetEdgeVerts[j][0]]; + int i1 = ids[(uint32_t)tetEdgeVerts[j][1]]; + edges[6*i + j].init(i0,i1, (int32_t)j, (int32_t)i); + } + } + std::sort(edges.begin(), edges.end()); + + mTetEdgeNrs.clear(); + mTetEdgeNrs.resize(numTets * 6, -1); + mTetEdges.clear(); + mEdgeTetNrs.clear(); + mEdgeTetAngles.clear(); + TetEdge te; + + struct ChainVert { + int adjVert0; + int adjVert1; + int tet0; + int tet1; + float dihed0; + float dihed1; + int mark; + }; + ChainVert cv; + cv.mark = 0; + nvidia::Array<ChainVert> chainVerts(mTetVertices.size(), cv); + nvidia::Array<int> chainVertNrs; + + int mark = 1; + + uint32_t i = 0; + while (i < edges.size()) { + SortEdge &e0 = edges[i]; + int edgeNr = (int32_t)mTetEdges.size(); + te.init(e0.i0, e0.i1); + te.firstTet = (int32_t)mEdgeTetNrs.size(); + te.numTets = 0; + mark++; + chainVertNrs.clear(); + do { + SortEdge &e = edges[i]; + mTetEdgeNrs[uint32_t(6 * e.tetNr + e.edgeNr)] = edgeNr; + int i2 = -1; + int i3 = -1; + for (uint32_t j = 0; j < 4; j++) { + int id = mTetIndices[4 * (uint32_t)e.tetNr + j]; + if (id != e0.i0 && id != e0.i1) { + if (i2 < 0) i2 = id; + else i3 = id; + } + } + PX_ASSERT(i2 >= 0 && i3 >= 0); + + // dihedral angle at edge + PxVec3 &p0 = mTetVertices[(uint32_t)e0.i0]; + PxVec3 &p1 = mTetVertices[(uint32_t)e0.i1]; + PxVec3 &p2 = mTetVertices[(uint32_t)i2]; + PxVec3 &p3 = mTetVertices[(uint32_t)i3]; + PxVec3 n2 = (p1-p0).cross(p2-p0); n2.normalize(); + if ((p3-p0).dot(n2) > 0.0f) n2 = -n2; + PxVec3 n3 = (p1-p0).cross(p3-p0); n3.normalize(); + if ((p2-p0).dot(n3) > 0.0f) n3 = -n3; + float dot = n2.dot(n3); + float dihed = PxPi - PxAcos(dot); + + // chain for ordering tets of edge correctly + ChainVert &cv2 = chainVerts[(uint32_t)i2]; + ChainVert &cv3 = chainVerts[(uint32_t)i3]; + if (cv2.mark != mark) { cv2.adjVert0 = -1; cv2.adjVert1 = -1; cv2.mark = mark; } + if (cv3.mark != mark) { cv3.adjVert0 = -1; cv3.adjVert1 = -1; cv3.mark = mark; } + + if (cv2.adjVert0 < 0) { cv2.adjVert0 = i3; cv2.tet0 = e.tetNr; cv2.dihed0 = dihed; } + else { cv2.adjVert1 = i3; cv2.tet1 = e.tetNr; cv2.dihed1 = dihed; } + if (cv3.adjVert0 < 0) { cv3.adjVert0 = i2; cv3.tet0 = e.tetNr; cv3.dihed0 = dihed; } + else { cv3.adjVert1 = i2; cv3.tet1 = e.tetNr; cv3.dihed1 = dihed; } + + chainVertNrs.pushBack(i2); + chainVertNrs.pushBack(i3); + i++; + } + while (i < edges.size() && edges[i] == e0); + + te.numTets = (int32_t)chainVertNrs.size() / 2; + // find chain start; + int startVertNr = -1; + for (uint32_t j = 0; j < chainVertNrs.size(); j++) { + ChainVert &cv = chainVerts[(uint32_t)chainVertNrs[j]]; + if (cv.adjVert0 < 0 || cv.adjVert1 < 0) { + startVertNr = chainVertNrs[j]; + break; + } + } + te.onSurface = startVertNr >= 0; + mTetEdges.pushBack(te); + + int curr = startVertNr; + if (curr < 0) curr = chainVertNrs[0]; + int prev = -1; + + // collect adjacent tetrahedra + for (int j = 0; j < te.numTets; j++) { + ChainVert &cv = chainVerts[(uint32_t)curr]; + int next; + if (cv.adjVert0 == prev) { + next = cv.adjVert1; + mEdgeTetNrs.pushBack(cv.tet1); + mEdgeTetAngles.pushBack(cv.dihed1); + } + else { + next = cv.adjVert0; + mEdgeTetNrs.pushBack(cv.tet0); + mEdgeTetAngles.pushBack(cv.dihed0); + } + prev = curr; + curr = next; + } + } +} + +// ----------------------------------------------------------------------------- +bool CompoundCreator::tetHasColor(int tetNr, int color) +{ + int nr = mTetFirstColor[(uint32_t)tetNr]; + while (nr >= 0) { + if (mTetColors[(uint32_t)nr].color == color) + return true; + nr = mTetColors[(uint32_t)nr].next; + } + return false; +} + +// ----------------------------------------------------------------------------- +bool CompoundCreator::tetAddColor(int tetNr, int color) +{ + if (tetHasColor(tetNr, color)) + return false; + Color c; + c.color = color; + c.next = mTetFirstColor[(uint32_t)tetNr]; + + if (mTetColorsFirstEmpty <= 0) { // new entry + mTetFirstColor[(uint32_t)tetNr] = (int32_t)mTetColors.size(); + mTetColors.pushBack(c); + } + else { // take from empty list + int newNr = mTetColorsFirstEmpty; + mTetFirstColor[(uint32_t)tetNr] = newNr; + mTetColorsFirstEmpty = mTetColors[(uint32_t)newNr].next; + mTetColors[(uint32_t)newNr] = c; + } + return true; +} + +// ----------------------------------------------------------------------------- +bool CompoundCreator::tetRemoveColor(int tetNr, int color) +{ + int nr = mTetFirstColor[(uint32_t)tetNr]; + int prev = -1; + while (nr >= 0) { + if (mTetColors[(uint32_t)nr].color == color) { + if (prev < 0) + mTetFirstColor[(uint32_t)tetNr] = mTetColors[(uint32_t)nr].next; + else + mTetColors[(uint32_t)prev].next = mTetColors[(uint32_t)nr].next; + + // add to empty list + mTetColors[(uint32_t)nr].next = mTetColorsFirstEmpty; + mTetColorsFirstEmpty = nr; + return true; + } + prev = nr; + nr = mTetColors[(uint32_t)nr].next; + } + return false; +} + +// ----------------------------------------------------------------------------- +int CompoundCreator::tetNumColors(int tetNr) +{ + int num = 0; + int nr = mTetFirstColor[(uint32_t)tetNr]; + while (nr >= 0) { + num++; + nr = mTetColors[(uint32_t)nr].next; + } + return num; +} + +// ----------------------------------------------------------------------------- +void CompoundCreator::deleteColors() +{ + mTetFirstColor.resize(mTetIndices.size()/4, -1); + mTetColors.clear(); + mTetColorsFirstEmpty = -1; +} + +// ----------------------------------------------------------------------------- +bool CompoundCreator::tryTet(int tetNr, int color) +{ + if (tetNr < 0) + return false; + + //if (mTetColors[tetNr] >= 0) + // return false; + + if (tetHasColor(tetNr, color)) + return false; + + mTestEdges.clear(); + mAddedTets.clear(); + + tetAddColor(tetNr, color); + mAddedTets.pushBack(tetNr); + + for (int i = 0; i < 6; i++) + mTestEdges.pushBack(mTetEdgeNrs[uint32_t(6*tetNr+i)]); + + bool failed = false; + + while (mTestEdges.size() > 0) { + int edgeNr = mTestEdges[mTestEdges.size()-1]; + mTestEdges.popBack(); + + TetEdge &e = mTetEdges[(uint32_t)edgeNr]; + bool anyOtherCol = false; + float sumAng = 0.0f; + for (int i = 0; i < e.numTets; i++) { + int edgeTetNr = mEdgeTetNrs[uint32_t(e.firstTet + i)]; + if (tetHasColor(edgeTetNr, color)) + sumAng += mEdgeTetAngles[uint32_t(e.firstTet + i)]; + else if (tetNumColors(edgeTetNr) > 0) + anyOtherCol = true; + } + if (sumAng < CONVEX_THRESHOLD) + continue; + +// if (e.onSurface || anyOtherCol) { + if (e.onSurface) { + failed = true; + break; + } + + for (int i = 0; i < e.numTets; i++) { + int edgeTetNr = mEdgeTetNrs[uint32_t(e.firstTet + i)]; + if (!tetHasColor(edgeTetNr, color)) { + tetAddColor(edgeTetNr, color); + mAddedTets.pushBack(edgeTetNr); + for (int j = 0; j < 6; j++) + mTestEdges.pushBack(mTetEdgeNrs[uint32_t(6*edgeTetNr+j)]); + } + } + } + if (failed) { + for (uint32_t i = 0; i < mAddedTets.size(); i++) + tetRemoveColor(mAddedTets[i], color); + mAddedTets.clear(); + return false; + } + + return true; +} + +// ----------------------------------------------------------------------------- +void CompoundCreator::colorTets() +{ + int numTets = (int32_t)mTetIndices.size() / 4; + deleteColors(); + + int color = 0; + nvidia::Array<int> edges; + nvidia::Array<int> faces; + + for (int i = 0; i < numTets; i++) { + if (tetNumColors(i) > 0) + continue; + + tetAddColor(i, color); + faces.clear(); + faces.pushBack(4*i); + faces.pushBack(4*i+1); + faces.pushBack(4*i+2); + faces.pushBack(4*i+3); + + while (faces.size() > 0) { + int faceNr = faces[faces.size()-1]; + faces.popBack(); + + int adjTetNr = mTetNeighbors[(uint32_t)faceNr]; + + if (adjTetNr < 0) + continue; + + //if (tetNumColors(adjTetNr) > 0) + // continue; + + if (!tryTet(adjTetNr, color)) + continue; + + for (uint32_t j = 0; j < mAddedTets.size(); j++) { + int addedTet = mAddedTets[j]; + for (int k = 0; k < 4; k++) { + int adj = mTetNeighbors[uint32_t(4*addedTet+k)]; + if (adj >= 0 && !tetHasColor(adj, color)) + faces.pushBack(4*addedTet+k); + } + } + } + color++; + } +} + +// ----------------------------------------------------------------------------- +void CompoundCreator::colorsToConvexes() +{ + mGeom.clear(); + + int numTets = (int32_t)mTetIndices.size() / 4; + int numColors = 0; + for (uint32_t i = 0; i < mTetColors.size(); i++) { + int color = mTetColors[i].color; + if (color >= numColors) + numColors = color+1; + } + + nvidia::Array<bool> colorVisited((uint32_t)numColors, false); + nvidia::Array<int> queue; + nvidia::Array<int> globalToLocal(mTetVertices.size(), -1); + + nvidia::Array<int> tetMarks((uint32_t)numTets, 0); + nvidia::Array<int> vertMarks(mTetVertices.size(), 0); + int mark = 1; + + nvidia::Array<int> colorToConvexNr; + + CompoundGeometry::Convex c; + + for (uint32_t i = 0; i < (uint32_t)numTets; i++) { + int nr = mTetFirstColor[i]; + while (nr >= 0) { + uint32_t color = (uint32_t)mTetColors[(uint32_t)nr].color; + nr = mTetColors[(uint32_t)nr].next; + + if (colorVisited[color]) + continue; + colorVisited[color] = true; + + if ((uint32_t)colorToConvexNr.size() <= color) + colorToConvexNr.resize(color+1, -1); + colorToConvexNr[color] = (int32_t)mGeom.convexes.size(); + + queue.clear(); + queue.pushBack((int32_t)i); + + mGeom.initConvex(c); + mark++; + c.numVerts = 0; + + // flood fill + while (!queue.empty()) { + uint32_t tetNr = (uint32_t)queue[queue.size()-1]; + queue.popBack(); + if (tetMarks[tetNr] == mark) + continue; + tetMarks[tetNr] = mark; + + for (uint32_t j = 0; j < 4; j++) { + int adjNr = mTetNeighbors[4*tetNr + j]; + if (adjNr < 0 || !tetHasColor(adjNr, (int32_t)color)) { + // create new face + mGeom.indices.pushBack(3); // face size + int flags = 0; + if (adjNr < 0) flags |= CompoundGeometry::FF_OBJECT_SURFACE; + mGeom.indices.pushBack(flags); + + for (uint32_t k = 0; k < 3; k++) { + uint32_t id = (uint32_t)mTetIndices[4*tetNr + tetFaceIds[j][k]]; + if (vertMarks[id] != mark) { + vertMarks[id] = mark; + globalToLocal[id] = c.numVerts; + c.numVerts++; + mGeom.vertices.pushBack(mTetVertices[id]); + } + mGeom.indices.pushBack(globalToLocal[id]); + } + c.numFaces++; + } + if (adjNr >= 0) { + // add neighbors + int colNr = mTetFirstColor[(uint32_t)adjNr]; + while (colNr >= 0) { + int adjColor = mTetColors[(uint32_t)colNr].color; + colNr = mTetColors[(uint32_t)colNr].next; + if (adjColor != (int32_t)color) { + bool isNew = true; + for (int k = 0; k < c.numNeighbors; k++) { + if (mGeom.neighbors[uint32_t(c.firstNeighbor+k)] == adjColor) { + isNew = false; + break; + } + } + if (isNew) { + mGeom.neighbors.pushBack(adjColor); + c.numNeighbors++; + } + } + } + } + if (adjNr < 0 || !tetHasColor(adjNr, (int32_t)color) || tetMarks[(uint32_t)adjNr] == mark) + continue; + queue.pushBack(adjNr); + } + } + mGeom.convexes.pushBack(c); + } + } + + for (uint32_t i = 0; i < mGeom.neighbors.size(); i++) { + if (mGeom.neighbors[i] >= 0) + mGeom.neighbors[i] = colorToConvexNr[(uint32_t)mGeom.neighbors[i]]; + } +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/CompoundCreatorBase.h b/APEX_1.4/module/destructible/fracture/Core/CompoundCreatorBase.h new file mode 100644 index 00000000..0805fc67 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/CompoundCreatorBase.h @@ -0,0 +1,110 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef COMPOUND_CREATOR_BASE_H +#define COMPOUND_CREATOR_BASE_H + +// Matthias Muller-Fischer + +#include <PxVec3.h> +#include <PxTransform.h> +#include <PsArray.h> +#include <PsUserAllocated.h> + +#include "CompoundGeometryBase.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + class SimScene; + +// --------------------------------------------------------------------------------------- +class CompoundCreator : public UserAllocated { + friend class nvidia::fracture::base::SimScene; +public: + // direct + void createTorus(float r0, float r1, int numSegs0, int numSegs1, const PxTransform *trans = NULL); + void createCylinder(float r, float h, int numSegs, const PxTransform *trans = NULL); + void createBox(const PxVec3 &dims, const PxTransform *trans = NULL); + void createSphere(const PxVec3 &dims, int resolution = 5, const PxTransform *trans = NULL); + void fromTetraMesh(const nvidia::Array<PxVec3> &tetVerts, const nvidia::Array<int> &tetIndices); + + const CompoundGeometry &getGeometry() { return mGeom; } + + virtual void debugDraw() {} + +protected: + CompoundCreator(SimScene* scene): mScene(scene) {} + virtual ~CompoundCreator() {} + + SimScene* mScene; + + static int tetFaceIds[4][3]; + static int tetEdgeVerts[6][2]; + static int tetFaceEdges[4][3]; + + void computeTetNeighbors(); + void computeTetEdges(); + void colorTets(); + void colorsToConvexes(); + + bool tetHasColor(int tetNr, int color); + bool tetAddColor(int tetNr, int color); + bool tetRemoveColor(int tetNr, int color); + int tetNumColors(int tetNr); + void deleteColors(); + + bool tryTet(int tetNr, int color); + + // from tet mesh + nvidia::Array<PxVec3> mTetVertices; + nvidia::Array<int> mTetIndices; + nvidia::Array<int> mTetNeighbors; + + nvidia::Array<int> mTetFirstColor; + struct Color { + int color; + int next; + }; + int mTetColorsFirstEmpty; + nvidia::Array<Color> mTetColors; + + struct TetEdge { + void init(int i0, int i1) { this->i0 = i0; this->i1 = i1; firstTet = 0; numTets = 0; onSurface = false; } + int i0, i1; + int firstTet, numTets; + bool onSurface; + }; + nvidia::Array<TetEdge> mTetEdges; + nvidia::Array<int> mTetEdgeNrs; + nvidia::Array<int> mEdgeTetNrs; + nvidia::Array<float> mEdgeTetAngles; + + nvidia::Array<int> mAddedTets; + nvidia::Array<int> mTestEdges; + + // input + nvidia::Array<PxVec3> mVertices; + nvidia::Array<int> mIndices; + + // output + CompoundGeometry mGeom; +}; + +}}} + +#endif +#endif diff --git a/APEX_1.4/module/destructible/fracture/Core/CompoundGeometryBase.cpp b/APEX_1.4/module/destructible/fracture/Core/CompoundGeometryBase.cpp new file mode 100644 index 00000000..014a37bb --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/CompoundGeometryBase.cpp @@ -0,0 +1,95 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "CompoundGeometryBase.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +// ------------------------------------------------------------------------------- +void CompoundGeometry::clear() +{ + convexes.clear(); + vertices.clear();; + normals.clear(); + indices.clear(); + neighbors.clear(); + planes.clear(); +} + +// ------------------------------------------------------------------------------- +bool CompoundGeometry::loadFromFile(const char * /*filename*/) +{ + return true; +} + +// ------------------------------------------------------------------------------- +bool CompoundGeometry::saveFromFile(const char * /*filename*/) +{ + return true; +} + +// ------------------------------------------------------------------------------- +void CompoundGeometry::initConvex(Convex &c) +{ + c.firstVert = (int32_t)vertices.size(); + c.numVerts = 0; + c.firstNormal = (int32_t)normals.size(); + c.firstIndex = (int32_t)indices.size(); + c.numFaces = 0; + c.firstPlane = 0; + c.firstNeighbor = (int32_t)neighbors.size(); + c.numNeighbors = 0; +} + +// ------------------------------------------------------------------------------- +void CompoundGeometry::derivePlanes() +{ + planes.clear(); + PxPlane p; + + for (uint32_t i = 0; i < convexes.size(); i++) { + Convex &c = convexes[i]; + c.firstPlane = (int32_t)planes.size(); + int *ids = &indices[(uint32_t)c.firstIndex]; + PxVec3 *verts = &vertices[(uint32_t)c.firstVert]; + for (int j = 0; j < c.numFaces; j++) { + int num = *ids++; + ids++; //int flags = *ids++; + if (num < 3) + p = PxPlane(1.0f, 0.0f, 0.0f, 0.0f); + else { + p.n = PxVec3(0.0f, 0.0f, 0.0f); + for (int k = 1; k < num-1; k++) { + const PxVec3 &p0 = verts[ids[0]]; + const PxVec3 &p1 = verts[ids[k]]; + const PxVec3 &p2 = verts[ids[k+1]]; + p.n += (p1-p0).cross(p2-p1); + } + p.n.normalize(); + p.d = p.n.dot(verts[ids[0]]); + } + planes.pushBack(p); + ids += num; + } + } +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/CompoundGeometryBase.h b/APEX_1.4/module/destructible/fracture/Core/CompoundGeometryBase.h new file mode 100644 index 00000000..30452676 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/CompoundGeometryBase.h @@ -0,0 +1,77 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef COMPOUND_GEOMETRY_BASE +#define COMPOUND_GEOMETRY_BASE + +#include <PxVec3.h> +#include <PxPlane.h> +#include <PsArray.h> +#include <PsUserAllocated.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +// ----------------------------------------------------------------------------------- +class CompoundGeometry : public UserAllocated +{ +public: + CompoundGeometry() {} + virtual ~CompoundGeometry() {} + bool loadFromFile(const char *filename); + bool saveFromFile(const char *filename); + void clear(); + void derivePlanes(); + + virtual void debugDraw(int /*maxConvexes*/ = 0) const {} + + struct Convex { // init using CompoundGeometry::initConvex() + int firstVert; + int numVerts; + int firstNormal; // one per face index! If not provided (see face flags) face normal is used + int firstIndex; + int numFaces; + int firstPlane; + int firstNeighbor; + int numNeighbors; + }; + + void initConvex(Convex &c); + + nvidia::Array<Convex> convexes; + nvidia::Array<PxVec3> vertices; + nvidia::Array<PxVec3> normals; // one per face and vertex! + // face size, face flags, id, id, .., face size, face flags, id .. + nvidia::Array<int> indices; + nvidia::Array<int> neighbors; + + nvidia::Array<PxPlane> planes; // derived for faster cuts + + enum FaceFlags { + FF_OBJECT_SURFACE = 1, + FF_HAS_NORMALS = 2, + FF_INVISIBLE = 4, + FF_NEW = 8, + }; +}; + +} +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/ConvexBase.cpp b/APEX_1.4/module/destructible/fracture/Core/ConvexBase.cpp new file mode 100644 index 00000000..35906cc7 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/ConvexBase.cpp @@ -0,0 +1,1371 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "PxPhysics.h" +#include "PxCooking.h" +#include "PxDefaultStreams.h" +#include "PxShape.h" +#include "PxMath.h" +#include "PxRigidDynamic.h" +#include "PxConvexMesh.h" +#include "PxMat44.h" +#include "PsMathUtils.h" +#include "PxVec2.h" + +#include "CompoundGeometryBase.h" +#include "SimSceneBase.h" +#include "PolygonTriangulatorBase.h" +#include "MeshClipperBase.h" + +#include "ConvexBase.h" + +#define COOK_TRIANGLES 0 + +#include <algorithm> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace physx; + +// -------------------------------------------------------------------------------------------- +Convex::Convex(SimScene* scene) +{ + mScene = scene; + mPxConvexMesh = NULL; + mPxActor = NULL; + mLocalPose = PxTransform(PxIdentity); + mParent = NULL; + mNewConvex = NULL; + mRefCounter = 0; + mIsFarConvex = false; + clear(); +} + +// -------------------------------------------------------------------------------------------- +Convex::~Convex() +{ + clear(); + if (mNewConvex != NULL) + PX_DELETE(mNewConvex); +} + +// -------------------------------------------------------------------------------------------- +void Convex::clear() +{ + mFaces.clear(); + mIndices.clear(); + mVertices.clear(); + mNormals.clear(); + mPlanes.clear(); + + mVisVertices.clear(); + mVisNormals.clear(); + mVisTangents.clear(); + mVisTexCoords.clear(); + mVisTriIndices.clear(); + + mHasExplicitVisMesh = false; + mIsGhostConvex = false; + mVisPolyStarts.clear(); + mVisPolyIndices.clear(); + mVisPolyNeighbors.clear(); + + if (mPxConvexMesh != NULL) + mPxConvexMesh->release(); + + mPxConvexMesh = NULL; + mPxActor = NULL; + mLocalPose = PxTransform(PxIdentity); + + mBounds.setEmpty(); + mMaterialOffset = PxVec3(0.0f, 0.0f, 0.0f); + mTexScale = 1.0f; + + mUse2dTexture = false; + mIndestructible = false; + mMaterialId = 0; + mSurfaceMaterialId = 0; + mModelIslandNr = 0; + + mVolume = 0.0f; + mVolumeDirty = true; +} + +// -------------------------------------------------------------------------------------------- +void Convex::createFromConvex(const Convex *convex, const PxTransform *trans) +{ + clear(); + mVertices = convex->mVertices; + mFaces = convex->mFaces; + clearFraceFlags(CompoundGeometry::FF_NEW); + + mIndices = convex->mIndices; + mNormals = convex->mNormals; + mMaterialOffset = convex->mMaterialOffset; + mTexScale = convex->mTexScale; + mIsGhostConvex = convex->mIsGhostConvex; + mLocalPose = convex->mLocalPose; + + if (trans != NULL) { + for (uint32_t i = 0; i < mVertices.size(); i++) + mVertices[i] = trans->transform(mVertices[i]); + for (uint32_t i = 0; i < mNormals.size(); i++) + mNormals[i] = trans->rotate(mNormals[i]); + mMaterialOffset -= trans->p; + } + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void Convex::transform(const PxMat44 &trans) +{ + for (uint32_t i = 0; i < mVertices.size(); i++) + mVertices[i] = trans.transform(mVertices[i]); + for (uint32_t i = 0; i < mNormals.size(); i++) + mNormals[i] = trans.rotate(mNormals[i]); + mMaterialOffset -= trans.getPosition(); + + if (mHasExplicitVisMesh) { + for (uint32_t i = 0; i < mVisVertices.size(); i++) + mVisVertices[i] = trans.transform(mVisVertices[i]); + for (uint32_t i = 0; i < mVisNormals.size(); i++) + mVisNormals[i] = trans.rotate(mVisNormals[i]); + } + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void Convex::createFromGeometry(const CompoundGeometry &geom, int convexNr, const PxMat44 *trans) +{ + clear(); + const CompoundGeometry::Convex &c = geom.convexes[(uint32_t)convexNr]; + + PxMat44 t = PxMat44(PxIdentity); + + if (trans) + t = *trans; + + mVertices.resize((uint32_t)c.numVerts); + for (int i = 0; i < c.numVerts; i++) + mVertices[(uint32_t)i] = t.transform(geom.vertices[uint32_t(c.firstVert + i)]); + + mFaces.resize((uint32_t)c.numFaces); + int num = 0; + const int *id = &geom.indices[(uint32_t)c.firstIndex]; + const PxVec3 *normals = (geom.normals.size() > 0) ? &geom.normals[(uint32_t)c.firstNormal] : NULL; + + for (uint32_t i = 0; i < (uint32_t)c.numFaces; i++) { + Face &f = mFaces[i]; + f.init(); + f.firstIndex = num; + f.numIndices = *id++; + f.flags = *id++; + for (int j = 0; j < f.numIndices; j++) + mIndices.pushBack(*id++); + if (f.flags & CompoundGeometry::FF_HAS_NORMALS) { + f.firstNormal = (int32_t)mNormals.size(); + for (int j = 0; j < f.numIndices; j++) { + mNormals.pushBack(t.rotate(*normals)); + normals++; + } + } + num += f.numIndices; + } + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void Convex::setPxActor(PxRigidActor *actor) +{ + mPxActor = actor; +} + +// -------------------------------------------------------------------------------------------- +void Convex::setLocalPose(const PxTransform &pose) +{ + mLocalPose = pose; +} + +// -------------------------------------------------------------------------------------------- +PxVec3 Convex::getCenter() const +{ + PxVec3 center(0.0f, 0.0f, 0.0f); + + if (mVertices.empty()) + return center; + + uint32_t numVerts = mVertices.size(); + for (uint32_t i = 0; i < numVerts; i++) + center += mVertices[i]; + center /= (float)numVerts; + + return center; +} + +// -------------------------------------------------------------------------------------------- +PxVec3 Convex::centerAtZero() +{ + PxVec3 center = getCenter(); + for (uint32_t i = 0; i < mVertices.size(); i++) + mVertices[i] -= center; + finalize(); + return center; +} + +// -------------------------------------------------------------------------------------------- +PxTransform Convex::getGlobalPose() const +{ + if (mPxActor == NULL) + return mLocalPose; + else + return mPxActor->getGlobalPose() * mLocalPose; +} + +// -------------------------------------------------------------------------------------------- +PxTransform Convex::getLocalPose() const +{ + return mLocalPose; +} + +// -------------------------------------------------------------------------------------------- +bool Convex::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const +{ + PxVec3 o,d; + PxTransform pose = getGlobalPose(); + d = pose.rotateInv(dir); + o = pose.transformInv(orig); + + if (mHasExplicitVisMesh) + return rayCastVisMesh(o,d, dist, normal); + else + return rayCastConvex(o,d, dist, normal); +} + +// -------------------------------------------------------------------------------------------- +bool Convex::rayCastConvex(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const +{ + float maxEntry = -PX_MAX_F32; + float minExit = PX_MAX_F32; + normal = PxVec3(0.0f, 1.0f, 0.0f); + + for (uint32_t i = 0; i < mPlanes.size(); i++) { + const PxPlane &plane = mPlanes[i]; + float dot = plane.n.dot(dir); + if (dot == 0.0f) + continue; + + float t = (plane.d - orig.dot(plane.n)) / dot; + if (dot < 0.0f) { + if (t > maxEntry) { + maxEntry = t; + normal = plane.n; + } + } + else { + minExit = PxMin(minExit, t); + } + } + + if (maxEntry > minExit) { + dist = PX_MAX_F32; + return false; + } + + dist = maxEntry; + normal.normalize(); + return dist >= 0.0f; +} + +// -------------------------------------------------------------------------------------------- +bool Convex::rayCastVisMesh(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const +{ + normal = PxVec3(0.0f, 1.0f, 0.0f); + dist = PX_MAX_F32; + int minTri = -1; + + for (uint32_t i = 0; i < mVisTriIndices.size(); i += 3) { + const PxVec3 &p0 = mVisVertices[(uint32_t)mVisTriIndices[i]]; + const PxVec3 &p1 = mVisVertices[(uint32_t)mVisTriIndices[i+1]]; + const PxVec3 &p2 = mVisVertices[(uint32_t)mVisTriIndices[i+2]]; + PxVec3 n = (p1-p0).cross(p2-p0); + float t = dir.dot(n); + if (t >= 0.0f) + continue; + t = n.dot(p0 - orig) / t; + if (t < 0.0f) + continue; + + // hit inside triangle? + PxVec3 hit = orig + t * dir; + float b2 = (p1-p0).cross(hit-p0).dot(n); + float b0 = (p2-p1).cross(hit-p1).dot(n); + float b1 = (p0-p2).cross(hit-p2).dot(n); + if (b0 < 0.0f || b1 < 0.0f || b2 < 0.0f) + continue; + + float d = (orig - hit).magnitude(); + + if (d < dist) { + dist = d; + minTri = (int32_t)i / 3; + normal = n; + } + } + normal.normalize(); + return minTri >= 0; +} + +// -------------------------------------------------------------------------------------------- +bool Convex::collide(const PxVec3 &pos, float r, float &penetration, PxVec3 &surfaceNormal, PxVec3 &surfaceVel) const +{ + PxVec3 p = getGlobalPose().transformInv(pos); + + float minDist = PX_MAX_F32; + int minPlane = -1; + + for (uint32_t i = 0; i < mPlanes.size(); i++) { + const PxPlane &plane = mPlanes[i]; + float dist = plane.d - p.dot(plane.n) + r; + if (dist < 0.0f) + return false; + if (dist < minDist) { + minDist = dist; + minPlane = (int32_t)i; + } + } + + if (minPlane < 0) + return false; + else { + PxPlane plane = mPlanes[(uint32_t)minPlane]; + surfaceNormal = plane.n; + penetration = minDist; + surfaceVel = PxVec3(0.0f, 0.0f, 0.0f); + + if (mPxActor != NULL) { + PxRigidDynamic *actor = mPxActor->is<physx::PxRigidDynamic>(); + if (actor != NULL) { + surfaceNormal = getGlobalPose().rotate(surfaceNormal); + surfaceVel = actor->getLinearVelocity() + actor->getAngularVelocity().cross(surfaceNormal * plane.d); + } + } + return true; + } +} + +// -------------------------------------------------------------------------------------------- +void Convex::finalize() +{ + updateBounds(); + updatePlanes(); +} + +// -------------------------------------------------------------------------------------------- +void Convex::updateBounds() +{ + mBounds.setEmpty(); + for (uint32_t i = 0; i < mVertices.size(); i++) + mBounds.include(mVertices[i]); +} + +// -------------------------------------------------------------------------------------------- +void Convex::updatePlanes() +{ + uint32_t numFaces = mFaces.size(); + mPlanes.resize(numFaces); + + for (uint32_t i = 0; i < numFaces; i++) { + Face &f = mFaces[i]; + if (f.numIndices < 3) { // should not happen + mPlanes[i].n = PxVec3(0.0f, 1.0f, 0.0f); + mPlanes[i].d = 0.0f; + continue; + } + PxVec3 n(0.0f, 0.0f, 0.0f); + PxVec3 &p0 = mVertices[(uint32_t)mIndices[(uint32_t)f.firstIndex]]; + for (int j = 1; j < f.numIndices-1; j++) { + PxVec3 &p1 = mVertices[(uint32_t)mIndices[uint32_t(f.firstIndex+j)]]; + PxVec3 &p2 = mVertices[(uint32_t)mIndices[uint32_t(f.firstIndex+j+1)]]; + n += (p1-p0).cross(p2-p0); + } + n.normalize(); + mPlanes[i].n = n; + mPlanes[i].d = mPlanes[i].n.dot(p0); + } +} + +// -------------------------------------------------------------------------------------------- +void Convex::getWorldBounds(PxBounds3 &bounds) const +{ + bounds = PxBounds3::transformSafe(getGlobalPose(), mBounds); +} + +// -------------------------------------------------------------------------------------------- +void Convex::getLocalBounds(PxBounds3 &bounds) const +{ + bounds = mBounds; +} + +// -------------------------------------------------------------------------------------------- +void Convex::intersectWithConvex(const PxPlane *planes, int numPlanes, const PxMat44 &trans, bool &empty) +{ + empty = false; + + PxMat33 M(trans.getBasis(0), trans.getBasis(1), trans.getBasis(2)); + PxMat33 M1 = M.getInverse(); + PxMat33 M1T = M1.getTranspose(); + + for (int i = 0; i < numPlanes; i++) { + PxPlane p; + p.n = M1T.transform(planes[i].n); + p.d = planes[i].d + trans.getPosition().dot(p.n); + float len = p.n.normalize(); + p.d /= len; + cut(p.n, p.d, empty); + if (empty) + return; + } +} + +// -------------------------------------------------------------------------------------------- +bool Convex::cut(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty, bool setNewFaceFlag) +{ + float eps = 1e-4f; + + //bool pos = false; + //bool neg = false; + + PxVec3 pn = localPlaneN; + float pd = localPlaneD; + + // does the plane pass through the convex? + float minD = PX_MAX_F32; + float maxD = -PX_MAX_F32; + + for (uint32_t i = 0; i < mVertices.size(); i++) { + float dot = mVertices[i].dot(pn); + if (dot < minD) minD = dot; + if (dot > maxD) maxD = dot; + } + + cutEmpty = minD > pd - eps; + if (cutEmpty || maxD < pd + eps) + return false; + + // new: avoid singular cases + for (uint32_t i = 0; i < mVertices.size(); i++) { + float dot = mVertices[i].dot(pn); + if (fabs(dot - pd) < 1e-5f) + pd += 1e-5f; + } + + // member so the memory does not have to be re-allocated for every cut + if (mNewConvex == NULL) + mNewConvex = mScene->createConvex(); + mNewConvex->clear(); + + // create vertices + uint32_t numFaces = mFaces.size(); + nvidia::Array<int> newNr(mVertices.size(), -1); + + struct Cut { + void set(int i0, int i1, int newId) { + this->i0 = i0; this->i1 = i1; this->newId = newId; next = -1; + } + bool is(int i0, int i1) { + return (this->i0 == i0 && this->i1 == i1) || (this->i0 == i1 && this->i1 == i0); + } + int i0, i1; + int newId; + int next; + }; + nvidia::Array<Cut> cuts; + + for (uint32_t i = 0; i < numFaces; i++) { + Face &f = mFaces[i]; + int *ids = &mIndices[(uint32_t)f.firstIndex]; + mNewConvex->mFaces.resize(mNewConvex->mFaces.size() + 1); + Face &newFace = mNewConvex->mFaces[mNewConvex->mFaces.size()-1]; + newFace.init(); + newFace.flags = f.flags; + newFace.firstIndex = (int32_t)mNewConvex->mIndices.size(); + bool hasNormals = (f.flags & CompoundGeometry::FF_HAS_NORMALS) != 0; + if (hasNormals) + newFace.firstNormal = (int32_t)mNewConvex->mNormals.size(); + + int cutNrs[2]; + uint32_t numCuts = 0; + bool winding = false; + + for (int j = 0; j < f.numIndices; j++) { + int j1 = (j+1)%f.numIndices; + int i0 = ids[j]; + int i1 = ids[j1]; + PxVec3 &p0 = mVertices[(uint32_t)i0]; + PxVec3 &p1 = mVertices[(uint32_t)i1]; + PxVec3 n0,n1; + if (hasNormals) { + n0 = mNormals[uint32_t(f.firstNormal+j)]; + n1 = mNormals[uint32_t(f.firstNormal+j1)]; + } + bool sign0 = p0.dot(pn) >= pd; + bool sign1 = p1.dot(pn) >= pd; + if (!sign0) { + if (newNr[(uint32_t)i0] < 0) { + newNr[(uint32_t)i0] = (int32_t)mNewConvex->mVertices.size(); + mNewConvex->mVertices.pushBack(p0); + } + mNewConvex->mIndices.pushBack(newNr[(uint32_t)i0]); + if (hasNormals) + mNewConvex->mNormals.pushBack(n0); + if (numCuts == 1) + winding = true; + } + + // cut? + if (sign0 != sign1) { + // do we have the cut vertex already? + uint32_t totalCuts = cuts.size(); + uint32_t k = 0; + while (k < totalCuts && !cuts[k].is(i0,i1)) + k++; + + float t = (pd - p0.dot(pn)) / (p1 - p0).dot(pn); + // create new cut vertex + if (k == totalCuts) { + cuts.resize(totalCuts+1); + cuts[totalCuts].set(i0, i1, (int32_t)mNewConvex->mVertices.size()); + PxVec3 p = p0 + (p1-p0) * t; + mNewConvex->mVertices.pushBack(p); + } + mNewConvex->mIndices.pushBack(cuts[k].newId); + if (hasNormals) { + PxVec3 n = n0 + (n1-n0) * t; + n.normalize(); + mNewConvex->mNormals.pushBack(n); + } + if (numCuts >= 2) { // numerical problems! + cutEmpty = true; + return false; + } + cutNrs[numCuts] = (int32_t)k; + numCuts++; + } + } + + if (numCuts == 1) { // numerical problems! + cutEmpty = true; + return false; + } + + if (numCuts == 2) { + Cut &cut0 = cuts[(uint32_t)cutNrs[0]]; + Cut &cut1 = cuts[(uint32_t)cutNrs[1]]; + if (winding) { + cut0.next = cutNrs[1]; + } + else { + cut1.next = cutNrs[0]; + } + } + + // check whether the new convex got a new face + + newFace.numIndices = (int32_t)mNewConvex->mIndices.size() - newFace.firstIndex; + if (newFace.numIndices == 0) + mNewConvex->mFaces.popBack(); + else if (newFace.numIndices < 3) { + cutEmpty = true; + return false; + } + } + + // create closing face + Face closingFace; + closingFace.init(); + closingFace.firstIndex = (int32_t)mNewConvex->mIndices.size(); + + int nr = 0; + for (uint32_t i = 0; i < cuts.size(); i++) { + mNewConvex->mIndices.pushBack(cuts[(uint32_t)nr].newId); + closingFace.numIndices++; + nr = cuts[(uint32_t)nr].next; + + if (nr < 0) { // numerical problems + cutEmpty = true; + return false; + } + } + if (closingFace.numIndices < 3) { + cutEmpty = true; + return false; + } + if (setNewFaceFlag) + closingFace.flags |= CompoundGeometry::FF_NEW; + + mNewConvex->mFaces.pushBack(closingFace); + + mVertices = mNewConvex->mVertices; + mIndices = mNewConvex->mIndices; + mFaces = mNewConvex->mFaces; + mNormals = mNewConvex->mNormals; + mVolumeDirty = true; + finalize(); + + return true; +} + +// -------------------------------------------------------------------------------------------- +PxConvexMesh* Convex::createPxConvexMesh(Compound *parent, PxPhysics *pxPhysics, PxCooking *pxCooking) +{ + mParent = parent; + + if (mVertices.empty()) + return NULL; + + if (mPxConvexMesh != NULL) + return mPxConvexMesh; + + mPxConvexMesh = NULL; + mPxActor = NULL; + +#if COOK_TRIANGLES + // create tri mesh + // in this tri mesh vertices are shared in contrast to the tri mesh for rendering + nvidia::Array<uint32_t> indices; + for (int i = 0; i < (int)mFaces.size(); i++) { + Face &f = mFaces[i]; + if (f.numIndices < 3) + continue; + int *ids = &mIndices[f.firstIndex]; + for (int j = 1; j < f.numIndices-1; j++) { + indices.pushBack(ids[0]); + indices.pushBack(ids[j]); + indices.pushBack(ids[j+1]); + } + } + + physx::PxConvexMeshDesc meshDesc; + meshDesc.setToDefault(); + meshDesc.points.count = mVertices.size(); + meshDesc.points.stride = sizeof(PxVec3); + meshDesc.points.data = &mVertices[0]; + meshDesc.triangles.count = indices.size() / 3; + meshDesc.triangles.stride = 3*sizeof(uint32_t); + meshDesc.triangles.data = &indices[0]; +#else + nvidia::Array<physx::PxHullPolygon> polygons; + polygons.reserve(mFaces.size()); + if (mPlanes.size() != mFaces.size()) + updatePlanes(); + + for (uint32_t i = 0; i < mFaces.size(); i++) { + Face &f = mFaces[i]; + if (f.numIndices < 3) + continue; + physx::PxHullPolygon p; + p.mIndexBase = (uint16_t)f.firstIndex; + p.mNbVerts = (uint16_t)f.numIndices; + p.mPlane[0] = mPlanes[i].n.x; + p.mPlane[1] = mPlanes[i].n.y; + p.mPlane[2] = mPlanes[i].n.z; + p.mPlane[3] = -mPlanes[i].d; + polygons.pushBack(p); + } + + physx::PxConvexMeshDesc meshDesc; + meshDesc.setToDefault(); + meshDesc.points.count = mVertices.size(); + meshDesc.points.stride = sizeof(PxVec3); + meshDesc.points.data = &mVertices[0]; + meshDesc.indices.count = mIndices.size(); + meshDesc.indices.data = &mIndices[0]; + meshDesc.indices.stride = sizeof(uint32_t); + meshDesc.polygons.count = mFaces.size(); + meshDesc.polygons.data = &polygons[0]; + meshDesc.polygons.stride = sizeof(physx::PxHullPolygon); + +#endif + + // Cooking from memory + PxDefaultMemoryOutputStream outBuffer; + if (!pxCooking->cookConvexMesh(meshDesc, outBuffer)) + return NULL; + + PxDefaultMemoryInputData inBuffer(outBuffer.getData(), outBuffer.getSize()); + mPxConvexMesh = pxPhysics->createConvexMesh(inBuffer); + + return mPxConvexMesh; +} + +// -------------------------------------------------------------------------------------------- +void Convex::setMaterialOffset(const PxVec3 &offset) +{ + if (mHasExplicitVisMesh) { + for (uint32_t i = 0; i < mVisVertices.size(); i++) + mVisVertices[i] += mMaterialOffset - offset; + } + mMaterialOffset = offset; +} + +// -------------------------------------------------------------------------------------------- +void Convex::createVisMeshFromConvex() +{ + // vertices are duplicated for each face to get sharp edges with multiple normals + mHasExplicitVisMesh = false; + mVisVertices.clear(); + mVisNormals.clear(); + mVisTangents.clear(); + mVisTriIndices.clear(); + mVisTexCoords.clear(); + PxVec3 n; + PxVec3 t0, t1; + + for (uint32_t i = 0; i < mFaces.size(); i++) { + Face &f = mFaces[i]; + if (f.flags & CompoundGeometry::FF_INVISIBLE) + continue; + if (f.numIndices < 3) + continue; + // normal + int *ids = &mIndices[(uint32_t)f.firstIndex]; + if (!(f.flags & CompoundGeometry::FF_HAS_NORMALS)) { + n = (mVertices[(uint32_t)ids[1]] - mVertices[(uint32_t)ids[0]]).cross(mVertices[(uint32_t)ids[2]] - mVertices[(uint32_t)ids[0]]); + n.normalize(); + } + // tangents + if (fabs(n.x) < fabs(n.y) && fabs(n.x) < fabs(n.z)) + t0 = PxVec3(1.0f, 0.0f, 0.0f); + else if (fabs(n.y) < fabs(n.z)) + t0 = PxVec3(0.0f, 1.0f, 0.0); + else + t0 = PxVec3(0.0f, 0.0f, 1.0f); + t1 = n.cross(t0); + t1.normalize(); + t0 = t1.cross(n); + + int firstVertNr = (int32_t)mVisVertices.size(); + for (int j = 0; j < f.numIndices; j++) { + PxVec3 p = mVertices[(uint32_t)ids[(uint32_t)j]]; + mVisVertices.pushBack(p); + if (f.flags & CompoundGeometry::FF_HAS_NORMALS) { + mVisNormals.pushBack(mNormals[uint32_t(f.firstNormal + j)]); + mVisTangents.pushBack(PxVec3(0.0f, 0.0f, 0.0f)); // on surface, not bump map + } + else { + mVisNormals.pushBack(n); + mVisTangents.pushBack(t0); // internal face, bump map + } + mVisTexCoords.pushBack(p.dot(t0) * mTexScale); + mVisTexCoords.pushBack(p.dot(t1) * mTexScale); + } + for (int j = 1; j < f.numIndices-1; j++) { + mVisTriIndices.pushBack(firstVertNr); + mVisTriIndices.pushBack(firstVertNr+j); + mVisTriIndices.pushBack(firstVertNr+j+1); + } + } +} + +// -------------------------------------------------------------------------------------------- +struct Edge { + // not using indices for edge match but positions + // so duplicated vertices are handled as one vertex + bool smaller(const PxVec3 &v0, const PxVec3 &v1) const { + if (v0.x < v1.x) return true; + if (v0.x > v1.x) return false; + if (v0.y < v1.y) return true; + if (v0.y > v1.y) return false; + return (v0.z < v1.z); + } + void set(const PxVec3 &v0, const PxVec3 &v1, int faceNr, int edgeNr) { + if (smaller(v0,v1)) { this->v0 = v0; this->v1 = v1; } + else { this->v0 = v1; this->v1 = v0; } + this->faceNr = faceNr; this->edgeNr = edgeNr; + } + bool operator < (const Edge &e) const { + if (smaller(v0, e.v0)) return true; + if (v0 == e.v0 && smaller(v1, e.v1)) return true; + return false; + } + bool operator == (const Edge &e) const { return v0 == e.v0 && v1 == e.v1; } + PxVec3 v0,v1; + int faceNr, edgeNr; +}; + +// -------------------------------------------------------------------------------------------- +bool Convex::computeVisMeshNeighbors() +{ + uint32_t numIndices = mVisPolyIndices.size(); + uint32_t numPolygons = mVisPolyStarts.size()-1; + + nvidia::Array<Edge> edges(numIndices); + + for (uint32_t i = 0; i < numPolygons; i++) { + int first = mVisPolyStarts[i]; + int num = mVisPolyStarts[i+1] - first; + for (int j = 0; j < num; j++) { + edges[uint32_t(first + j)].set( + mVisVertices[(uint32_t)mVisPolyIndices[uint32_t(first + j)]], + mVisVertices[(uint32_t)mVisPolyIndices[uint32_t(first + (j+1)%num)]], (int32_t)i, first + j); + } + } + std::sort(edges.begin(), edges.end()); + + mVisPolyNeighbors.resize(numIndices); + bool manifold = true; + uint32_t i = 0; + while (i < edges.size()) { + Edge &e0 = edges[i]; + i++; + if (i < edges.size() && edges[i] == e0) { + Edge &e1 = edges[i]; + mVisPolyNeighbors[(uint32_t)e0.edgeNr] = e1.faceNr; + mVisPolyNeighbors[(uint32_t)e1.edgeNr] = e0.faceNr; + i++; + } + while (i < edges.size() && edges[i] == e0) { + manifold = false; + i++; + } + } + return manifold; +} + +// -------------------------------------------------------------------------------------------- +bool Convex::setExplicitVisMeshFromTriangles(int numVertices, const PxVec3 *vertices, const PxVec3 *normals, const PxVec2 *texcoords, + int numIndices, const uint32_t *indices, PxTransform *trans, const PxVec3* scale) +{ + mHasExplicitVisMesh = true; + + // reduce to vertices referenced by indices + // needed if submesh is provided + nvidia::Array<int> oldToNew((uint32_t)numVertices, -1); + mVisVertices.clear(); + mVisNormals.clear(); + mVisTangents.clear(); + mVisTexCoords.clear(); + + const float scaleMagn = scale ? scale->magnitude() : 1.f; + + for (int i = 0; i < numIndices; i++) { + uint32_t id = (uint32_t)indices[(uint32_t)i]; + if (oldToNew[id] < 0) { + oldToNew[id] = (int32_t)mVisVertices.size(); + + PxVec3 p = vertices[id]; + PxVec3 n = normals[id]; + if (scale != NULL) + { + p.x = scale->x*p.x; + p.y = scale->y*p.y; + p.z = scale->z*p.z; + n.x = scale->x*n.x/scaleMagn; + n.y = scale->y*n.y/scaleMagn; + n.z = scale->z*n.z/scaleMagn; + } + if (trans != NULL) { + p = trans->transform(p); + n = trans->rotate(n); + } + mVisVertices.pushBack(p); + mVisNormals.pushBack(n); + mVisTangents.pushBack(PxVec3(0.0f, 0.0f, 0.0f)); // on surface, no bump map + mVisTexCoords.pushBack(texcoords[id].x); // to do, get as input + mVisTexCoords.pushBack(texcoords[id].y); + } + } + + uint32_t numTris = (uint32_t)numIndices / 3; + mVisPolyStarts.resize(numTris+1); + for (uint32_t i = 0; i < numTris+1; i++) + mVisPolyStarts[i] = 3*(int32_t)i; + + mVisPolyIndices.resize((uint32_t)numIndices); + for (uint32_t i = 0; i < (uint32_t)numIndices; i++) + mVisPolyIndices[i] = oldToNew[(uint32_t)indices[i]]; + + mVisTriIndices.clear(); + + bool manifold = computeVisMeshNeighbors(); + createVisTrisFromPolys(); + computeVisTangentsFromPoly(); + + return manifold; +} + +// -------------------------------------------------------------------------------------------- +bool Convex::setExplicitVisMeshFromPolygons(int numVertices, const PxVec3 *vertices, const PxVec3 *normals, const PxVec3 *tangents, const float *texCoords, + int numPolygons, const int *polyStarts, + int numIndices, const int *indices, PxTransform *trans, const PxVec3* scale) +{ + mHasExplicitVisMesh = true; + + mVisVertices.resize((uint32_t)numVertices); + mVisNormals.resize((uint32_t)numVertices); + mVisTangents.resize((uint32_t)numVertices); + mVisTexCoords.resize(2*(uint32_t)numVertices); + + const float scaleMagn = scale ? scale->magnitude() : 1.f; + + for (uint32_t i = 0; i < (uint32_t)numVertices; i++) { + if (trans != NULL) { + mVisVertices[i] = trans->transform(vertices[i]); + mVisNormals[i] = trans->rotate(normals[i]); + if (tangents != NULL) + mVisTangents[i] = trans->rotate(tangents[i]); + else + mVisTangents[i] = PxVec3(0.0f, 0.0f, 0.0f); + } + else { + mVisVertices[i] = vertices[i]; + mVisNormals[i] = normals[i]; + if (tangents != NULL) + mVisTangents[i] = tangents[i]; + else + mVisTangents[i] = PxVec3(0.0f, 0.0f, 0.0f); + } + if (texCoords != NULL) { + mVisTexCoords[2*i] = texCoords[2*i]; + mVisTexCoords[2*i+1] = texCoords[2*i+1]; + } + if (scale != NULL) + { + mVisVertices[i].x *= scale->x; + mVisVertices[i].y *= scale->y; + mVisVertices[i].z *= scale->z; + mVisNormals[i].x *= scale->x/scaleMagn; + mVisNormals[i].y *= scale->y/scaleMagn; + mVisNormals[i].z *= scale->z/scaleMagn; + } + } + + mVisPolyStarts.resize((uint32_t)numPolygons+1); + for (uint32_t i = 0; i < (uint32_t)numPolygons+1; i++) + mVisPolyStarts[i] = polyStarts[i]; + + mVisPolyIndices.resize((uint32_t)numIndices); + for (uint32_t i = 0; i < (uint32_t)numIndices; i++) + mVisPolyIndices[i] = indices[i]; + + bool manifold = computeVisMeshNeighbors(); + createVisTrisFromPolys(); + computeVisTangentsFromPoly(); + + return manifold; +} + +// -------------------------------------------------------------------------------------------- +void Convex::computeVisTangentsFromPoly() { + // Must be called after createVisTrisFromPolys + //Adapt from Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html + + uint32_t numTris = mVisTriIndices.size() / 3; + int* tris = &mVisTriIndices[0]; + uint32_t numV = mVisVertices.size(); + + for (uint32_t i = 0; i < numTris; i++) + { + uint32_t i0 = (uint32_t)tris[0]; + uint32_t i1 = (uint32_t)tris[1]; + uint32_t i2 = (uint32_t)tris[2]; + + PxVec3& v0 = mVisVertices[i0]; + PxVec3& v1 = mVisVertices[i1]; + PxVec3& v2 = mVisVertices[i2]; + + + float* tex0 = &mVisTexCoords[2*i0]; + float* tex1 = &mVisTexCoords[2*i1]; + float* tex2 = &mVisTexCoords[2*i2]; + + float x0 = v1.x - v0.x; + float x1 = v2.x - v0.x; + float y0 = v1.y - v0.y; + float y1 = v2.y - v0.y; + float z1 = v1.z - v0.z; + float z2 = v2.z - v0.z; + + float s0 = tex1[0] - tex0[0]; + float s1 = tex2[0] - tex0[0]; + float t0 = tex1[1] - tex0[1]; + float t1 = tex2[1] - tex0[1]; + + float idet = 1.0f / (s0*t1 - s1*t0); + PxVec3 t = idet*PxVec3(t1*x0 - t0*x1,t1*y0 - t0*y1,t1*z1 - t0*z2); + //PxVec3 b = idet*PxVec3(s0*x1 - s1*x0,s0*y1 - s1*y0,s0*z2 - s1*z1); + +/* if ( (i0 == 0) || (i1 == 0) || (i2 == 0) ) { + cout<<t[0]<<" "<<t[1]<<" "<<t[2]<<endl; + ok= true; + }*/ + mVisTangents[i0] += t; + mVisTangents[i1] += t; + mVisTangents[i2] += t; + + tris+=3; + } + //cout<<"OK = "<<ok<<endl; + + for (uint32_t i = 0; i < numV; i++) + { + PxVec3& n = mVisNormals[i]; + PxVec3& t = mVisTangents[i]; + + + // Gram-Schmidt orthogonalize + t = (t - n * n.dot(t)); + t.normalize(); + + if (!t.isFinite()) t = PxVec3(0.0f, 0.0f, 0.0f); + + mVisTexCoords[2*i] += 5.0f; + } +} + +// -------------------------------------------------------------------------------------------- +void Convex::createVisTrisFromPolys() +{ + mVisTriIndices.clear(); + for (uint32_t i = 0; i < mVisPolyStarts.size()-1; i++) { + uint32_t first = (uint32_t)mVisPolyStarts[i]; + uint32_t num = (uint32_t)mVisPolyStarts[i+1] - first; + if (num == 3) { + mVisTriIndices.pushBack(mVisPolyIndices[first]); + mVisTriIndices.pushBack(mVisPolyIndices[first+1]); + mVisTriIndices.pushBack(mVisPolyIndices[first+2]); + continue; + } + PolygonTriangulator *pt = mScene->getPolygonTriangulator(); //PolygonTriangulator::getInstance(); + pt->triangulate(&mVisVertices[0], (int32_t)num, &mVisPolyIndices[first]); + const nvidia::Array<int> indices = pt->getIndices(); + + uint32_t numIds = mVisTriIndices.size(); + mVisTriIndices.resize(numIds + indices.size()); + for (uint32_t j = 0; j < indices.size(); j++) + mVisTriIndices[numIds+j] = indices[j]; + } +} + +// -------------------------------------------------------------------------------------------- +void Convex::transformVisualMesh(const PxTransform &trans) +{ + for (uint32_t i = 0; i < mVisVertices.size(); i++) + mVisVertices[i] = trans.transform(mVisVertices[i]); + for (uint32_t i = 0; i < mVisNormals.size(); i++) + mVisNormals[i] = trans.rotate(mVisNormals[i]); + for (uint32_t i = 0; i < mVisTangents.size(); i++) + mVisTangents[i] = trans.rotate(mVisTangents[i]); +} + +// -------------------------------------------------------------------------------------------- +bool Convex::insideVisualMesh(const PxVec3 &pos) const +{ + int num[6] = {0,0,0,0,0,0}; + const uint32_t numAxes = 2; // max 3: the nigher the more robust but slower + + for (uint32_t i = 0; i < mVisTriIndices.size(); i += 3) { + const PxVec3 &p0 = mVisVertices[(uint32_t)mVisTriIndices[i]]; + const PxVec3 &p1 = mVisVertices[(uint32_t)mVisTriIndices[i+1]]; + const PxVec3 &p2 = mVisVertices[(uint32_t)mVisTriIndices[i+2]]; + PxVec3 n = (p1-p0).cross(p2-p0); + float d = n.dot(p0); + float ds = d - pos.dot(n); + + // for all axes, cound the hits of the ray starting from pos with the mesh + for (uint32_t j = 0; j < numAxes; j++) { + if (n[j] == 0.0f) + continue; + + uint32_t j0 = (j+1)%3; + uint32_t j1 = (j+2)%3; + float x0 = p0[j0]; + float y0 = p0[j1]; + float x1 = p1[j0]; + float y1 = p1[j1]; + float x2 = p2[j0]; + float y2 = p2[j1]; + + float px = pos[j0]; + float py = pos[j1]; + + // inside triangle? + float d0 = (x1-x0) * (py-y0) - (y1-y0) * (px-x0); + float d1 = (x2-x1) * (py-y1) - (y2-y1) * (px-x1); + float d2 = (x0-x2) * (py-y2) - (y0-y2) * (px-x2); + bool inside = + (d0 <= 0.0f && d1 <= 0.0f && d2 <= 0.0f) || + (d0 >= 0.0f && d1 >= 0.0f && d2 >= 0.0f); + if (!inside) + continue; + + float s = ds / n[j]; + if (s > 0.0f) + num[2*j] += (n[j] > 0.0f) ? +1 : -1; + else + num[2*j+1] += (n[j] < 0.0f) ? +1 : -1; + } + } + uint32_t numVotes = 0; + for (uint32_t i = 0; i < 6; i++) { + if (num[i] > 0) + numVotes++; + } + return numVotes > numAxes; +} + +// -------------------------------------------------------------------------------------------- +bool Convex::clipVisualMesh(MeshClipper *clipper, const PxTransform &trans, nvidia::Array<Convex*> &newConvexes) +{ + bool empty, completelyInside; + newConvexes.clear(); + + clipper->clip(this, trans, mTexScale, true, empty, completelyInside); + + if (completelyInside) { + mHasExplicitVisMesh = false; + return true; + } + + if (empty) + return false; + + const MeshClipper::Mesh &mesh = clipper->getMesh(0); + + mVisVertices = mesh.vertices; + mVisNormals = mesh.normals; + mVisTangents = mesh.tangents; + mVisTexCoords = mesh.texCoords; + mVisPolyStarts = mesh.polyStarts; + mVisPolyIndices = mesh.polyIndices; + mVisPolyNeighbors = mesh.polyNeighbors; + mHasExplicitVisMesh = true; + + createVisTrisFromPolys(); + + finalize(); + + int numMeshes = clipper->getNumMeshes(); + if (numMeshes > 1) { + newConvexes.resize((uint32_t)numMeshes-1); + for (int i = 1; i < numMeshes; i++) { + const MeshClipper::Mesh &mesh = clipper->getMesh(i); + Convex *c = mScene->createConvex(); + newConvexes[(uint32_t)i-1] = c; + c->createFromConvex(this); + c->mVisVertices = mesh.vertices; + c->mVisNormals = mesh.normals; + c->mVisTangents = mesh.tangents; + c->mVisTexCoords = mesh.texCoords; + c->mVisPolyStarts = mesh.polyStarts; + c->mVisPolyIndices = mesh.polyIndices; + c->mVisPolyNeighbors = mesh.polyNeighbors; + c->mHasExplicitVisMesh = true; + c->createVisTrisFromPolys(); + c->finalize(); + } + } + return true; +} + +// -------------------------------------------------------------------------------------------- +void Convex::fitToVisualMesh(bool &cutEmpty, int numFitDirections) +{ + cutEmpty = false; + if (!mHasExplicitVisMesh) + return; + + static const int numNormals = 3 + 4; + static const float normals[numNormals][3] = { + {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f} + // avoid singular cases + // {1.0f, 1.1f, 1.2f}, {-1.3f, 1.2f, 1.0f}, {1.0f, -1.2f, 1.0f}, {1.2f, 1.3f, -1.0f} + }; + + cutEmpty = false; + const float eps = 1e-3f; + + int num = numFitDirections; + if (num > numNormals) + num = numNormals; + + for (int i = 0; i < num; i++) { + PxVec3 n(normals[i][0], normals[i][1], normals[i][2]); + n.normalize(); + float minVD = PX_MAX_F32; + float maxVD = -PX_MAX_F32; + float minCD = PX_MAX_F32; + float maxCD = -PX_MAX_F32; + for (uint32_t j = 0; j < mVisVertices.size(); j++) { + float d = mVisVertices[j].dot(n); + if (d < minVD) minVD = d; + if (d > maxVD) maxVD = d; + } + for (uint32_t j = 0; j < mVertices.size(); j++) { + float d = mVertices[j].dot(n); + if (d < minCD) minCD = d; + if (d > maxCD) maxCD = d; + } + if (maxVD < maxCD - eps) { + cut(n, maxVD, cutEmpty, false); + if (cutEmpty) + return; + } + if (minVD > minCD + eps) { + cut(-n, -minVD - eps, cutEmpty, false); + if (cutEmpty) + return; + } + } + finalize(); +} + +// -------------------------------------------------------------------------------------------- +float Convex::getVolume() const +{ + if (!mVolumeDirty) + return mVolume; + + mVolume = 0.0f; + for (uint32_t i = 0; i < mFaces.size(); i++) { + const Face &f = mFaces[i]; + if (f.numIndices < 3) + continue; + const int *ids = &mIndices[(uint32_t)f.firstIndex]; + const PxVec3 &p0 = mVertices[(uint32_t)ids[0]]; + for (int j = 1; j < f.numIndices-1; j++) { + const PxVec3 &p1 = mVertices[(uint32_t)ids[(uint32_t)j]]; + const PxVec3 &p2 = mVertices[(uint32_t)ids[(uint32_t)j+1]]; + mVolume += p0.cross(p1).dot(p2); + } + } + mVolume *= (1.0f / 6.0f); + mVolumeDirty = false; + return mVolume; +} + +// -------------------------------------------------------------------------------------------- +void Convex::removeInvisibleFacesFlags() +{ + for (uint32_t i = 0; i < mFaces.size(); i++) + mFaces[i].flags &= ~CompoundGeometry::FF_INVISIBLE; +} + +// -------------------------------------------------------------------------------------------- +void Convex::updateFaceVisibility(const float *faceCoverage) +{ + for (uint32_t i = 0; i < mFaces.size(); i++) { + if (faceCoverage[i] > 0.95f) + mFaces[i].flags |= CompoundGeometry::FF_INVISIBLE; + else + mFaces[i].flags &= ~CompoundGeometry::FF_INVISIBLE; + } +} + +// -------------------------------------------------------------------------------------------- +void Convex::clearFraceFlags(unsigned int flag) +{ + for (uint32_t i = 0; i < mFaces.size(); i++) + mFaces[i].flags &= ~flag; +} + +// -------------------------------------------------------------------------------------------- +bool Convex::insideFattened(const PxVec3 &pos, float r) const +{ + // early out with bounding box + if (pos.x < mBounds.minimum.x - r || pos.x > mBounds.maximum.x + r) + return false; + if (pos.y < mBounds.minimum.y - r || pos.y > mBounds.maximum.y + r) + return false; + if (pos.z < mBounds.minimum.z - r || pos.z > mBounds.maximum.z + r) + return false; + + // planes + for (uint32_t i = 0; i < mPlanes.size(); i++) { + if (mPlanes[i].n.dot(pos) > mPlanes[i].d + r) + return false; + } + return true; +} + +// -------------------------------------------------------------------------------------------- +bool Convex::check() { + PxVec3 center = getCenter(); + + for (uint32_t i = 0; i < mFaces.size(); i++) { + Face &f = mFaces[i]; + if (f.numIndices < 3) + return false; + + PxVec3 &p0 = mVertices[(uint32_t)mIndices[(uint32_t)f.firstIndex]]; + float A = 0.0f; + PxVec3 n(0.0, 0.0, 0.0); + + for (int j = 1; j < f.numIndices-1; j++) { + PxVec3 &p1 = mVertices[(uint32_t)mIndices[uint32_t(f.firstIndex+j)]]; + PxVec3 &p2 = mVertices[(uint32_t)mIndices[uint32_t(f.firstIndex+j+1)]]; + PxVec3 nj = (p1-p0).cross(p2-p0); + A += nj.magnitude(); + n += nj; + } + if (A < 1e-6) + return false; + + float d = n.dot(p0); + if (n.dot(center) > d) + return false; + } + return true; +} + +bool Convex::isOnConvexSurface(const PxVec3 pts) const { + const float EPSILON = 1e-6f; + uint32_t numF = mFaces.size(); + for (uint32_t i = 0; i < numF; i++) { + + const Face& f = mFaces[i]; + int nv = f.numIndices; + + float areaFan = 0.0f; + // Compute face area + for (int j = 1; j < nv-1; j++) { + const PxVec3& p0 = mVertices[(uint32_t)mIndices[uint32_t(f.firstIndex)]]; + const PxVec3& p1 = mVertices[(uint32_t)mIndices[uint32_t(f.firstIndex+j)]]; + const PxVec3& p2 = mVertices[(uint32_t)mIndices[uint32_t(f.firstIndex+(j+1))]]; + areaFan += 0.5f* (((p1-p0).cross(p2-p0))).magnitude(); + } + float areaP = 0.0f; + + for (int j = 0; j < nv; j++) { + + const PxVec3& p1 = mVertices[(uint32_t)mIndices[uint32_t(f.firstIndex+j)]]; + const PxVec3& p2 = mVertices[(uint32_t)mIndices[uint32_t(f.firstIndex+(j+1) % nv)]]; + areaP += 0.5f*(((p1-pts).cross(p2-pts))).magnitude(); + } + if ((areaP - areaFan)/areaFan < EPSILON) { + return true; + } + } + return false; + +} + +} +} +} +#endif diff --git a/APEX_1.4/module/destructible/fracture/Core/ConvexBase.h b/APEX_1.4/module/destructible/fracture/Core/ConvexBase.h new file mode 100644 index 00000000..98b44af2 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/ConvexBase.h @@ -0,0 +1,223 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef CONVEX_BASE +#define CONVEX_BASE + +#include <PxPhysics.h> +#include <PxCooking.h> +#include <PxVec3.h> +#include <PxPlane.h> +#include <PxBounds3.h> +#include <PxTransform.h> +#include <PsArray.h> +#include <PsUserAllocated.h> + + +namespace nvidia +{ + +namespace fracture +{ +namespace base +{ + +class Compound; +class CompoundGeometry; +class MeshClipper; +class SimScene; + +// ---------------------------------------------------------------------------- +class Convex : public UserAllocated +{ + friend class SimScene; +protected: + Convex(SimScene* scene); +public: + virtual ~Convex(); + + void createFromConvex(const Convex *convex, const PxTransform *trans = NULL); + void createFromGeometry(const CompoundGeometry &geom, int convexNr, const PxMat44 *trans = NULL); + //bool createFromXml(XMLParser *p, float scale, bool ignoreVisualMesh = false); + + void transform(const PxMat44 &trans); + PxVec3 centerAtZero(); + PxVec3 getCenter() const; + void setTexScale(float texScale) { mTexScale = texScale; } + void increaseRefCounter() { mRefCounter++; } + int decreaseRefCounter() { mRefCounter--; return mRefCounter; } + + bool rayCast(const PxVec3 &ray, const PxVec3 &dir, float &dist, PxVec3 &normal) const; + bool collide(const PxVec3 &pos, float r, float &penetration, PxVec3 &surfaceNormal, PxVec3 &surfaceVel) const; + + void intersectWithConvex(const PxPlane *planes, int numPlanes, const PxMat44 &trans, bool &empty); + + virtual void draw(bool /*debug*/ = false) {} + + PxConvexMesh* createPxConvexMesh(Compound *parent, PxPhysics *pxPhysics, PxCooking *pxCooking); + void setPxActor(PxRigidActor *actor); + void setLocalPose(const PxTransform &pose); + + // accessors + Compound *getParent() { return mParent; } + const Compound *getParent() const { return mParent; } + const PxConvexMesh *getPxConvexMesh() const { return mPxConvexMesh; } + PxConvexMesh *getPxConvexMesh() { return mPxConvexMesh; } + + const nvidia::Array<PxPlane> &getPlanes() const { return mPlanes; }; + const PxBounds3 &getBounds() const { return mBounds; } + void getWorldBounds(PxBounds3 &bounds) const; + void getLocalBounds(PxBounds3 &bounds) const; + float getVolume() const; + void removeInvisibleFacesFlags(); + void updateFaceVisibility(const float *faceCoverage); + void clearFraceFlags(unsigned int flag); + + struct Face { + void init() { + firstIndex = 0; numIndices = 0; flags = 0; firstNormal = 0; + } + int firstIndex; + int numIndices; + int flags; + int firstNormal; + + + }; + + const nvidia::Array<Face> &getFaces() const { return mFaces; } + const nvidia::Array<int> &getIndices() const { return mIndices; } + const nvidia::Array<PxVec3> &getVertices() const { return mVertices; } + + const nvidia::Array<PxVec3> &getVisVertices() const { return mVisVertices; } + const nvidia::Array<PxVec3> &getVisNormals() const { return mVisNormals; } + const nvidia::Array<PxVec3> &getVisTangents() const { return mVisTangents; } + const nvidia::Array<float> &getVisTexCoords() const { return mVisTexCoords; } + const nvidia::Array<int> &getVisTriIndices() const { return mVisTriIndices; } + + const nvidia::Array<int> &getVisPolyStarts() const { return mVisPolyStarts; } + const nvidia::Array<int> &getVisPolyIndices() const { return mVisPolyIndices; } + const nvidia::Array<int> &getVisPolyNeighbors() const { return mVisPolyNeighbors; } + + PxVec3 getMaterialOffset() const { return mMaterialOffset; } + void setMaterialOffset(const PxVec3 &offset); + PxTransform getGlobalPose() const; + PxTransform getLocalPose() const; + + bool isGhostConvex() const { return mIsGhostConvex; } + + // explicit visual mesh + bool hasExplicitVisMesh() const { return mHasExplicitVisMesh; } + bool setExplicitVisMeshFromTriangles(int numVertices, const PxVec3 *vertices, const PxVec3 *normals, const PxVec2 *texcoords, + int numIndices, const uint32_t *indices, PxTransform *trans = NULL, const PxVec3* scale = NULL); + bool setExplicitVisMeshFromPolygons(int numVertices, const PxVec3 *vertices, const PxVec3 *normals, + const PxVec3 *tangents, const float *texCoords, + int numPolygons, const int *polyStarts, // numPolygons+1 entries + int numIndices, const int *indices, PxTransform *trans = NULL, const PxVec3* scale = NULL); + void createVisTrisFromPolys(); + void createVisMeshFromConvex(); + void transformVisualMesh(const PxTransform &trans); + bool insideVisualMesh(const PxVec3 &pos) const; + + bool clipVisualMesh(MeshClipper *clipper, const PxTransform &trans, nvidia::Array<Convex*> &newConvexes); + void fitToVisualMesh(bool &cutEmpty, int numFitDirections = 3); + + bool isOnConvexSurface(const PxVec3 pts) const; + bool check(); + + PxActor* getActor(); + bool insideFattened(const PxVec3 &pos, float r) const; + + bool use2dTexture() const { return mUse2dTexture; } + bool isIndestructible() const { return mIndestructible; } + int getMaterialId() const { return mMaterialId; } + int getSurfaceMaterialId() const { return mSurfaceMaterialId; } + void setSurfaceMaterialId(int id) { mSurfaceMaterialId = id; } + + void setModelIslandNr(int nr) { mModelIslandNr = nr; } + int getModelIslandNr() const { return mModelIslandNr; } + + void setConvexRendererInfo(int groupNr, int groupPos) const { mConvexRendererGroupNr = groupNr; mConvexRendererGroupPos = groupPos; } + int getConvexRendererGroupNr() const { return mConvexRendererGroupNr; } + int getConvexRendererGroupPos() const { return mConvexRendererGroupPos; } + + void setIsFarConvex(bool v) { mIsFarConvex = v; } + bool getIsFarConvex() { return mIsFarConvex; } + +protected: + void clear(); + void finalize(); + void updateBounds(); + void updatePlanes(); + + bool computeVisMeshNeighbors(); + void computeVisTangentsFromPoly(); + bool cutVisMesh(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty); + bool cut(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty, bool setNewFaceFlag = true); + + bool rayCastConvex(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const; + bool rayCastVisMesh(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const; + + SimScene* mScene; + + nvidia::Array<Face> mFaces; + nvidia::Array<int> mIndices; + nvidia::Array<PxVec3> mVertices; + nvidia::Array<PxVec3> mNormals; + nvidia::Array<PxPlane> mPlanes; + + nvidia::Array<PxVec3> mVisVertices; + nvidia::Array<PxVec3> mVisNormals; + nvidia::Array<PxVec3> mVisTangents; + nvidia::Array<float> mVisTexCoords; + nvidia::Array<int> mVisTriIndices; + + int mRefCounter; + bool mHasExplicitVisMesh; + bool mIsGhostConvex; + nvidia::Array<int> mVisPolyStarts; // for explicit mesh only + nvidia::Array<int> mVisPolyIndices; + nvidia::Array<int> mVisPolyNeighbors; + + Convex *mNewConvex; // temporary buffer for cut operations + + Compound *mParent; + PxRigidActor *mPxActor; + PxTransform mLocalPose; + PxConvexMesh *mPxConvexMesh; + + PxBounds3 mBounds; + mutable float mVolume; + mutable bool mVolumeDirty; + PxVec3 mMaterialOffset; + float mTexScale; + int mModelIslandNr; + + // material + bool mUse2dTexture; + bool mIndestructible; + int mMaterialId; + int mSurfaceMaterialId; + + bool mIsFarConvex; + + mutable int mConvexRendererGroupNr; + mutable int mConvexRendererGroupPos; +}; + +} +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/Delaunay2dBase.cpp b/APEX_1.4/module/destructible/fracture/Core/Delaunay2dBase.cpp new file mode 100644 index 00000000..a4aa0f1e --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/Delaunay2dBase.cpp @@ -0,0 +1,319 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "Delaunay2dBase.h" +#include "PxBounds3.h" +#include <PxMath.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace nvidia; +// ------------------------------------------------------------------------------------- +Delaunay2d::Delaunay2d(SimScene* scene): + mScene(scene) +{ +} + +// ------------------------------------------------------------------------------------- +Delaunay2d::~Delaunay2d() +{ +} + +// ------------------------------------------------------------------------------------- +void Delaunay2d::clear() +{ + mVertices.clear(); + mIndices.clear(); + mTriangles.clear(); + mFirstFarVertex = 0; + + mConvexVerts.clear(); + mConvexes.clear(); + mConvexNeighbors.clear(); +} + +// ------------------------------------------------------------------------------------- +void Delaunay2d::triangulate(const PxVec3 *vertices, int numVerts, int byteStride, bool removeFarVertices) +{ + clear(); + + uint8_t *vp = (uint8_t*)vertices; + mVertices.resize((uint32_t)numVerts); + for (uint32_t i = 0; i < (uint32_t)numVerts; i++) { + mVertices[i] = (*(PxVec3*)vp); + mVertices[i].z = 0.0f; + vp += byteStride; + } + + delaunayTriangulation(); + + for (uint32_t i = 0; i < mTriangles.size(); i++) { + Triangle &t = mTriangles[i]; + if (!removeFarVertices || (t.p0 < mFirstFarVertex && t.p1 < mFirstFarVertex && t.p2 < mFirstFarVertex)) { + mIndices.pushBack(t.p0); + mIndices.pushBack(t.p1); + mIndices.pushBack(t.p2); + } + } + + if (removeFarVertices) + mVertices.resize((uint32_t)mFirstFarVertex); +} + + +// ------------------------------------------------------------------------------------- +void Delaunay2d::delaunayTriangulation() +{ + PxBounds3 bounds; + bounds.setEmpty(); + + for (uint32_t i = 0; i < mVertices.size(); i++) + bounds.include(mVertices[i]); + + bounds.fattenSafe(bounds.getDimensions().magnitude()); + + // start with two triangles + //float scale = 10.0f; + PxVec3 p0(bounds.minimum.x, bounds.minimum.y, 0.0f); + PxVec3 p1(bounds.maximum.x, bounds.minimum.y, 0.0f); + PxVec3 p2(bounds.maximum.x, bounds.maximum.y, 0.0f); + PxVec3 p3(bounds.minimum.x, bounds.maximum.y, 0.0f); + + mFirstFarVertex = (int32_t)mVertices.size(); + mVertices.pushBack(p0); + mVertices.pushBack(p1); + mVertices.pushBack(p2); + mVertices.pushBack(p3); + + mTriangles.clear(); + addTriangle(mFirstFarVertex, mFirstFarVertex+1, mFirstFarVertex+2); + addTriangle(mFirstFarVertex, mFirstFarVertex+2, mFirstFarVertex+3); + + // insert other points + for (uint32_t i = 0; i < (uint32_t)mFirstFarVertex; i++) { + mEdges.clear(); + uint32_t j = 0; + while (j < mTriangles.size()) { + Triangle &t = mTriangles[j]; + if ((t.center - mVertices[i]).magnitudeSquared() > t.circumRadiusSquared) { + j++; + continue; + } + Edge e0(t.p0, t.p1); + Edge e1(t.p1, t.p2); + Edge e2(t.p2, t.p0); + bool found0 = false; + bool found1 = false; + bool found2 = false; + + uint32_t k = 0; + while (k < mEdges.size()) { + Edge &e = mEdges[k]; + bool found = false; + if (e == e0) { found0 = true; found = true; } + if (e == e1) { found1 = true; found = true; } + if (e == e2) { found2 = true; found = true; } + if (found) { + mEdges[k] = mEdges[mEdges.size()-1]; + mEdges.popBack(); + } + else k++; + } + if (!found0) mEdges.pushBack(e0); + if (!found1) mEdges.pushBack(e1); + if (!found2) mEdges.pushBack(e2); + mTriangles[j] = mTriangles[mTriangles.size()-1]; + mTriangles.popBack(); + } + for (j = 0; j < mEdges.size(); j++) { + Edge &e = mEdges[j]; + addTriangle(e.p0, e.p1, (int32_t)i); + } + } +} + +// ------------------------------------------------------------------------------------- +void Delaunay2d::addTriangle(int p0, int p1, int p2) +{ + Triangle triangle; + triangle.p0 = p0; + triangle.p1 = p1; + triangle.p2 = p2; + getCircumSphere(mVertices[(uint32_t)p0], mVertices[(uint32_t)p1], mVertices[(uint32_t)p2], triangle.center, triangle.circumRadiusSquared); + mTriangles.pushBack(triangle); +} + +// ------------------------------------------------------------------------------------- +void Delaunay2d::getCircumSphere(const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2, + PxVec3 ¢er, float &radiusSquared) +{ + float x1 = p1.x - p0.x; + float y1 = p1.y - p0.y; + float x2 = p2.x - p0.x; + float y2 = p2.y - p0.y; + + float det = x1 * y2 - x2 * y1; + if (det == 0.0f) { + center = p0; radiusSquared = 0.0f; + return; + } + det = 0.5f / det; + float len1 = x1*x1 + y1*y1; + float len2 = x2*x2 + y2*y2; + float cx = (len1 * y2 - len2 * y1) * det; + float cy = (len2 * x1 - len1 * x2) * det; + center.x = p0.x + cx; + center.y = p0.y + cy; + center.z = 0.0f; + radiusSquared = cx * cx + cy * cy; +} + +// ------------------------------------------------------------------------------------- +void Delaunay2d::computeVoronoiMesh() +{ + mConvexes.clear(); + mConvexVerts.clear(); + mConvexNeighbors.clear(); + + uint32_t numVerts = mVertices.size(); + uint32_t numTris = mIndices.size() / 3; + + // center positions + nvidia::Array<PxVec3> centers(numTris); + for (uint32_t i = 0; i < numTris; i++) { + PxVec3 &p0 = mVertices[(uint32_t)mIndices[3*i]]; + PxVec3 &p1 = mVertices[(uint32_t)mIndices[3*i+1]]; + PxVec3 &p2 = mVertices[(uint32_t)mIndices[3*i+2]]; + float r2; + getCircumSphere(p0,p1,p2, centers[i], r2); + } + + // vertex -> triangles links + nvidia::Array<int> firstVertTri(numVerts+1, 0); + nvidia::Array<int> vertTris; + + for (uint32_t i = 0; i < numTris; i++) { + firstVertTri[(uint32_t)mIndices[3*i]]++; + firstVertTri[(uint32_t)mIndices[3*i+1]]++; + firstVertTri[(uint32_t)mIndices[3*i+2]]++; + } + + int numLinks = 0; + for (uint32_t i = 0; i < numVerts; i++) { + numLinks += firstVertTri[i]; + firstVertTri[i] = numLinks; + } + firstVertTri[numVerts] = numLinks; + vertTris.resize((uint32_t)numLinks); + + for (uint32_t i = 0; i < numTris; i++) { + uint32_t &i0 = (uint32_t&)firstVertTri[(uint32_t)mIndices[3*i]]; + uint32_t &i1 = (uint32_t&)firstVertTri[(uint32_t)mIndices[3*i+1]]; + uint32_t &i2 = (uint32_t&)firstVertTri[(uint32_t)mIndices[3*i+2]]; + i0--; vertTris[i0] = (int32_t)i; + i1--; vertTris[i1] = (int32_t)i; + i2--; vertTris[i2] = (int32_t)i; + } + + // convexes + Convex c; + nvidia::Array<int> nextVert(numVerts, -1); + nvidia::Array<int> vertVisited(numVerts, -1); + nvidia::Array<int> triOfVert(numVerts, -1); + nvidia::Array<int> convexOfVert(numVerts, -1); + + for (uint32_t i = 0; i < numVerts; i++) { + int first = firstVertTri[i]; + int last = firstVertTri[i+1]; + int num = last - first; + if (num < 3) + continue; + + int start = -1; + + for (int j = first; j < last; j++) { + int triNr = vertTris[(uint32_t)j]; + + int k = 0; + while (k < 3 && mIndices[uint32_t(3*triNr+k)] != (int32_t)i) + k++; + + int j0 = mIndices[uint32_t(3*triNr + (k+1)%3)]; + int j1 = mIndices[uint32_t(3*triNr + (k+2)%3)]; + + if (j == first) + start = j0; + + nextVert[(uint32_t)j0] = j1; + vertVisited[(uint32_t)j0] = 2*(int32_t)i; + triOfVert[(uint32_t)j0] = triNr; + } + + c.firstNeighbor = (int32_t)mConvexNeighbors.size(); + c.firstVert = (int32_t)mConvexVerts.size(); + c.numVerts = num; + bool rollback = false; + int id = start; + do { + if (vertVisited[(uint32_t)id] != 2*(int32_t)i) { + rollback = true; + break; + } + vertVisited[(uint32_t)id] = 2*(int32_t)i+1; + + mConvexVerts.pushBack(centers[(uint32_t)triOfVert[(uint32_t)id]]); + mConvexNeighbors.pushBack(id); + id = nextVert[(uint32_t)id]; + } while (id != start); + + if (rollback) { + mConvexVerts.resize((uint32_t)c.firstVert); + mConvexNeighbors.resize((uint32_t)c.firstNeighbor); + continue; + } + + c.numVerts = (int32_t)mConvexVerts.size() - c.firstVert; + c.numNeighbors = (int32_t)mConvexNeighbors.size() - c.firstNeighbor; + convexOfVert[i] = (int32_t)mConvexes.size(); + mConvexes.pushBack(c); + } + + // compute neighbors + uint32_t newPos = 0; + for (uint32_t i = 0; i < mConvexes.size(); i++) { + Convex &c = mConvexes[i]; + uint32_t pos = (uint32_t)c.firstNeighbor; + uint32_t num = (uint32_t)c.numNeighbors; + c.firstNeighbor = (int32_t)newPos; + c.numNeighbors = 0; + for (uint32_t j = 0; j < num; j++) { + int n = convexOfVert[(uint32_t)mConvexNeighbors[pos+j]]; + if (n >= 0) { + mConvexNeighbors[newPos] = n; + newPos++; + c.numNeighbors++; + } + } + } + mConvexNeighbors.resize(newPos); +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/Delaunay2dBase.h b/APEX_1.4/module/destructible/fracture/Core/Delaunay2dBase.h new file mode 100644 index 00000000..2d477c14 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/Delaunay2dBase.h @@ -0,0 +1,110 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef DELAUNAY_2D_BASE_H +#define DELAUNAY_2D_BASE_H + +#include <PxVec3.h> +#include <PsArray.h> +#include <PsUserAllocated.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +// ------------------------------------------------------------------------------ + +struct Point; +struct Edge; +struct Triangle; +class SimScene; + +// ------------------------------------------------------------------------------ + +class Delaunay2d : public UserAllocated { + friend class SimScene; +public: + // singleton pattern + //static Delaunay2d* getInstance(); + //static void destroyInstance(); + + void triangulate(const PxVec3 *vertices, int numVerts, int byteStride, bool removeFarVertices = true); + const nvidia::Array<int> getIndices() const { return mIndices; } + + // voronoi mesh, needs triangle mesh + void computeVoronoiMesh(); + + struct Convex { + int firstVert; + int numVerts; + int firstNeighbor; + int numNeighbors; + }; + + const nvidia::Array<Convex> getConvexes() const { return mConvexes; } + const nvidia::Array<PxVec3> getConvexVerts() const { return mConvexVerts; } + const nvidia::Array<int> getConvexNeighbors() const { return mConvexNeighbors; } + +protected: + Delaunay2d(SimScene* scene); + virtual ~Delaunay2d(); + + void clear(); + void delaunayTriangulation(); + + struct Edge { + Edge() {} + Edge(int np0, int np1) { p0 = np0; p1 = np1; } + bool operator == (const Edge &e) { + return (p0 == e.p0 && p1 == e.p1) || (p0 == e.p1 && p1 == e.p0); + } + int p0, p1; + }; + + struct Triangle { + int p0, p1, p2; + PxVec3 center; + float circumRadiusSquared; + }; + + void addTriangle(int p0, int p1, int p2); + void getCircumSphere(const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2, + PxVec3 ¢er, float &radiusSquared); + + SimScene* mScene; + + nvidia::Array<PxVec3> mVertices; + nvidia::Array<int> mIndices; + + nvidia::Array<Triangle> mTriangles; + nvidia::Array<Edge> mEdges; + + nvidia::Array<Convex> mConvexes; + nvidia::Array<PxVec3> mConvexVerts; + nvidia::Array<int> mConvexNeighbors; + + int mFirstFarVertex; +}; + +} +} +} + +// ------------------------------------------------------------------------------ + + +#endif +#endif diff --git a/APEX_1.4/module/destructible/fracture/Core/Delaunay3dBase.cpp b/APEX_1.4/module/destructible/fracture/Core/Delaunay3dBase.cpp new file mode 100644 index 00000000..4af95e65 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/Delaunay3dBase.cpp @@ -0,0 +1,566 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "Delaunay3dBase.h" +#include "PsSort.h" +#include <PxAssert.h> + +#include "PxBounds3.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace nvidia; + +// side orientation points outwards +const int Delaunay3d::Tetra::sideIndices[4][3] = {{1,2,3},{2,0,3},{0,1,3},{2,1,0}}; + +// ------ singleton pattern ----------------------------------------------------------- +// +//static Delaunay3d *gDelaunay3d = NULL; +// +//Delaunay3d* Delaunay3d::getInstance() +//{ +// if (gDelaunay3d == NULL) { +// gDelaunay3d = PX_NEW(Delaunay3d)(); +// } +// return gDelaunay3d; +//} +// +//void Delaunay3d::destroyInstance() +//{ +// if (gDelaunay3d != NULL) { +// PX_DELETE(gDelaunay3d); +// } +// gDelaunay3d = NULL; +//} + +// ----------------------------------------------------------------------------- +void Delaunay3d::tetrahedralize(const PxVec3 *vertices, int numVerts, int byteStride, bool removeExtraVerts) +{ + clear(); + + uint8_t *vp = (uint8_t*)vertices; + for (int i = 0; i < numVerts; i++) { + mVertices.pushBack(*(PxVec3*)vp); + vp += byteStride; + } + + delaunayTetrahedralization(); + + compressTetrahedra(removeExtraVerts); + if (removeExtraVerts) { + mVertices.resize((uint32_t)mFirstFarVertex); + } + + for (uint32_t i = 0; i < mTetras.size(); i++) { + Tetra &t = mTetras[i]; + mIndices.pushBack(t.ids[0]); + mIndices.pushBack(t.ids[1]); + mIndices.pushBack(t.ids[2]); + mIndices.pushBack(t.ids[3]); + } +} + +// ----------------------------------------------------------------------------- +void Delaunay3d::clear() +{ + mVertices.clear(); + mIndices.clear(); + mTetras.clear(); + mFirstFarVertex = 0; + mLastFarVertex = 0; + + mGeom.clear(); + + mTetMarked.clear(); + mTetMark = 0; +} + +// ----------------------------------------------------------------------------- +void Delaunay3d::delaunayTetrahedralization() +{ + int i,j; + + nvidia::Array<Edge> edges; + Edge edge; + + PxBounds3 bounds; + bounds.setEmpty(); + for (uint32_t i = 0; i < mVertices.size(); i++) + bounds.include(mVertices[i]); + + // start with large tetrahedron + mTetras.clear(); + float a = 3.0f * bounds.getDimensions().magnitude(); + float x = 0.5f * a; + float y0 = x / sqrtf(3.0f); + float y1 = x * sqrtf(3.0f) - y0; + float z0 = 0.25f * sqrtf(6.0f) * a; + float z1 = a * sqrtf(6.0f) / 3.0f - z0; + + PxVec3 center = bounds.getCenter(); + + mFirstFarVertex = (int32_t)mVertices.size(); + PxVec3 p0(-x,-y0,-z1); mVertices.pushBack(center + p0); + PxVec3 p1( x,-y0,-z1); mVertices.pushBack(center + p1); + PxVec3 p2( 0, y1,-z1); mVertices.pushBack(center + p2); + PxVec3 p3( 0, 0, z0); mVertices.pushBack(center + p3); + mLastFarVertex = (int32_t)mVertices.size()-1; + + Tetra tetra; + tetra.init(mFirstFarVertex, mFirstFarVertex+1, mFirstFarVertex+2, mFirstFarVertex+3); + mTetras.pushBack(tetra); + + // build Delaunay triangulation iteratively + + int lastVertex = (int)mVertices.size()-4; + for (i = 0; i < lastVertex; i++) { + PxVec3 &v = mVertices[(uint32_t)i]; + + int tNr = findSurroundingTetra((int32_t)mTetras.size()-1, v); // fast walk + if (tNr < 0) + continue; + // assert(tNr >= 0); + + int newTetraNr = (int32_t)mTetras.size(); + retriangulate(tNr, i); + edges.clear(); + for (j = newTetraNr; j < (int)mTetras.size(); j++) { + Tetra &newTet = mTetras[(uint32_t)j]; + edge.init(newTet.ids[2], newTet.ids[3], j,1); + edges.pushBack(edge); + edge.init(newTet.ids[3], newTet.ids[1], j,2); + edges.pushBack(edge); + edge.init(newTet.ids[1], newTet.ids[2], j,3); + edges.pushBack(edge); + } + shdfnd::sort(edges.begin(), edges.size()); + for (j = 0; j < (int)edges.size(); j += 2) { + Edge &edge0 = edges[(uint32_t)j]; + Edge &edge1 = edges[(uint32_t)j+1]; + PX_ASSERT(edge0 == edge1); + mTetras[(uint32_t)edge0.tetraNr].neighborNrs[(uint32_t)edge0.neighborNr] = edge1.tetraNr; + mTetras[(uint32_t)edge1.tetraNr].neighborNrs[(uint32_t)edge1.neighborNr] = edge0.tetraNr; + } + } +} + +// ----------------------------------------------------------------------------- +int Delaunay3d::findSurroundingTetra(int startTetra, const PxVec3 &p) const +{ + // find the tetrahedra which contains the vertex + // by walking through mesh O(n ^ (1/3)) + + mTetMark++; + + if (mTetras.size() == 0) return -1; + int tetNr = startTetra; + PX_ASSERT(!mTetras[(uint32_t)startTetra].deleted); + + if (mTetMarked.size() < mTetras.size()) + mTetMarked.resize(mTetras.size(), -1); + + bool loop = false; + + while (tetNr >= 0) { + if (mTetMarked[(uint32_t)tetNr] == mTetMark) { + loop = true; + break; + } + mTetMarked[(uint32_t)tetNr] = mTetMark; + + const Tetra &tetra = mTetras[(uint32_t)tetNr]; + const PxVec3 &p0 = mVertices[(uint32_t)tetra.ids[0]]; + PxVec3 q = p-p0; + PxVec3 q0 = mVertices[(uint32_t)tetra.ids[1]] - p0; + PxVec3 q1 = mVertices[(uint32_t)tetra.ids[2]] - p0; + PxVec3 q2 = mVertices[(uint32_t)tetra.ids[3]] - p0; + PxMat33 m; + m.column0 = q0; + m.column1 = q1; + m.column2 = q2; + float det = m.getDeterminant(); + m.column0 = q; + float x = m.getDeterminant(); + if (x < 0.0f && tetra.neighborNrs[1] >= 0) { + tetNr = tetra.neighborNrs[1]; + continue; + } + m.column0 = q0; m.column1 = q; + float y = m.getDeterminant(); + if (y < 0.0f && tetra.neighborNrs[2] >= 0) { + tetNr = tetra.neighborNrs[2]; + continue; + } + m.column1 = q1; m.column2 = q; + float z = m.getDeterminant(); + if (z < 0.0f && tetra.neighborNrs[3] >= 0) { + tetNr = tetra.neighborNrs[3]; + continue; + } + if (x + y + z > det && tetra.neighborNrs[0] >= 0) { + tetNr = tetra.neighborNrs[0]; + continue; + } + return tetNr; + } + if (loop) { // search failed, brute force: + for (uint32_t i = 0; i < mTetras.size(); i++) { + const Tetra &tetra = mTetras[i]; + if (tetra.deleted) + continue; + + const PxVec3 &p0 = mVertices[(uint32_t)tetra.ids[0]]; + const PxVec3 &p1 = mVertices[(uint32_t)tetra.ids[1]]; + const PxVec3 &p2 = mVertices[(uint32_t)tetra.ids[2]]; + const PxVec3 &p3 = mVertices[(uint32_t)tetra.ids[3]]; + + PxVec3 n; + n = (p1-p0).cross(p2-p0); + if (n.dot(p) < n.dot(p0)) continue; + n = (p2-p0).cross(p3-p0); + if (n.dot(p) < n.dot(p0)) continue; + n = (p3-p0).cross(p1-p0); + if (n.dot(p) < n.dot(p0)) continue; + n = (p3-p1).cross(p2-p1); + if (n.dot(p) < n.dot(p1)) continue; + return (int32_t)i; + } + return -1; + } + else + return -1; +} + +// ----------------------------------------------------------------------------- +void Delaunay3d::updateCircumSphere(Tetra &tetra) +{ + if (!tetra.circumsphereDirty) + return; + PxVec3 p0 = mVertices[(uint32_t)tetra.ids[0]]; + PxVec3 b = mVertices[(uint32_t)tetra.ids[1]] - p0; + PxVec3 c = mVertices[(uint32_t)tetra.ids[2]] - p0; + PxVec3 d = mVertices[(uint32_t)tetra.ids[3]] - p0; + float det = b.x*(c.y*d.z - c.z*d.y) - b.y*(c.x*d.z - c.z*d.x) + b.z*(c.x*d.y-c.y*d.x); + if (det == 0.0f) { + tetra.center = p0; tetra.radiusSquared = 0.0f; + return; // singular case + } + det *= 2.0f; + PxVec3 v = c.cross(d)*b.dot(b) + d.cross(b)*c.dot(c) + b.cross(c)*d.dot(d); + v /= det; + tetra.radiusSquared = v.magnitudeSquared(); + tetra.center = p0 + v; + tetra.circumsphereDirty = false; +} + +// ----------------------------------------------------------------------------- +bool Delaunay3d::pointInCircumSphere(Tetra &tetra, const PxVec3 &p) +{ + updateCircumSphere(tetra); + return (tetra.center - p).magnitudeSquared() < tetra.radiusSquared; +} + +// ----------------------------------------------------------------------------- +void Delaunay3d::retriangulate(int tetraNr, int vertNr) +{ + Tetra &tetra = mTetras[(uint32_t)tetraNr]; + if (tetra.deleted) return; + Tetra tNew; + PxVec3 &v = mVertices[(uint32_t)vertNr]; + tetra.deleted = true; + for (uint32_t i = 0; i < 4; i++) { + int n = mTetras[(uint32_t)tetraNr].neighborNrs[i]; + if (n >= 0 && mTetras[(uint32_t)n].deleted) + continue; + if (n >= 0 && pointInCircumSphere(mTetras[(uint32_t)n],v)) + retriangulate(n, vertNr); + else { + Tetra &t = mTetras[(uint32_t)tetraNr]; + tNew.init(vertNr, + t.ids[(uint32_t)Tetra::sideIndices[i][0]], + t.ids[(uint32_t)Tetra::sideIndices[i][1]], + t.ids[(uint32_t)Tetra::sideIndices[i][2]] + ); + tNew.neighborNrs[0] = n; + if (n >= 0) { + mTetras[(uint32_t)n].neighborOf( + tNew.ids[1], tNew.ids[2], tNew.ids[3]) + = (int32_t)mTetras.size(); + } + mTetras.pushBack(tNew); + } + } +} + +// ---------------------------------------------------------------------- +void Delaunay3d::compressTetrahedra(bool removeExtraVerts) +{ + nvidia::Array<int> oldToNew(mTetras.size(), -1); + + uint32_t num = 0; + for (uint32_t i = 0; i < mTetras.size(); i++) { + Tetra &t = mTetras[i]; + + if (removeExtraVerts) { + if (t.ids[0] >= mFirstFarVertex || + t.ids[1] >= mFirstFarVertex || + t.ids[2] >= mFirstFarVertex || + t.ids[3] >= mFirstFarVertex) + continue; + } + + if (t.deleted) + continue; + + oldToNew[i] = (int32_t)num; + mTetras[num] = t; + num++; + } + mTetras.resize(num); + + for (uint32_t i = 0; i < num; i++) { + Tetra &t = mTetras[i]; + for (uint32_t j = 0; j < 4; j++) { + if (t.neighborNrs[j] >= 0) + t.neighborNrs[j] = oldToNew[(uint32_t)t.neighborNrs[j]]; + } + } +} + +// ---------------------------------------------------------------------- +void Delaunay3d::computeVoronoiMesh() +{ + mGeom.clear(); + + if (mTetras.empty()) + return; + + // vertex -> tetras links + uint32_t numVerts = mVertices.size(); + + nvidia::Array<int> firstVertTet(numVerts+1, 0); + nvidia::Array<int> vertTets; + + nvidia::Array<int> tetMarks(mTetras.size(), -1); + int tetMark = 0; + + for (uint32_t i = 0; i < mTetras.size(); i++) { + Tetra &t = mTetras[i]; + firstVertTet[(uint32_t)t.ids[0]]++; + firstVertTet[(uint32_t)t.ids[1]]++; + firstVertTet[(uint32_t)t.ids[2]]++; + firstVertTet[(uint32_t)t.ids[3]]++; + } + + int numLinks = 0; + for (uint32_t i = 0; i < numVerts; i++) { + numLinks += firstVertTet[i]; + firstVertTet[i] = numLinks; + } + firstVertTet[numVerts] = numLinks; + vertTets.resize((uint32_t)numLinks); + + for (uint32_t i = 0; i < mTetras.size(); i++) { + Tetra &t = mTetras[i]; + uint32_t &i0 = (uint32_t&)firstVertTet[(uint32_t)t.ids[0]]; + uint32_t &i1 = (uint32_t&)firstVertTet[(uint32_t)t.ids[1]]; + uint32_t &i2 = (uint32_t&)firstVertTet[(uint32_t)t.ids[2]]; + uint32_t &i3 = (uint32_t&)firstVertTet[(uint32_t)t.ids[3]]; + i0--; vertTets[i0] = (int32_t)i; + i1--; vertTets[i1] = (int32_t)i; + i2--; vertTets[i2] = (int32_t)i; + i3--; vertTets[i3] = (int32_t)i; + } + + nvidia::Array<int> convexOfFace(numVerts, -1); + nvidia::Array<int> vertOfTet(mTetras.size(), -1); + nvidia::Array<int> convexOfVert(numVerts, -1); + + for (uint32_t i = 0; i < numVerts; i++) { + int i0 = (int32_t)i; + + int firstTet = firstVertTet[i]; + int lastTet = firstVertTet[i+1]; + + // debug + //bool ok = true; + //for (int j = firstTet; j < lastTet; j++) { + // int tetNr = vertTets[j]; + // Tetra &t = mTetras[tetNr]; + // int num = 0; + // for (int k = 0; k < 4; k++) { + // int n = t.neighborNrs[k]; + // bool in = false; + // for (int l = firstTet; l < lastTet; l++) { + // if (vertTets[l] == n) + // in = true; + // } + // if (in) + // num++; + // } + // if (num != 3) + // ok = false; + //} + //if (ok) + // int foo = 0; + + + // new convex + int convexNr = (int32_t)i; + CompoundGeometry::Convex c; + mGeom.initConvex(c); + c.numVerts = lastTet - firstTet; + + bool rollBack = false; + + // create vertices + for (int j = firstTet; j < lastTet; j++) { + int tetNr = vertTets[(uint32_t)j]; + vertOfTet[(uint32_t)tetNr] = j - firstTet; + updateCircumSphere(mTetras[(uint32_t)tetNr]); + mGeom.vertices.pushBack(mTetras[(uint32_t)tetNr].center); + } + + // create indices + for (int j = firstTet; j < lastTet; j++) { + int tetNr = vertTets[(uint32_t)j]; + Tetra &t = mTetras[(uint32_t)tetNr]; + + for (uint32_t k = 0; k < 4; k++) { + int i1 = t.ids[k]; + if (i1 == i0) + continue; + if (convexOfFace[(uint32_t)i1] == convexNr) + continue; + convexOfFace[(uint32_t)i1] = convexNr; + mGeom.neighbors.pushBack(i1); + c.numNeighbors++; + + // new face + c.numFaces++; + int faceStart = (int32_t)mGeom.indices.size(); + mGeom.indices.pushBack(0); + mGeom.indices.pushBack(0); // face attrib + + int faceSize = 0; + int currNr = tetNr; + int prevNr = -1; + tetMark++; + + do { + mGeom.indices.pushBack(vertOfTet[(uint32_t)currNr]); + faceSize++; + + if (tetMarks[(uint32_t)currNr] == tetMark) { // safety + rollBack = true; + break; + } + tetMarks[(uint32_t)currNr] = tetMark; + + // find proper neighbor tet + int nextTet = -1; + for (uint32_t l = 0; l < 4; l++) { + int nr = mTetras[(uint32_t)currNr].neighborNrs[l]; + if (nr < 0) + continue; + if (nr == prevNr) + continue; + + Tetra &tn = mTetras[(uint32_t)nr]; + bool hasEdge = + (tn.ids[0] == i0 || tn.ids[1] == i0 || tn.ids[2] == i0 || tn.ids[3] == i0) && + (tn.ids[0] == i1 || tn.ids[1] == i1 || tn.ids[2] == i1 || tn.ids[3] == i1); + if (!hasEdge) + continue; + + //if (prevNr < 0) { // correct winding + // if ((t.center - faceC).cross(tn.center - faceC).dot(faceN) < 0.0f) + // continue; + //} + nextTet = nr; + break; + } + + if (nextTet < 0) { // not proper convex, roll back + rollBack = true; + break; + } + + prevNr = currNr; + currNr = nextTet; + + } while (currNr != tetNr); + + if (rollBack) + break; + + mGeom.indices[(uint32_t)faceStart] = faceSize; + } + if (rollBack) + break; + } + if (rollBack) { + mGeom.indices.resize((uint32_t)c.firstIndex); + mGeom.vertices.resize((uint32_t)c.firstVert); + } + else { + convexOfVert[(uint32_t)i] = (int32_t)mGeom.convexes.size(); + mGeom.convexes.pushBack(c); + } + } + + // fix face orientations + for (uint32_t i = 0; i < mGeom.convexes.size(); i++) { + CompoundGeometry::Convex &c = mGeom.convexes[i]; + int *ids = &mGeom.indices[(uint32_t)c.firstIndex]; + PxVec3 *vertices = &mGeom.vertices[(uint32_t)c.firstVert]; + PxVec3 cc(0.0f, 0.0f, 0.0f); + for (uint32_t j = 0; j < (uint32_t)c.numVerts; j++) + cc += vertices[j]; + cc /= (float)c.numVerts; + + uint32_t *faceIds = (uint32_t*)ids; + for (int j = 0; j < c.numFaces; j++) { + uint32_t faceSize = *faceIds++; + faceIds++; //int faceAttr = *faceIds++; + PxVec3 fc(0.0f, 0.0f, 0.0f); + for (uint32_t k = 0; k < faceSize; k++) + fc += vertices[faceIds[k]]; + fc /= (float)faceSize; + PxVec3 n = fc - cc; + if ((vertices[faceIds[1]] - vertices[faceIds[0]]).cross(vertices[faceIds[2]] - vertices[faceIds[0]]).dot(n) < 0.0f) { + for (uint32_t k = 0; k < faceSize/2; k++) { + uint32_t d = faceIds[k]; faceIds[k] = faceIds[faceSize-1-k]; faceIds[faceSize-1-k] = d; + } + } + faceIds += faceSize; + } + } + + // fix neighbors + for (uint32_t i = 0; i < mGeom.neighbors.size(); i++) { + if (mGeom.neighbors[i] >= 0) + mGeom.neighbors[i] = convexOfVert[(uint32_t)mGeom.neighbors[i]]; + } +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/Delaunay3dBase.h b/APEX_1.4/module/destructible/fracture/Core/Delaunay3dBase.h new file mode 100644 index 00000000..9ffaaa3a --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/Delaunay3dBase.h @@ -0,0 +1,139 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef DELAUNAY_3D_BASE_H +#define DELAUNAY_3D_BASE_H + +// Matthias Muller-Fischer + +#include <PxVec3.h> +#include <PsArray.h> +#include <PsUserAllocated.h> + +using namespace nvidia; + +#include "CompoundGeometryBase.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + class SimScene; + +// --------------------------------------------------------------------------------------- +class Delaunay3d : public UserAllocated { + friend class SimScene; +public: + // singleton pattern + //static Delaunay3d* getInstance(); + //static void destroyInstance(); + + // tetra mesh + void tetrahedralize(const PxVec3 *vertices, int numVerts, int byteStride, bool removeExtraVerts = true); + const nvidia::Array<int> getTetras() const { return mIndices; } + + // voronoi mesh, needs tetra mesh + void computeVoronoiMesh(); + + const CompoundGeometry &getGeometry() { return mGeom; } + +protected: + Delaunay3d(SimScene* scene): mScene(scene) {} + virtual ~Delaunay3d() {} + + // ------------------------------------------------------ + struct Edge + { + void init(int i0, int i1, int tetraNr, int neighborNr = -1) { + this->tetraNr = tetraNr; + this->neighborNr = neighborNr; + if (i0 > i1) { this->i0 = i0; this->i1 = i1; } + else { this->i0 = i1; this->i1 = i0; } + } + bool operator <(const Edge &e) const { + if (i0 < e.i0) return true; + if (i0 > e.i0) return false; + if (i1 < e.i1) return true; + if (i1 > e.i1) return false; + return (neighborNr < e.neighborNr); + } + bool operator ==(Edge &e) const { + return i0 == e.i0 && i1 == e.i1; + } + int i0, i1; + int tetraNr; + int neighborNr; + }; + + // ------------------------------------------------------ + struct Tetra + { + void init(int i0, int i1, int i2, int i3) { + ids[0] = i0; ids[1] = i1; ids[2] = i2; ids[3] = i3; + neighborNrs[0] = neighborNrs[1] = neighborNrs[2] = neighborNrs[3] = -1; + circumsphereDirty = true; + center = PxVec3(0.0f, 0.0f, 0.0f); + radiusSquared = 0.0f; + deleted = false; + } + inline int& neighborOf(int i0, int i1, int i2) { + if (ids[0] != i0 && ids[0] != i1 && ids[0] != i2) return neighborNrs[0]; + if (ids[1] != i0 && ids[1] != i1 && ids[1] != i2) return neighborNrs[1]; + if (ids[2] != i0 && ids[2] != i1 && ids[2] != i2) return neighborNrs[2]; + if (ids[3] != i0 && ids[3] != i1 && ids[3] != i2) return neighborNrs[3]; + return neighborNrs[0]; + } + + int ids[4]; + int neighborNrs[4]; + bool circumsphereDirty; + PxVec3 center; + float radiusSquared; + bool deleted; + + static const int sideIndices[4][3]; + }; + + // ------------------------------------------------------ + void clear(); + void delaunayTetrahedralization(); + + int findSurroundingTetra(int startTetra, const PxVec3 &p) const; + void updateCircumSphere(Tetra &tetra); + bool pointInCircumSphere(Tetra &tetra, const PxVec3 &p); + void retriangulate(int tetraNr, int vertNr); + void compressTetrahedra(bool removeExtraVerts); + + SimScene* mScene; + + int mFirstFarVertex; + int mLastFarVertex; + nvidia::Array<PxVec3> mVertices; + nvidia::Array<Tetra> mTetras; + nvidia::Array<int> mIndices; + + CompoundGeometry mGeom; + + mutable nvidia::Array<int> mTetMarked; + mutable int mTetMark; + +}; + +} +} +} + +#endif +#endif diff --git a/APEX_1.4/module/destructible/fracture/Core/FracturePatternBase.cpp b/APEX_1.4/module/destructible/fracture/Core/FracturePatternBase.cpp new file mode 100644 index 00000000..f4a87b27 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/FracturePatternBase.cpp @@ -0,0 +1,1021 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "PxMath.h" +#include "PxMat44.h" +#include "PsMathUtils.h" + +#include "FracturePatternBase.h" +#include "ConvexBase.h" +#include "CompoundBase.h" +#include "MeshClipperBase.h" +#include "IslandDetectorBase.h" +#include "SimSceneBase.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace nvidia; + +#define HIDE_INVISIBLE_FACES 1 + +// -------------------------------------------------------------------------------------------- +FracturePattern::FracturePattern(SimScene* scene): + mScene(scene) +{ +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::clear() +{ + mGeom.clear(); + mFirstConvexOfCell.clear(); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::finalize() +{ + mFirstPiece.resize(mGeom.convexes.size(), -1); + mSplitPiece.resize(mGeom.convexes.size(), false); + mPieces.clear(); + + // compute volumes of convexes + mConvexVolumes.resize(mGeom.convexes.size(), 0.0f); + Convex* c = mScene->createConvex(); + for (uint32_t i = 0; i < mGeom.convexes.size(); i++) { + c->createFromGeometry(mGeom, (int32_t)i); + mConvexVolumes[i] = c->getVolume(); + } + mGeom.derivePlanes(); + PX_DELETE(c); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::create3dVoronoi(const PxVec3 &dims, int numCells, float biasExp, float maxDist) +{ + using namespace physx::shdfnd; + clear(); + nvidia::Array<PxVec3> points((uint32_t)numCells); + float r = PxPow(dims.magnitude(), 1.0f/biasExp); + float max2 = maxDist * maxDist; + + mBounds.minimum = -dims; + mBounds.maximum = dims; + + for (int i = 0; i < numCells; i++) { + PxVec3 &p = points[(uint32_t)i]; + do { + p = PxVec3(rand(-r,r), rand(-r,r), rand(-r,r)); + float len = p.normalize(); + p *= PxPow(len, biasExp); + } while (!mBounds.contains(p) || (maxDist < PX_MAX_F32 && p.magnitudeSquared() > max2)); + } + // avoid numerical problems with flat quads! + float eps = 0.001f * mBounds.getDimensions().magnitude(); + points.pushBack(PxVec3(-dims.x + rand(-eps, eps), -dims.y + rand(-eps, eps), -dims.z + rand(-eps, eps))); + points.pushBack(PxVec3( dims.x + rand(-eps, eps), -dims.y + rand(-eps, eps), -dims.z + rand(-eps, eps))); + points.pushBack(PxVec3( dims.x + rand(-eps, eps), dims.y + rand(-eps, eps), -dims.z + rand(-eps, eps))); + points.pushBack(PxVec3(-dims.x + rand(-eps, eps), dims.y + rand(-eps, eps), -dims.z + rand(-eps, eps))); + points.pushBack(PxVec3(-dims.x + rand(-eps, eps), -dims.y + rand(-eps, eps), dims.z + rand(-eps, eps))); + points.pushBack(PxVec3( dims.x + rand(-eps, eps), -dims.y + rand(-eps, eps), dims.z + rand(-eps, eps))); + points.pushBack(PxVec3( dims.x + rand(-eps, eps), dims.y + rand(-eps, eps), dims.z + rand(-eps, eps))); + points.pushBack(PxVec3(-dims.x + rand(-eps, eps), dims.y + rand(-eps, eps), dims.z + rand(-eps, eps))); + + Delaunay3d *d = mScene->getDelaunay3d(); + d->tetrahedralize(&points[0], (int32_t)points.size(), sizeof(PxVec3), true); + d->computeVoronoiMesh(); + mGeom = d->getGeometry(); + + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::createLocal3dVoronoi(const PxVec3 &dims, int numCells, float radius) +{ + using namespace physx::shdfnd; + + clear(); + nvidia::Array<PxVec3> points((uint32_t)numCells); + float r = radius; + float r2 = r*r; + + mBounds.minimum = -dims; + mBounds.maximum = dims; + + for (int i = 0; i < numCells; i++) { + PxVec3 &p = points[(uint32_t)i]; + do { + p = PxVec3(rand(-r,r), rand(-r,r), rand(-r,r)); + } while (!mBounds.contains(p) || p.magnitudeSquared() > r2); + } + // avoid numerical problems with flat quads! + float eps = 0.001f * mBounds.getDimensions().magnitude(); + points.pushBack(PxVec3(-dims.x + rand(-eps, eps), -dims.y + rand(-eps, eps), -dims.z + rand(-eps, eps))); + points.pushBack(PxVec3( dims.x + rand(-eps, eps), -dims.y + rand(-eps, eps), -dims.z + rand(-eps, eps))); + points.pushBack(PxVec3( dims.x + rand(-eps, eps), dims.y + rand(-eps, eps), -dims.z + rand(-eps, eps))); + points.pushBack(PxVec3(-dims.x + rand(-eps, eps), dims.y + rand(-eps, eps), -dims.z + rand(-eps, eps))); + points.pushBack(PxVec3(-dims.x + rand(-eps, eps), -dims.y + rand(-eps, eps), dims.z + rand(-eps, eps))); + points.pushBack(PxVec3( dims.x + rand(-eps, eps), -dims.y + rand(-eps, eps), dims.z + rand(-eps, eps))); + points.pushBack(PxVec3( dims.x + rand(-eps, eps), dims.y + rand(-eps, eps), dims.z + rand(-eps, eps))); + points.pushBack(PxVec3(-dims.x + rand(-eps, eps), dims.y + rand(-eps, eps), dims.z + rand(-eps, eps))); + + Delaunay3d *d = mScene->getDelaunay3d(); + d->tetrahedralize(&points[0], (int32_t)points.size(), sizeof(PxVec3), true); + d->computeVoronoiMesh(); + mGeom = d->getGeometry(); + + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::createRegular3dVoronoi(const PxVec3 &dims, float pieceSize, float relRandOffset) +{ + clear(); + mBounds.minimum= -dims; + mBounds.maximum= dims; + nvidia::Array<PxVec3> points; + + float rel = relRandOffset; + if (rel < 1e-4f) + rel = 1e-4f; // avoid singular cases + + float off = rel * pieceSize; + + int numX = (int)(2.0f*dims.x / pieceSize) + 1; + int numY = (int)(2.0f*dims.y / pieceSize) + 1; + int numZ = (int)(2.0f*dims.z / pieceSize) + 1; + + for (int xi = 0; xi < numX; xi++) { + for (int yi = 0; yi < numY; yi++) { + for (int zi = 0; zi < numZ; zi++) { + points.pushBack(PxVec3( + mBounds.minimum.x + xi * pieceSize + physx::shdfnd::rand(-off, off), + mBounds.minimum.y + yi * pieceSize + physx::shdfnd::rand(-off, off), + mBounds.minimum.z + zi * pieceSize + physx::shdfnd::rand(-off, off))); + } + } + } + + Delaunay3d *d = mScene->getDelaunay3d(); + d->tetrahedralize(&points[0], (int32_t)points.size(), sizeof(PxVec3), true); + d->computeVoronoiMesh(); + mGeom = d->getGeometry(); + + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::addBox(const PxBounds3 &bounds) +{ + static int boxFaces[6][4] = {{0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7}, {0,3,2,1}, {4,5,6,7}}; + CompoundGeometry::Convex c; + mGeom.initConvex(c); + + c.numVerts = 8; + mGeom.vertices.pushBack(PxVec3(bounds.minimum.x, bounds.minimum.y, bounds.minimum.z)); + mGeom.vertices.pushBack(PxVec3(bounds.maximum.x, bounds.minimum.y, bounds.minimum.z)); + mGeom.vertices.pushBack(PxVec3(bounds.maximum.x, bounds.maximum.y, bounds.minimum.z)); + mGeom.vertices.pushBack(PxVec3(bounds.minimum.x, bounds.maximum.y, bounds.minimum.z)); + mGeom.vertices.pushBack(PxVec3(bounds.minimum.x, bounds.minimum.y, bounds.maximum.z)); + mGeom.vertices.pushBack(PxVec3(bounds.maximum.x, bounds.minimum.y, bounds.maximum.z)); + mGeom.vertices.pushBack(PxVec3(bounds.maximum.x, bounds.maximum.y, bounds.maximum.z)); + mGeom.vertices.pushBack(PxVec3(bounds.minimum.x, bounds.maximum.y, bounds.maximum.z)); + + c.numFaces = 6; + for (int i = 0; i < 6; i++) { + mGeom.indices.pushBack(4); // size + mGeom.indices.pushBack(0); // flags + for (int j = 0; j < 4; j++) + mGeom.indices.pushBack(boxFaces[i][j]); + } + mGeom.convexes.pushBack(c); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::createCrack(const PxVec3 &dims, float spacing, float zRand) +{ + clear(); + + float minZ = -1.2f * zRand; + float maxZ = 1.2f * zRand; + + PxBounds3 bounds; + bounds.minimum = PxVec3(-dims.x, -dims.y, -dims.z); + bounds.maximum = PxVec3( dims.x, dims.y, minZ); + addBox(bounds); + + nvidia::Array<PxVec3> points; + + mBounds.minimum = -dims; + mBounds.maximum = dims; + + float area = 4.0f * dims.x * dims.y; + int numCells = (int)(area / (spacing * spacing)); + + for (int i = 0; i < numCells; i++) { + PxVec3 p = PxVec3(physx::shdfnd::rand(-dims.x, dims.x), physx::shdfnd::rand(-dims.y,dims.y), 0.0f); + points.pushBack(p); + } + + Delaunay2d *d = mScene->getDelaunay2d(); + d->triangulate(&points[0], (int32_t)points.size(), sizeof(PxVec3), true); + d->computeVoronoiMesh(); + + // convert to 3d + const nvidia::Array<Delaunay2d::Convex> &convexes = d->getConvexes(); + nvidia::Array<PxVec3> verts = d->getConvexVerts(); + for (uint32_t i = 0; i < verts.size(); i++) + verts[i].z += physx::shdfnd::rand(-zRand, zRand); + + int numConvexes = (int32_t)convexes.size(); + + const nvidia::Array<int> &neighbors = d->getConvexNeighbors(); + + for (int side = 0; side < 2; side++) { + for (uint32_t i = 0; i < convexes.size(); i++) { + const Delaunay2d::Convex &c2 = convexes[i]; + + CompoundGeometry::Convex c3; + mGeom.initConvex(c3); + + // neighbors + c3.numNeighbors = c2.numNeighbors + 2; + for (int j = 0; j < c2.numNeighbors; j++) { + int n = neighbors[uint32_t(c2.firstNeighbor + j)] + 1; + if (side == 0) + mGeom.neighbors.pushBack(n); + else + mGeom.neighbors.pushBack(numConvexes + n); + } + if (side == 0) { + mGeom.neighbors.pushBack(1 + numConvexes + (int32_t)i); + mGeom.neighbors.pushBack(0); + } + else { + mGeom.neighbors.pushBack(1 + (int32_t)i); + mGeom.neighbors.pushBack(1 + 2*numConvexes); + } + + // vertices + c3.numVerts = 2 * c2.numVerts; + for (int j = 0; j < c2.numVerts; j++) { + PxVec3 p = verts[uint32_t(c2.firstVert+j)]; + if (side == 0) { + mGeom.vertices.pushBack(PxVec3(p.x, p.y, minZ)); + mGeom.vertices.pushBack(p); + } + else { + mGeom.vertices.pushBack(p); + mGeom.vertices.pushBack(PxVec3(p.x, p.y, maxZ)); + } + } + + // faces + c3.numFaces = c2.numVerts + 2; + mGeom.indices.pushBack(c2.numVerts); + mGeom.indices.pushBack(0); // flags + for (int j = 0; j < c2.numVerts; j++) + mGeom.indices.pushBack(2*j+1); + mGeom.indices.pushBack(c2.numVerts); + mGeom.indices.pushBack(0); // flags + for (int j = c2.numVerts-1; j >= 0; j--) + mGeom.indices.pushBack(2*j); + for (int j = 0; j < c2.numVerts; j++) { + mGeom.indices.pushBack(4); // size + mGeom.indices.pushBack(0); // flags + int k = (j+1)%c2.numVerts; + mGeom.indices.pushBack(2*j); + mGeom.indices.pushBack(2*k); + mGeom.indices.pushBack(2*k+1); + mGeom.indices.pushBack(2*j+1); + } + + mGeom.convexes.pushBack(c3); + } + } + + bounds.minimum = PxVec3(-dims.x, -dims.y, maxZ); + bounds.maximum = PxVec3( dims.x, dims.y, dims.z); + addBox(bounds); + + // two cells + mFirstConvexOfCell.pushBack(0); + mFirstConvexOfCell.pushBack(1 + numConvexes); + mFirstConvexOfCell.pushBack(1 + 2*numConvexes + 1); + + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::create2dVoronoi(const PxVec3 &dims, int numCells, float biasExp, int numRays) +{ + clear(); + nvidia::Array<PxVec3> points; + float r0 = dims.magnitude(); + float r = physx::shdfnd::pow(r0, 1.0f/biasExp); + + mBounds.minimum= -dims; + mBounds.maximum= dims; + + if (numRays == 0) { + for (int i = 0; i < numCells; i++) { + PxVec3 p; + do { + p = PxVec3(physx::shdfnd::rand(-r,r), physx::shdfnd::rand(-r,r), 0.0f); + float len = p.normalize(); + p *= physx::shdfnd::pow(len, biasExp); + } while (!mBounds.contains(p)); + points.pushBack(p); + } + } + else { + float diag = mBounds.getDimensions().magnitude(); + float eps = 0.0025f * diag; + + int cellsPerRay = numCells / numRays + 1; + float dr = 0.05f * diag / cellsPerRay; + float dphi = PxTwoPi / numRays; + + for (int i = 0; i < numRays; i++) { + float phi = i * dphi; + PxVec3 n(PxCos(phi), PxSin(phi), 0.0f); + + for (int j = 0; j < cellsPerRay; j++) { + float rj = dr * physx::shdfnd::pow((float)(j+1), biasExp); + PxVec3 p = n * rj; + p.x += physx::shdfnd::rand(-rj * eps, rj * eps); + p.y += physx::shdfnd::rand(-rj * eps, rj * eps); + if (!mBounds.contains(p)) + break; + points.pushBack(p); + } + } + } + + float s = 1.2f; + points.pushBack(PxVec3(-s*dims.x, -s*dims.y, 0.0f)); + points.pushBack(PxVec3( s*dims.x, -s*dims.y, 0.0f)); + points.pushBack(PxVec3( s*dims.x, s*dims.y, 0.0f)); + points.pushBack(PxVec3(-s*dims.x, s*dims.y, 0.0f)); + + Delaunay2d *d = mScene->getDelaunay2d(); + d->triangulate(&points[0], (int32_t)points.size(), sizeof(PxVec3), true); + d->computeVoronoiMesh(); + + // convert to 3d + const nvidia::Array<Delaunay2d::Convex> &convexes = d->getConvexes(); + const nvidia::Array<PxVec3> &verts = d->getConvexVerts(); + mGeom.neighbors = d->getConvexNeighbors(); + + mGeom.convexes.resize(convexes.size()); + for (uint32_t i = 0; i < convexes.size(); i++) { + CompoundGeometry::Convex &c3 = mGeom.convexes[i]; + const Delaunay2d::Convex &c2 = convexes[i]; + + c3.firstNeighbor = c2.firstNeighbor; + c3.numNeighbors = c2.numNeighbors; + + c3.firstVert = (int32_t)mGeom.vertices.size(); + c3.numVerts = 2 * c2.numVerts; + for (int j = 0; j < c2.numVerts; j++) { + PxVec3 p = verts[uint32_t(c2.firstVert+j)]; + p.z = mBounds.minimum.z; + mGeom.vertices.pushBack(p); + p.z = mBounds.maximum.z; + mGeom.vertices.pushBack(p); + } + + c3.firstIndex = (int32_t)mGeom.indices.size(); + c3.numFaces = c2.numVerts + 2; + mGeom.indices.pushBack(c2.numVerts); + mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE); + for (int j = 0; j < c2.numVerts; j++) + mGeom.indices.pushBack(2*j+1); + mGeom.indices.pushBack(c2.numVerts); + mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE); + for (int j = c2.numVerts-1; j >= 0; j--) + mGeom.indices.pushBack(2*j); + for (int j = 0; j < c2.numVerts; j++) { + mGeom.indices.pushBack(4); + mGeom.indices.pushBack(0); + int k = (j+1)%c2.numVerts; + mGeom.indices.pushBack(2*j); + mGeom.indices.pushBack(2*k); + mGeom.indices.pushBack(2*k+1); + mGeom.indices.pushBack(2*j+1); + } + } + + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::createGlass(float radius, float thickness, int numSectors, float sectorRand, float firstSegmentSize, float segmentScale, float segmentRand) +{ + clear(); + CompoundGeometry::Convex c; + static int faces[6][4] = {{0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7}, {3,2,1,0}, {4,5,6,7}}; + + nvidia::Array<float> secAngles((uint32_t)numSectors); + float dSec = PxTwoPi / (float)numSectors; + for (uint32_t i = 0; i < (uint32_t)numSectors; i++) + secAngles[i] = i * dSec + physx::shdfnd::rand(-sectorRand, sectorRand) * dSec; + + // how many segments? + float segSize = firstSegmentSize; + float d = 0.0f; + int numSegs = 0; + while (d < radius) { + numSegs++; + d += segSize; + segSize *= segmentScale; + } + + for (uint32_t i = 0; i < (uint32_t)numSectors; i++) { + float segSize = firstSegmentSize; + float d = 0.0f; + float r0 = 0.0f; + float r1 = 0.0f; + float p0, p1; + + float a0 = secAngles[i]; + float a1 = secAngles[(i + 1) % numSectors]; + + for (int j = 0; j < numSegs; j++) { + d += segSize; + p0 = r0; + p1 = r1; + r0 = d + physx::shdfnd::rand(-segmentRand, segmentRand) * segSize; + r1 = d + physx::shdfnd::rand(-segmentRand, segmentRand) * segSize; + segSize *= segmentScale; + + mGeom.initConvex(c); + c.numFaces = 6; + c.numNeighbors = 6; + c.numVerts = 8; + c.firstPlane = 0; + mGeom.convexes.pushBack(c); + + float sin0 = PxSin(a0); + float sin1 = PxSin(a1); + float cos0 = PxCos(a0); + float cos1 = PxCos(a1); + + mGeom.vertices.pushBack(PxVec3(p0 * cos0, p0 * sin0, -thickness)); + mGeom.vertices.pushBack(PxVec3(r0 * cos0, r0 * sin0, -thickness)); + mGeom.vertices.pushBack(PxVec3(r1 * cos1, r1 * sin1, -thickness)); + mGeom.vertices.pushBack(PxVec3(p1 * cos1, p1 * sin1, -thickness)); + mGeom.vertices.pushBack(PxVec3(p0 * cos0, p0 * sin0, thickness)); + mGeom.vertices.pushBack(PxVec3(r0 * cos0, r0 * sin0, thickness)); + mGeom.vertices.pushBack(PxVec3(r1 * cos1, r1 * sin1, thickness)); + mGeom.vertices.pushBack(PxVec3(p1 * cos1, p1 * sin1, thickness)); + + for (uint32_t k = 0; k < 6; k++) { + mGeom.indices.pushBack(4); // face size + mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE); // flags + mGeom.indices.pushBack(faces[k][0]); + mGeom.indices.pushBack(faces[k][1]); + mGeom.indices.pushBack(faces[k][2]); + mGeom.indices.pushBack(faces[k][3]); + } + mGeom.neighbors.pushBack(i > 0 ? ((int32_t)i-1) * numSegs + j : (numSectors-1) * numSegs + j); + mGeom.neighbors.pushBack(j < numSegs-1 ? (int32_t)i * numSegs + j+1 : -1); + mGeom.neighbors.pushBack((int32_t)i < numSectors-1 ? ((int32_t)i+1) * numSegs + j : j); + mGeom.neighbors.pushBack(j > 0 ? (int32_t)i * numSegs + j-1 : -1); + mGeom.neighbors.pushBack(-1); + mGeom.neighbors.pushBack(-1); + } + } + finalize(); +} +// -------------------------------------------------------------------------------------------- +void FracturePattern::createRegularCubeMesh(const PxVec3 &extents, float cubeSize) +{ + clear(); + int numX = (int)(2.0f*extents.x / cubeSize) + 1; + int numY = (int)(2.0f*extents.y / cubeSize) + 1; + int numZ = (int)(2.0f*extents.z / cubeSize) + 1; + + CompoundGeometry::Convex c; + static int faces[6][4] = {{0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7}, {3,2,1,0}, {4,5,6,7}}; + + for (int xi = 0; xi < numX; xi++) { + for (int yi = 0; yi < numY; yi++) { + for (int zi = 0; zi < numZ; zi++) { + mGeom.initConvex(c); + c.numFaces = 6; + c.numNeighbors = 6; + c.numVerts = 8; + c.firstPlane = 0; + mGeom.convexes.pushBack(c); + + PxVec3 p0(-extents.x + xi*cubeSize, -extents.y + yi*cubeSize, -extents.z + zi*cubeSize); + PxVec3 p1 = p0 + PxVec3(cubeSize, cubeSize, cubeSize); + mGeom.vertices.pushBack(PxVec3(p0.x, p0.y, p0.z)); + mGeom.vertices.pushBack(PxVec3(p1.x, p0.y, p0.z)); + mGeom.vertices.pushBack(PxVec3(p1.x, p1.y, p0.z)); + mGeom.vertices.pushBack(PxVec3(p0.x, p1.y, p0.z)); + mGeom.vertices.pushBack(PxVec3(p0.x, p0.y, p1.z)); + mGeom.vertices.pushBack(PxVec3(p1.x, p0.y, p1.z)); + mGeom.vertices.pushBack(PxVec3(p1.x, p1.y, p1.z)); + mGeom.vertices.pushBack(PxVec3(p0.x, p1.y, p1.z)); + for (int i = 0; i < 6; i++) { + mGeom.indices.pushBack(4); // face size + mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE); // flags + mGeom.indices.pushBack(faces[i][0]); + mGeom.indices.pushBack(faces[i][1]); + mGeom.indices.pushBack(faces[i][2]); + mGeom.indices.pushBack(faces[i][3]); + } + mGeom.neighbors.pushBack(yi > 0 ? (xi * numY + yi-1) * numZ + zi : -1); + mGeom.neighbors.pushBack(xi < numX-1 ? ((xi+1) * numY + yi) * numZ + zi : -1); + mGeom.neighbors.pushBack(yi < numY-1 ? (xi * numY + yi+1) * numZ + zi : -1); + mGeom.neighbors.pushBack(xi > 0 ? ((xi-1) * numY + yi) * numZ + zi : -1); + mGeom.neighbors.pushBack(zi > 0 ? (xi * numY + yi) * numZ + zi-1 : -1); + mGeom.neighbors.pushBack(zi < numZ-1 ? (xi * numY + yi) * numZ + zi+1 : -1); + } + } + } + + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::createCrosses(const PxVec3 &dims, float spacing) +{ + clear(); + + int numX = (int)floorf(2.0f * dims.x / spacing) + 1; + int numY = (int)floorf(2.0f * dims.y / spacing) + 1; + int numZ = (int)floorf(2.0f * dims.z / spacing) + 1; + + static int offset[5] = {0,3,1,4,2}; + static int cross[5][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}, {0,0}}; + PxBounds3 bounds; + + for (int zi = 0; zi < numZ; zi++) { + for (int yi = 0; yi < numY; yi++) { + for (int xi = 0; xi < numX; xi += 5) { + float z = -dims.z + (zi + xi % 2 + yi % 2) * spacing; + float y = -dims.y + yi * spacing; + float x = -dims.x + (xi + offset[yi % 5]) * spacing; + + mFirstConvexOfCell.pushBack((int32_t)mGeom.convexes.size()); + + for (int i = 0; i < 5; i++) { + bounds.minimum.x = x + cross[i][0] * spacing; + bounds.minimum.y = y + cross[i][1] * spacing; + bounds.minimum.z = z; + bounds.maximum = bounds.minimum + PxVec3(spacing, spacing, spacing); + addBox(bounds); + } + } + } + } + + mFirstConvexOfCell.pushBack((int32_t)mGeom.convexes.size()); + + finalize(); +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::getConvexIntersection(const Convex *convex, const PxMat44 &trans, float minConvexSize, int /*numFitDirections*/) const +{ + PxTransform localPose = convex->getLocalPose(); + const nvidia::Array<PxPlane> convexPlanes = convex->getPlanes(); + + mScene->profileBegin("find pattern candidates"); + + // cull outside convexes + nvidia::Array<int> candidates(mGeom.convexes.size()); + for (uint32_t i = 0; i < candidates.size(); i++) + candidates[i] = (int32_t)i; + + for (uint32_t i = 0; i < convexPlanes.size(); i++) { + PxPlane plane = convexPlanes[i]; + plane.n = localPose.rotate(plane.n); // only valid for rigid transforms! + plane.d = plane.d + localPose.p.dot(plane.n); + + uint32_t num = 0; + for (uint32_t j = 0; j < candidates.size(); j++) { + const CompoundGeometry::Convex &c = mGeom.convexes[(uint32_t)candidates[j]]; + bool inside = false; + for (int k = 0; k < c.numVerts; k++) { + PxVec3 p = trans.transform(mGeom.vertices[uint32_t(c.firstVert + k)]); + if (p.dot(plane.n) < plane.d) { + inside = true; + break; + } + } + if (inside) { + candidates[num] = candidates[j]; + num++; + } + } + candidates.resize(num); + } + + mScene->profileEnd("find pattern candidates"); + + // retreive convexes + Piece piece; + nvidia::Array<Convex*> newConvexes; + + mScene->profileBegin("clip all"); + + mScene->profileBegin("clipper init"); + MeshClipper *clipper = mScene->getMeshClipper(); + clipper->init(convex); + mScene->profileEnd("clipper init"); + + mScene->profileBegin("clipper clip"); + + for (uint32_t i = 0; i < candidates.size(); i++) { + uint32_t convexNr = (uint32_t)candidates[i]; + Convex *c = mScene->createConvex(); + const PxTransform transformTemp = convex->getLocalPose(); + c->createFromConvex(convex, &transformTemp); + const CompoundGeometry::Convex &gc = mGeom.convexes[convexNr]; + + bool empty = true; + c->intersectWithConvex(&mGeom.planes[(uint32_t)gc.firstPlane], gc.numFaces, trans, empty); + + if (empty) { + PX_DELETE(c); + continue; + } + + const PxBounds3 &bounds = c->getBounds(); + PxVec3 dim = bounds.getDimensions(); + if (!c->isGhostConvex() && (dim.x < minConvexSize || dim.y < minConvexSize || dim.z < minConvexSize)) { + PX_DELETE(c); + continue; + } + + empty = false; + newConvexes.clear(); + + if (convex->hasExplicitVisMesh()) { + if (!c->clipVisualMesh(clipper, convex->getLocalPose(), newConvexes)) { + PX_DELETE(c); + continue; + } + if (newConvexes.size() > 0) + mSplitPiece[convexNr] = true; + } + + c->setModelIslandNr(convex->getModelIslandNr()); + c->setSurfaceMaterialId(convex->getSurfaceMaterialId()); + newConvexes.pushBack(c); + + for (uint32_t i = 0; i < newConvexes.size(); i++) { + Convex *c = newConvexes[i]; + const PxBounds3 &bounds = c->getBounds(); + PxVec3 dim = bounds.getDimensions(); + if (!c->isGhostConvex() && (dim.x < minConvexSize || dim.y < minConvexSize || dim.z < minConvexSize)) { + // TODO: Spawn debris? + PX_DELETE(c); + continue; + } + piece.convex = newConvexes[i]; + piece.next = mFirstPiece[convexNr]; + mFirstPiece[convexNr] = (int32_t)mPieces.size(); + mPieces.pushBack(piece); + } + } + mScene->profileBegin("clipper clip"); + + mScene->profileEnd("clip all"); + +} + +// -------------------------------------------------------------------------------------------- +void FracturePattern::getCompoundIntersection(const Compound *compound, const PxMat44 &trans, float radius, float minConvexSize, + nvidia::Array<int> &compoundSizes, nvidia::Array<Convex*> &newConvexes) const +{ + // radius = 0.0f : complete fracture + // radius > 0.0f : partial (local) fracture + + //{ + + // IslandDetector *id = IslandDetector::getInstance(); + // id->detect(&convexes[0], convexes.size(), true); + //} + + const nvidia::Array<Convex*> &convexes = compound->getConvexes(); + //const nvidia::Array<PxBounds3>& attachmentBounds = compound->getAttachmentBounds(); + + PxMat33 m(trans.getBasis(0), trans.getBasis(1), trans.getBasis(2)); + float transScale = m.getDeterminant(); + + newConvexes.clear(); + compoundSizes.clear(); + + PxVec3 fractureCenter = trans.getPosition(); + + for (uint32_t i = 0; i < mGeom.convexes.size(); i++) { + mFirstPiece[i] = -1; + mSplitPiece[i] = false; + } + mPieces.clear(); + + nvidia::Array<Convex*> farConvexes; + nvidia::Array<Convex*> cellConvexes; + + // fracture convexes + int numFitDirections = 7; + + // complete fracture + if (radius == 0.0f) { + for (uint32_t i = 0; i < convexes.size(); i++) { + Convex *c = convexes[i]; + //if (c->isGhostConvex()) + // /*int foo = 0*/; + getConvexIntersection(c, trans, minConvexSize, numFitDirections); + } + } + else { // partial fracture + + // fracture non-ghost convexes and determine furthest fractured vertex + float maxGhostRadius2 = 0.0f; + + for (uint32_t i = 0; i < convexes.size(); i++) { + Convex *c = convexes[i]; + if (c->isGhostConvex()) + continue; + + PxTransform localPose = c->getLocalPose(); + PxVec3 localCenter = localPose.transformInv(fractureCenter); + + // is the convex outside of the fracture sphere? + if (c->insideFattened(localCenter, radius)) { + getConvexIntersection(c, trans, minConvexSize, numFitDirections); + + const nvidia::Array<PxVec3> &verts = c->getVertices(); + for (uint32_t j = 0; j < verts.size(); j++) { + float r2 = (verts[j] - localCenter).magnitudeSquared(); + if (r2 > maxGhostRadius2) + maxGhostRadius2 = r2; + } + } + else { + c->transform(localPose); + c->clearFraceFlags(CompoundGeometry::FF_NEW); + c->setIsFarConvex(true); + farConvexes.pushBack(c); // double use -> that is why we need reference counters for convexes! + } + } + + // added overlap test in island detector, no need for ghost anymore! + +// // fracture ghost convexes using the maxGhostRadius +// float maxGhostRadius = PxSqrt(maxGhostRadius2); +// +// for (int i = 0; i < (int)convexes.size(); i++) { +// Convex *c = convexes[i]; +// if (!c->isGhostConvex()) +// continue; +// PxTransform localPose = c->getLocalPose(); +// PxVec3 localCenter = localPose.transformInv(fractureCenter); +// +// // is the convex outside of the fracture sphere? +// if (c->insideFattened(localCenter, maxGhostRadius)) { +//// if (c->insideFattened(localCenter, radius)) { // foo +// getConvexIntersection(c, trans, minConvexSize, numFitDirections); +// } +// else { +// c->transform(localPose); +// farConvexes.pushBack(c); // double use -> that is why we need reference counters for convexes! +// } +// } + } + + // collect pieces + bool complexCells = !mFirstConvexOfCell.empty(); + uint32_t numCells = complexCells ? mFirstConvexOfCell.size()-1 : mGeom.convexes.size(); + + for (uint32_t i = 0; i < numCells; i++) { + uint32_t numConvexes = uint32_t(complexCells ? mFirstConvexOfCell[i+1] - mFirstConvexOfCell[i] : 1); + + cellConvexes.clear(); + PxVec3 matOff = PxVec3(0.0f, 0.0f, 0.0f); + bool hasGhosts = false; + bool splitCell = false; + + + for (uint32_t k = 0; k < numConvexes; k++) { + uint32_t convexNr = complexCells ? (uint32_t)mFirstConvexOfCell[i] + k : i; + + if (mSplitPiece[convexNr]) + splitCell = true; + + if (mFirstPiece[convexNr] < 0) + continue; + + int nr = mFirstPiece[convexNr]; + while (nr >= 0) { + Convex *c = mPieces[(uint32_t)nr].convex; + if (c->isGhostConvex()) + hasGhosts = true; + else + matOff = c->getMaterialOffset(); + cellConvexes.pushBack(c); + nr = mPieces[(uint32_t)nr].next; + } + } + + // fit to visual mesh, only if there are no ghost convexes, otherwise the faces do to match anymore + if (!hasGhosts) { + uint32_t num = 0; + for (uint32_t j = 0; j < cellConvexes.size(); j++) { + Convex *c = cellConvexes[j]; + if (c->hasExplicitVisMesh()) { + bool empty = false; + c->fitToVisualMesh(empty, numFitDirections); + if (empty) { + PX_DELETE(c); + continue; + } + } + cellConvexes[num] = c; + num++; + } + cellConvexes.resize(num); + } + + if (cellConvexes.size() == 1) { + newConvexes.pushBack(cellConvexes[0]); + compoundSizes.pushBack(1); + continue; + } + + // all volume covered with new pieces? + bool hasExplicitMesh = false; + + float volumeFraction = 0.0f; + for (uint32_t j = 0; j < cellConvexes.size(); j++) { + const Convex *c = cellConvexes[j]; + float vol = c->isGhostConvex() ? -c->getVolume() : c->getVolume(); + volumeFraction += vol; + if (c->hasExplicitVisMesh()) + hasExplicitMesh = true; + } + + float vol = mConvexVolumes[i] * transScale; + float volDiff = fabsf(vol - volumeFraction) / vol; + + if (splitCell) { // each convex piece within the pattern piece becomes a separate compound + for (uint32_t j = 0; j < cellConvexes.size(); j++) { + newConvexes.pushBack(cellConvexes[j]); + compoundSizes.pushBack(1); + } + } + else if (!complexCells && !hasExplicitMesh && volDiff < 0.01f) { // the entire pattern piece becomes a convex + // delete parts + for (uint32_t j = 0; j < cellConvexes.size(); j++) + PX_DELETE(cellConvexes[j]); + + // create single piece + Convex *c = mScene->createConvex(); + c->createFromGeometry(mGeom, (int32_t)i, &trans); + newConvexes.pushBack(c); + c->setMaterialOffset(matOff); + compoundSizes.pushBack(1); + } + else { // all connected convex pieces within the pattern cell become one compound + IslandDetector *id = mScene->getIslandDetector(); + id->detect(cellConvexes, false); + const nvidia::Array<IslandDetector::Island> &islands = id->getIslands(); + const nvidia::Array<int> &islandConvexes = id->getIslandConvexes(); + + for (uint32_t j = 0; j < islands.size(); j++) { + const IslandDetector::Island &is = islands[j]; + for (int k = 0; k < is.size; k++) + newConvexes.pushBack(cellConvexes[(uint32_t)islandConvexes[uint32_t(is.firstNr+k)]]); + compoundSizes.pushBack(is.size); + } + } + } + + // merge far convexes for local fracture + if (radius > 0.0f) { + farConvexes.reserve(farConvexes.size() + newConvexes.size()); + + uint32_t oldConvexNr = 0; + uint32_t newConvexNr = 0; + uint32_t numNewCompounds = 0; + + for (uint32_t i = 0; i < compoundSizes.size(); i++) { + uint32_t oldCompoundSize = (uint32_t)compoundSizes[i]; + uint32_t newCompoundSize = 0; + bool onlyGhosts = true; + for (uint32_t j = 0; j < oldCompoundSize; j++) { + Convex *c = newConvexes[oldConvexNr + j]; + if (!c->insideFattened(fractureCenter, radius)) { + c->clearFraceFlags(CompoundGeometry::FF_NEW); + c->setIsFarConvex(true); + farConvexes.pushBack(c); + } + else { + if (!c->isGhostConvex()) + onlyGhosts = false; + newConvexes[newConvexNr] = c; + newConvexNr++; + newCompoundSize++; + } + } + if (newCompoundSize > 0) { + if (onlyGhosts) { // remove compounds that contain only ghost convexes + for (uint32_t j = 0; j < newCompoundSize; j++) { + newConvexNr--; + PX_DELETE(newConvexes[newConvexNr]); + } + } + else { + compoundSizes[numNewCompounds] = (int32_t)newCompoundSize; + numNewCompounds++; + } + } + oldConvexNr += oldCompoundSize; + } + newConvexes.resize(newConvexNr); + compoundSizes.resize(numNewCompounds); + } + + if (farConvexes.size() > 0) { + IslandDetector *id = mScene->getIslandDetector(); + + mScene->profileBegin("island detection"); + + id->detect(farConvexes, true); + + mScene->profileEnd("island detection"); + + const nvidia::Array<IslandDetector::Island> &islands = id->getIslands(); + const nvidia::Array<int> &islandConvexes = id->getIslandConvexes(); + + for (uint32_t i = 0; i < islands.size(); i++) { + const IslandDetector::Island &island = islands[i]; + compoundSizes.pushBack(island.size); + for (int j = 0; j < island.size; j++) { + int nr = islandConvexes[uint32_t(island.firstNr + j)]; + newConvexes.pushBack(farConvexes[(uint32_t)nr]); + } + } + + //const nvidia::Array<int> &pairs = id->getNeighborEdges(); + //FILE *f = fopen("c:\\test.txt", "a"); + //fprintf(f, "convexes %i, edges %i\n", farConvexes.size(), pairs.size()/2); + //fclose(f); + + //StaticTester::getInstance()->setStretchThreshold(1.0f); // 1 newton / m^2 + //StaticTester::getInstance()->setCompressionThreshold(10.0f); // 10 newton / m^2 + //StaticTester::getInstance()->setTorqueThreshold(2.0f); // 2 newton / m + //StaticTester::getInstance()->analyse(farConvexes, attachmentBounds, id->getNeighborEdges()); + +#if HIDE_INVISIBLE_FACES + if (radius != 0.0f) { + // invisible faces may open up with partial fracturing + const nvidia::Array<float> faceCoverage = mScene->getIslandDetector()->getFaceCoverage(); + uint32_t globalFaceNr = 0; + for (uint32_t i = 0; i < farConvexes.size(); i++) { + Convex *c = farConvexes[i]; + c->updateFaceVisibility(&faceCoverage[globalFaceNr]); + globalFaceNr += c->getFaces().size(); + } + // brute force + //for (int i = 0; i < (int)newConvexes.size(); i++) { + // newConvexes[i]->updateFaceVisibility + // newConvexes[i]->removeInvisibleFacesFlags(); + //} + } +#endif + } + + //if (farConvexes.size() > 0) { + // compoundSizes.pushBack(farConvexes.size()); + // for (int i = 0; i < (int)farConvexes.size(); i++) + // newConvexes.pushBack(farConvexes[i]); + //} + +// printf("%i new convexes, %i new compounds\n", newConvexes.size(), compoundSizes.size()); +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/FracturePatternBase.h b/APEX_1.4/module/destructible/fracture/Core/FracturePatternBase.h new file mode 100644 index 00000000..425efd22 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/FracturePatternBase.h @@ -0,0 +1,95 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef FRACTURE_PATTERN_BASE +#define FRACTURE_PATTERN_BASE + +#include "Delaunay3dBase.h" +#include "Delaunay2dBase.h" +#include "CompoundGeometryBase.h" +#include "PxTransform.h" +#include "PxBounds3.h" +#include <PsUserAllocated.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +class Convex; +class Compound; +class CompoundGeometry; + +//------------------------------------------------------------------------------------------ +class FracturePattern : public UserAllocated +{ + friend class SimScene; +protected: + FracturePattern(SimScene* scene); +public: + virtual ~FracturePattern() {} + + void create3dVoronoi(const PxVec3 &dims, int numCells, float biasExp = 1.0f, float maxDist = PX_MAX_F32); + void create2dVoronoi(const PxVec3 &dims, int numCells, float biasExp = 1.0f, int numRays = 0); + + void createRegularCubeMesh(const PxVec3 &dims, float cubeSize); + void createRegular3dVoronoi(const PxVec3 &dims, float pieceSize, float relRandOffset = 0.1f); + void createLocal3dVoronoi(const PxVec3 &dims, int numCells, float radius); + void createGlass(float radius, float thickness, int numSectors, float sectorRand, float firstSegmentSize, float segmentScale, float segmentRand); + void createCrack(const PxVec3 &dims, float spacing, float zRand); + void createCrosses(const PxVec3 &dims, float spacing); + + // radius = 0.0f : complete fracture + // radius > 0.0f : partial (local) fracture + void getCompoundIntersection(const Compound *compound, const PxMat44 &trans, float radius, float minConvexSize, + nvidia::Array<int> &compoundSizes, nvidia::Array<Convex*> &newConvexes) const; + + const CompoundGeometry &getGeometry() { return mGeom; } + +protected: + void addBox(const PxBounds3 &bounds); + void clear(); + void finalize(); + + void getConvexIntersection(const Convex *convex, const PxMat44 &trans, float minConvexSize, int numFitDirections = 3) const; + + SimScene* mScene; + + CompoundGeometry mGeom; + + // cells can have multiple connected convexes + // if this array is empty, each convex is a separate cell + // size of array must be num cells + 1 + nvidia::Array<int> mFirstConvexOfCell; + + PxBounds3 mBounds; + nvidia::Array<float> mConvexVolumes; + + // temporary for intersection computation + mutable nvidia::Array<int> mFirstPiece; + mutable nvidia::Array<bool> mSplitPiece; + struct Piece { + Convex* convex; + int next; + }; + mutable nvidia::Array<Piece> mPieces; +}; + +} +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/IceBoxPruningBase.cpp b/APEX_1.4/module/destructible/fracture/Core/IceBoxPruningBase.cpp new file mode 100644 index 00000000..774d0049 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/IceBoxPruningBase.cpp @@ -0,0 +1,270 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for box pruning. + * \file IceBoxPruning.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + You could use a complex sweep-and-prune as implemented in I-Collide. + You could use a complex hashing scheme as implemented in V-Clip or recently in ODE it seems. + You could use a "Recursive Dimensional Clustering" algorithm as implemented in GPG2. + + Or you could use this. + Faster ? I don't know. Probably not. It would be a shame. But who knows ? + Easier ? Definitely. Enjoy the sheer simplicity. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "IceBoxPruningBase.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. + * \param nb0 [in] number of boxes in the first set + * \param bounds0 [in] list of boxes for the first set + * \param nb1 [in] number of boxes in the second set + * \param bounds1 [in] list of boxes for the second set + * \param pairs [out] list of overlapping pairs + * \param axes [in] projection order (0,2,1 is often best) + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BoxPruning::bipartiteBoxPruning(const nvidia::Array<PxBounds3> &bounds0, const nvidia::Array<PxBounds3> &bounds1, nvidia::Array<uint32_t>& pairs, const Axes& axes) +{ + uint32_t nb0 = bounds0.size(); + uint32_t nb1 = bounds1.size(); + pairs.clear(); + // Checkings + if(nb0 == 0 || nb1 == 0) return false; + + // Catch axes + uint32_t Axis0 = axes.Axis0; + //uint32_t Axis1 = axes.Axis1; + //uint32_t Axis2 = axes.Axis2; + + // Allocate some temporary data + if (mMinPosBounds0.size() < nb0) + mMinPosBounds0.resize(nb0); + if (mMinPosBounds1.size() < nb1) + mMinPosBounds1.resize(nb1); + + // 1) Build main lists using the primary axis + for(uint32_t i=0;i<nb0;i++) mMinPosBounds0[i] = bounds0[i].minimum[Axis0]; + for(uint32_t i=0;i<nb1;i++) mMinPosBounds1[i] = bounds1[i].minimum[Axis0]; + + // 2) Sort the lists + uint32_t* Sorted0 = mRS0.Sort(&mMinPosBounds0[0], nb0).GetRanks(); + uint32_t* Sorted1 = mRS1.Sort(&mMinPosBounds1[0], nb1).GetRanks(); + + // 3) Prune the lists + uint32_t Index0, Index1; + + const uint32_t* const LastSorted0 = &Sorted0[nb0]; + const uint32_t* const LastSorted1 = &Sorted1[nb1]; + const uint32_t* RunningAddress0 = Sorted0; + const uint32_t* RunningAddress1 = Sorted1; + + while(RunningAddress1<LastSorted1 && Sorted0<LastSorted0) + { + Index0 = *Sorted0++; + + while(RunningAddress1<LastSorted1 && mMinPosBounds1[*RunningAddress1]<mMinPosBounds0[Index0]) RunningAddress1++; + + const uint32_t* RunningAddress2_1 = RunningAddress1; + + while(RunningAddress2_1<LastSorted1 && mMinPosBounds1[Index1 = *RunningAddress2_1++]<=bounds0[Index0].maximum[Axis0]) + { + if(bounds0[Index0].intersects(bounds1[Index1])) + { + pairs.pushBack(Index0); + pairs.pushBack(Index1); + } + } + } + + //// + + while(RunningAddress0<LastSorted0 && Sorted1<LastSorted1) + { + Index0 = *Sorted1++; + + while(RunningAddress0<LastSorted0 && mMinPosBounds0[*RunningAddress0]<=mMinPosBounds1[Index0]) RunningAddress0++; + + const uint32_t* RunningAddress2_0 = RunningAddress0; + + while(RunningAddress2_0<LastSorted0 && mMinPosBounds0[Index1 = *RunningAddress2_0++]<=bounds1[Index0].maximum[Axis0]) + { + if(bounds0[Index1].intersects(bounds1[Index0])) + { + pairs.pushBack(Index1); + pairs.pushBack(Index0); + } + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. + * \param nb [in] number of boxes + * \param list [in] list of boxes + * \param pairs [out] list of overlapping pairs + * \param axes [in] projection order (0,2,1 is often best) + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BoxPruning::completeBoxPruning(const nvidia::Array<PxBounds3> &bounds, nvidia::Array<uint32_t> &pairs, const Axes& axes) +{ + uint32_t nb = bounds.size(); + pairs.clear(); + + // Checkings + if(!nb) return false; + + // Catch axes + uint32_t Axis0 = axes.Axis0; + //uint32_t Axis1 = axes.Axis1; + //uint32_t Axis2 = axes.Axis2; + + // Allocate some temporary data + if (mPosList.size() < nb) + mPosList.resize(nb); + + // 1) Build main list using the primary axis + for(uint32_t i=0;i<nb;i++) mPosList[i] = bounds[i].minimum[Axis0]; + + // 2) Sort the list + uint32_t* Sorted = mRS.Sort(&mPosList[0], nb).GetRanks(); + + // 3) Prune the list + const uint32_t* const LastSorted = &Sorted[nb]; + const uint32_t* RunningAddress = Sorted; + uint32_t Index0, Index1; + while(RunningAddress<LastSorted && Sorted<LastSorted) + { + Index0 = *Sorted++; + + while(RunningAddress<LastSorted && mPosList[*RunningAddress++]<mPosList[Index0]); + + const uint32_t* RunningAddress2 = RunningAddress; + + while(RunningAddress2<LastSorted && mPosList[Index1 = *RunningAddress2++]<=bounds[Index0].maximum[Axis0]) + { + if(Index0!=Index1) + { + if(bounds[Index0].intersects(bounds[Index1])) + { + pairs.pushBack(Index0); + pairs.pushBack(Index1); + } + } + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Brute-force versions are kept: +// - to check the optimized versions return the correct list of intersections +// - to check the speed of the optimized code against the brute-force one +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Brute-force bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. + * \param nb0 [in] number of boxes in the first set + * \param bounds0 [in] list of boxes for the first set + * \param nb1 [in] number of boxes in the second set + * \param bounds1 [in] list of boxes for the second set + * \param pairs [out] list of overlapping pairs + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BoxPruning::bruteForceBipartiteBoxTest(const nvidia::Array<PxBounds3> &bounds0, const nvidia::Array<PxBounds3> &bounds1, nvidia::Array<uint32_t>& pairs, const Axes& /*axes*/) +{ + uint32_t nb0 = bounds0.size(); + uint32_t nb1 = bounds1.size(); + pairs.clear(); + + // Checkings + if(!nb0 || !nb1) return false; + + // Brute-force nb0*nb1 overlap tests + for(uint32_t i=0;i<nb0;i++) + { + for(uint32_t j=0;j<nb1;j++) + { + if(bounds0[i].intersects(bounds1[j])) { + pairs.pushBack(i); + pairs.pushBack(j); + } + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. + * \param nb [in] number of boxes + * \param list [in] list of boxes + * \param pairs [out] list of overlapping pairs + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BoxPruning::bruteForceCompleteBoxTest(const nvidia::Array<PxBounds3> &bounds, nvidia::Array<uint32_t> &pairs, const Axes& /*axes*/) +{ + uint32_t nb = bounds.size(); + pairs.clear(); + + // Checkings + if(!nb) return false; + + // Brute-force n(n-1)/2 overlap tests + for(uint32_t i=0;i<nb;i++) + { + for(uint32_t j=i+1;j<nb;j++) + { + if(bounds[i].intersects(bounds[j])) + { + pairs.pushBack(i); + pairs.pushBack(j); + } + } + } + return true; +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/IceBoxPruningBase.h b/APEX_1.4/module/destructible/fracture/Core/IceBoxPruningBase.h new file mode 100644 index 00000000..b7bb9119 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/IceBoxPruningBase.h @@ -0,0 +1,76 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for box pruning. + * \file IceBoxPruning.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEBOXPRUNING_BASE_H__ +#define __ICEBOXPRUNING_BASE_H__ + +//#include "vector" +#include <PsArray.h> +#include "IceRevisitedRadixBase.h" +#include "PxVec3.h" +#include "PxBounds3.h" +#include <PsUserAllocated.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + + struct Axes + { + void set(uint32_t a0, uint32_t a1, uint32_t a2) { + Axis0 = a0; Axis1 = a1; Axis2 = a2; + } + uint32_t Axis0; + uint32_t Axis1; + uint32_t Axis2; + }; + + class BoxPruning : public UserAllocated + { + public: + // Optimized versions + bool completeBoxPruning(const nvidia::Array<PxBounds3> &bounds, nvidia::Array<uint32_t> &pairs, const Axes& axes); + bool bipartiteBoxPruning(const nvidia::Array<PxBounds3> &bounds0, const nvidia::Array<PxBounds3> &bounds1, nvidia::Array<uint32_t>& pairs, const Axes& axes); + + // Brute-force versions + bool bruteForceCompleteBoxTest(const nvidia::Array<PxBounds3> &bounds, nvidia::Array<uint32_t> &pairs, const Axes& axes); + bool bruteForceBipartiteBoxTest(const nvidia::Array<PxBounds3> &bounds0, const nvidia::Array<PxBounds3> &bounds1, nvidia::Array<uint32_t>& pairs, const Axes& axes); + + protected: + nvidia::Array<float> mMinPosBounds0; + nvidia::Array<float> mMinPosBounds1; + nvidia::Array<float> mPosList; + RadixSort mRS0, mRS1; + RadixSort mRS; + }; + +} +} +} + +#endif // __ICEBOXPRUNING_H__ +#endif diff --git a/APEX_1.4/module/destructible/fracture/Core/IceRevisitedRadixBase.cpp b/APEX_1.4/module/destructible/fracture/Core/IceRevisitedRadixBase.cpp new file mode 100644 index 00000000..116ea2c4 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/IceRevisitedRadixBase.cpp @@ -0,0 +1,500 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains source code from the article "Radix Sort Revisited". + * \file IceRevisitedRadix.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Revisited Radix Sort. + * This is my new radix routine: + * - it uses indices and doesn't recopy the values anymore, hence wasting less ram + * - it creates all the histograms in one run instead of four + * - it sorts words faster than dwords and bytes faster than words + * - it correctly sorts negative floating-point values by patching the offsets + * - it automatically takes advantage of temporal coherence + * - multiple keys support is a side effect of temporal coherence + * - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway] + * + * History: + * - 08.15.98: very first version + * - 04.04.00: recoded for the radix article + * - 12.xx.00: code lifting + * - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here) + * - 10.11.01: added local ram support + * - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting...... + * - 01.02.02: - "mIndices" renamed => "mRanks". That's a rank sorter after all. + * - ranks are not "reset" anymore, but implicit on first calls + * + * \class RadixSort + * \author Pierre Terdiman + * \version 1.4 + * \date August, 15, 1998 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* +To do: + - add an offset parameter between two input values (avoid some data recopy sometimes) + - unroll ? asm ? + - 11 bits trick & 3 passes as Michael did + - prefetch stuff the day I have a P3 +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "IceRevisitedRadixBase.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +#define INVALIDATE_RANKS mCurrentSize|=0x80000000 +#define VALIDATE_RANKS mCurrentSize&=0x7fffffff +#define CURRENT_SIZE (mCurrentSize&0x7fffffff) +#define INVALID_RANKS (mCurrentSize&0x80000000) + +#define CHECK_RESIZE(n) \ + if(n!=mPreviousSize) \ + { \ + if(n>mCurrentSize) Resize(n); \ + else ResetRanks(); \ + mPreviousSize = n; \ + } + +#define CREATE_HISTOGRAMS(type, buffer) \ + /* Clear counters/histograms */ \ + \ + memset(mHistogram, 0, 256*4*sizeof(uint32_t)); \ + \ + /* Prepare to count */ \ + uint8_t* p = (uint8_t*)input; \ + uint8_t* pe = &p[nb*4]; \ + uint32_t* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \ + uint32_t* h1= &mHistogram[256]; /* Histogram for second pass */ \ + uint32_t* h2= &mHistogram[512]; /* Histogram for third pass */ \ + uint32_t* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \ + \ + bool AlreadySorted = true; /* Optimism... */ \ + \ + if(INVALID_RANKS) \ + { \ + /* Prepare for temporal coherence */ \ + type* Running = (type*)buffer; \ + type PrevVal = *Running; \ + \ + while(p!=pe) \ + { \ + /* Read input buffer in previous sorted order */ \ + type Val = *Running++;; \ + /* Check whether already sorted or not */ \ + if(Val<PrevVal) { AlreadySorted = false; break; } /* Early out */ \ + /* Update for next iteration */ \ + PrevVal = Val; \ + \ + /* Create histograms */ \ + h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++; \ + } \ + \ + /* If all input values are already sorted, we just have to return and leave the */ \ + /* previous list unchanged. That way the routine may take advantage of temporal */ \ + /* coherence, for example when used to sort transparent faces. */ \ + if(AlreadySorted) \ + { \ + mNbHits++; \ + for(uint32_t i=0;i<nb;i++) mRanks[i] = i; \ + return *this; \ + } \ + } \ + else \ + { \ + /* Prepare for temporal coherence */ \ + uint32_t* Indices = mRanks; \ + type PrevVal = (type)buffer[*Indices]; \ + \ + while(p!=pe) \ + { \ + /* Read input buffer in previous sorted order */ \ + type Val = (type)buffer[*Indices++]; \ + /* Check whether already sorted or not */ \ + if(Val<PrevVal) { AlreadySorted = false; break; } /* Early out */ \ + /* Update for next iteration */ \ + PrevVal = Val; \ + \ + /* Create histograms */ \ + h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++; \ + } \ + \ + /* If all input values are already sorted, we just have to return and leave the */ \ + /* previous list unchanged. That way the routine may take advantage of temporal */ \ + /* coherence, for example when used to sort transparent faces. */ \ + if(AlreadySorted) { mNbHits++; return *this; } \ + } \ + \ + /* Else there has been an early out and we must finish computing the histograms */ \ + while(p!=pe) \ + { \ + /* Create histograms without the previous overhead */ \ + h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++; \ + } + +#define CHECK_PASS_VALIDITY(pass) \ + /* Shortcut to current counters */ \ + uint32_t* CurCount = &mHistogram[pass<<8]; \ + \ + /* Reset flag. The sorting pass is supposed to be performed. (default) */ \ + bool PerformPass = true; \ + \ + /* Check pass validity */ \ + \ + /* If all values have the same byte, sorting is useless. */ \ + /* It may happen when sorting bytes or words instead of dwords. */ \ + /* This routine actually sorts words faster than dwords, and bytes */ \ + /* faster than words. Standard running time (O(4*n))is reduced to O(2*n) */ \ + /* for words and O(n) for bytes. Running time for floats depends on actual values... */ \ + \ + /* Get first byte */ \ + uint8_t UniqueVal = *(((uint8_t*)input)+pass); \ + \ + /* Check that byte's counter */ \ + if(CurCount[UniqueVal]==nb) PerformPass=false; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RadixSort::RadixSort() : mCurrentSize(0), mRanks(NULL), mRanks2(NULL), mTotalCalls(0), mNbHits(0) +{ + // Initialize indices + mRanksSize = 0; + INVALIDATE_RANKS; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RadixSort::~RadixSort() +{ + // Release everything + PX_FREE(mRanks2); + PX_FREE(mRanks); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Resizes the inner lists. + * \param nb [in] new size (number of dwords) + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool RadixSort::Resize(uint32_t nb) +{ + if (mRanksSize >= nb) + return true; + + // Free previously used ram + PX_FREE(mRanks2); + PX_FREE(mRanks); + + // Get some fresh one + mRanks = (uint32_t*) PX_ALLOC(sizeof(uint32_t)*nb,PX_DEBUG_EXP("RT_FRACTURE")); + mRanks2 = (uint32_t*) PX_ALLOC(sizeof(uint32_t)*nb,PX_DEBUG_EXP("RT_FRACTURE")); + + mRanksSize = nb; + + return true; +} + +inline void RadixSort::CheckResize(uint32_t nb) +{ + uint32_t CurSize = CURRENT_SIZE; + if(nb!=CurSize) + { + if(nb>CurSize) Resize(nb); + mCurrentSize = nb; + INVALIDATE_RANKS; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main sort routine. + * This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data. + * \param input [in] a list of integer values to sort + * \param nb [in] number of values to sort, must be < 2^31 + * \param signedvalues [in] true to handle negative values, false if you know your input buffer only contains positive values + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RadixSort& RadixSort::Sort(const uint32_t* input, uint32_t nb, bool signedvalues) +{ + // Checkings + if(!input || !nb || nb&0x80000000) return *this; + + // Stats + mTotalCalls++; + + // Resize lists if needed + CheckResize(nb); + + // Create histograms (counters). Counters for all passes are created in one run. + // Pros: read input buffer once instead of four times + // Cons: mHistogram is 4Kb instead of 1Kb + // We must take care of signed/unsigned values for temporal coherence.... I just + // have 2 code paths even if just a single opcode changes. Self-modifying code, someone? + if(!signedvalues) { CREATE_HISTOGRAMS(uint32_t, input); } + else { CREATE_HISTOGRAMS(int32_t, input); } + + // Compute #negative values involved if needed + uint32_t NbNegativeValues = 0; + if(signedvalues) + { + // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128 + // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte, + // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers. + uint32_t* h3= &mHistogram[768]; + for(uint32_t i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part + } + + // Radix sort, j is the pass number (0=LSB, 3=MSB) + for(uint32_t j=0;j<4;j++) + { + CHECK_PASS_VALIDITY(j); + + // Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is + // not a problem, numbers are correctly sorted anyway. + if(PerformPass) + { + // Should we care about negative values? + if(j!=3 || !signedvalues) + { + // Here we deal with positive values only + + // Create offsets + mOffset[0] = 0; + for(uint32_t i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + } + else + { + // This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place. + + // Create biased offsets, in order for negative numbers to be sorted as well + mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones + for(uint32_t i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + + // Fixing the wrong place for negative values + mOffset[128] = 0; + for(uint32_t i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + } + + // Perform Radix Sort + uint8_t* InputBytes = (uint8_t*)input; + InputBytes += j; + if(INVALID_RANKS) + { + for(uint32_t i=0;i<nb;i++) mRanks2[mOffset[InputBytes[i<<2]]++] = i; + VALIDATE_RANKS; + } + else + { + uint32_t* Indices = mRanks; + uint32_t* IndicesEnd = &mRanks[nb]; + while(Indices!=IndicesEnd) + { + uint32_t id = *Indices++; + mRanks2[mOffset[InputBytes[id<<2]]++] = id; + } + } + + // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. + uint32_t* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp; + } + } + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main sort routine. + * This one is for floating-point values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data. + * \param input [in] a list of floating-point values to sort + * \param nb [in] number of values to sort, must be < 2^31 + * \return Self-Reference + * \warning only sorts IEEE floating-point values + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RadixSort& RadixSort::Sort(const float* input2, uint32_t nb) +{ + // Checkings + if(!input2 || !nb || nb&0x80000000) return *this; + + // Stats + mTotalCalls++; + + uint32_t* input = (uint32_t*)input2; + + // Resize lists if needed + CheckResize(nb); + + // Create histograms (counters). Counters for all passes are created in one run. + // Pros: read input buffer once instead of four times + // Cons: mHistogram is 4Kb instead of 1Kb + // Floating-point values are always supposed to be signed values, so there's only one code path there. + // Please note the floating point comparison needed for temporal coherence! Although the resulting asm code + // is dreadful, this is surprisingly not such a performance hit - well, I suppose that's a big one on first + // generation Pentiums....We can't make comparison on integer representations because, as Chris said, it just + // wouldn't work with mixed positive/negative values.... + { CREATE_HISTOGRAMS(float, input2); } + + // Compute #negative values involved if needed + uint32_t NbNegativeValues = 0; + // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128 + // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte, + // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers. + uint32_t* h3= &mHistogram[768]; + for(uint32_t i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part + + // Radix sort, j is the pass number (0=LSB, 3=MSB) + for(uint32_t j=0;j<4;j++) + { + // Should we care about negative values? + if(j!=3) + { + // Here we deal with positive values only + CHECK_PASS_VALIDITY(j); + + if(PerformPass) + { + // Create offsets + mOffset[0] = 0; + for(uint32_t i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + + // Perform Radix Sort + uint8_t* InputBytes = (uint8_t*)input; + InputBytes += j; + if(INVALID_RANKS) + { + for(uint32_t i=0;i<nb;i++) mRanks2[mOffset[InputBytes[i<<2]]++] = i; + VALIDATE_RANKS; + } + else + { + uint32_t* Indices = mRanks; + uint32_t* IndicesEnd = &mRanks[nb]; + while(Indices!=IndicesEnd) + { + uint32_t id = *Indices++; + mRanks2[mOffset[InputBytes[id<<2]]++] = id; + } + } + + // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. + uint32_t* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp; + } + } + else + { + // This is a special case to correctly handle negative values + CHECK_PASS_VALIDITY(j); + + if(PerformPass) + { + // Create biased offsets, in order for negative numbers to be sorted as well + mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones + for(uint32_t i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + + // We must reverse the sorting order for negative numbers! + mOffset[255] = 0; + for(uint32_t i=0;i<127;i++) mOffset[254-i] = mOffset[255-i] + CurCount[255-i]; // Fixing the wrong order for negative values + for(uint32_t i=128;i<256;i++) mOffset[i] += CurCount[i]; // Fixing the wrong place for negative values + + // Perform Radix Sort + if(INVALID_RANKS) + { + for(uint32_t i=0;i<nb;i++) + { + uint32_t Radix = input[i]>>24; // Radix byte, same as above. AND is useless here (uint32_t). + // ### cmp to be killed. Not good. Later. + if(Radix<128) mRanks2[mOffset[Radix]++] = i; // Number is positive, same as above + else mRanks2[--mOffset[Radix]] = i; // Number is negative, flip the sorting order + } + VALIDATE_RANKS; + } + else + { + for(uint32_t i=0;i<nb;i++) + { + uint32_t Radix = input[mRanks[i]]>>24; // Radix byte, same as above. AND is useless here (uint32_t). + // ### cmp to be killed. Not good. Later. + if(Radix<128) mRanks2[mOffset[Radix]++] = mRanks[i]; // Number is positive, same as above + else mRanks2[--mOffset[Radix]] = mRanks[i]; // Number is negative, flip the sorting order + } + } + // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. + uint32_t* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp; + } + else + { + // The pass is useless, yet we still have to reverse the order of current list if all values are negative. + if(UniqueVal>=128) + { + if(INVALID_RANKS) + { + // ###Possible? + for(uint32_t i=0;i<nb;i++) mRanks2[i] = nb-i-1; + VALIDATE_RANKS; + } + else + { + for(uint32_t i=0;i<nb;i++) mRanks2[i] = mRanks[nb-i-1]; + } + + // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. + uint32_t* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp; + } + } + } + } + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the ram used. + * \return memory used in bytes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +uint32_t RadixSort::GetUsedRam() const +{ + uint32_t UsedRam = sizeof(RadixSort); + + UsedRam += 2*CURRENT_SIZE*sizeof(uint32_t); // 2 lists of indices + return UsedRam; +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/IceRevisitedRadixBase.h b/APEX_1.4/module/destructible/fracture/Core/IceRevisitedRadixBase.h new file mode 100644 index 00000000..a7e9dede --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/IceRevisitedRadixBase.h @@ -0,0 +1,84 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains source code from the article "Radix Sort Revisited". + * \file IceRevisitedRadix.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICERADIXSORT_BASE_H__ +#define __ICERADIXSORT_BASE_H__ + +#include "PxSimpleTypes.h" +#include "ApexUsingNamespace.h" +#include <PsUserAllocated.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + + class RadixSort : public UserAllocated + { + public: + // Constructor/Destructor + RadixSort(); + virtual ~RadixSort(); + // Sorting methods + RadixSort& Sort(const uint32_t* input, uint32_t nb, bool signedvalues=true); + RadixSort& Sort(const float* input, uint32_t nb); + + //! Access to results. mRanks is a list of indices in sorted order, i.e. in the order you may further process your data + inline uint32_t* GetRanks() const { return mRanks; } + + //! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want. + inline uint32_t* GetRecyclable() const { return mRanks2; } + + // Stats + uint32_t GetUsedRam() const; + //! Returns the total number of calls to the radix sorter. + inline uint32_t GetNbTotalCalls() const { return mTotalCalls; } + //! Returns the number of premature exits due to temporal coherence. + inline uint32_t GetNbHits() const { return mNbHits; } + + private: + + uint32_t mHistogram[256*4]; //!< Counters for each byte + uint32_t mOffset[256]; //!< Offsets (nearly a cumulative distribution function) + uint32_t mCurrentSize; //!< Current size of the indices list + + uint32_t mRanksSize; + uint32_t* mRanks; //!< Two lists, swapped each pass + uint32_t* mRanks2; + // Stats + uint32_t mTotalCalls; + uint32_t mNbHits; + // Internal methods + void CheckResize(uint32_t nb); + bool Resize(uint32_t nb); + }; + +} +} +} + +#endif // __ICERADIXSORT_H__ +#endif diff --git a/APEX_1.4/module/destructible/fracture/Core/IslandDetectorBase.cpp b/APEX_1.4/module/destructible/fracture/Core/IslandDetectorBase.cpp new file mode 100644 index 00000000..387d5734 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/IslandDetectorBase.cpp @@ -0,0 +1,440 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "IslandDetectorBase.h" +#include "ConvexBase.h" +#include "CompoundGeometryBase.h" +#include "PsSort.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace nvidia; + +// ----------------------------------------------------------------------------- +IslandDetector::IslandDetector(SimScene* scene): + mScene(scene) +{ + mNeigborPairsDirty = true; +} + +// ----------------------------------------------------------------------------- +void IslandDetector::detect(const nvidia::Array<Convex*> &convexes, bool computeFaceCoverage) +{ + createConnectivity(convexes, computeFaceCoverage); + addOverlapConnectivity(convexes); + createIslands(); + mNeigborPairsDirty = true; +} + +// ----------------------------------------------------------------------------- +bool IslandDetector::touching(const Convex *c0, int faceNr, const Convex *c1, float eps) +{ + const Convex::Face &face = c0->getFaces()[(uint32_t)faceNr]; + const nvidia::Array<int> &indices = c0->getIndices(); + const nvidia::Array<PxVec3> &verts = c0->getVertices(); + const nvidia::Array<PxPlane> &planes = c1->getPlanes(); + + for (int i = 0; i < face.numIndices; i++) { + PxVec3 v = verts[(uint32_t)indices[uint32_t(face.firstIndex + i)]]; + v = v + c0->getMaterialOffset() - c1->getMaterialOffset(); // transform to c1 + bool inside = true; + for (uint32_t j = 0; j < planes.size(); j++) { + const PxPlane &p = planes[j]; + if (p.n.dot(v) - p.d > eps) { + inside = false; + break; + } + } + if (inside) + return true; + } + return false; +} + +// ----------------------------------------------------------------------------- +void IslandDetector::createConnectivity(const nvidia::Array<Convex*> &convexes, bool computeFaceCoverage) +{ + mFaces.clear(); + Face face; + int globalNr = 0; + + for (uint32_t i = 0; i < convexes.size(); i++) { + const Convex *c = convexes[i]; + face.convexNr = (int32_t)i; + const nvidia::Array<PxPlane> &planes = c->getPlanes(); + for (uint32_t j = 0; j < planes.size(); j++) { + globalNr++; + if (c->getFaces()[j].flags & CompoundGeometry::FF_OBJECT_SURFACE) + continue; + face.faceNr = (int32_t)j; + face.globalNr = globalNr-1; + float d = planes[j].d; + d = d + c->getMaterialOffset().dot(planes[j].n); // transform to global + face.orderVal = fabsf(d); + mFaces.pushBack(face); + } + } + mFaceCoverage.clear(); + + if (computeFaceCoverage) { + mFaceCoverage.resize((uint32_t)globalNr, 0.0f); + } + + shdfnd::sort(mFaces.begin(), mFaces.size()); + + float eps = 1e-3f; + mFirstNeighbor.clear(); + mFirstNeighbor.resize(convexes.size(), -1); + mNeighbors.clear(); + Neighbor n; + + for (uint32_t i = 0; i < mFaces.size(); i++) { + Face &fi = mFaces[i]; + uint32_t j = i+1; + while (j < mFaces.size() && mFaces[j].orderVal - fi.orderVal < eps) { + Face &fj = mFaces[j]; + j++; + + if (fi.convexNr == fj.convexNr) + continue; + + PxPlane pi = convexes[(uint32_t)fi.convexNr]->getPlanes()[(uint32_t)fi.faceNr]; + if (convexes[(uint32_t)fi.convexNr]->isGhostConvex()) + pi.n = -pi.n; + + PxPlane pj = convexes[(uint32_t)fj.convexNr]->getPlanes()[(uint32_t)fj.faceNr]; + if (convexes[(uint32_t)fj.convexNr]->isGhostConvex()) + pj.n = -pj.n; + + if (pi.n.dot(pj.n) > -1.0f + eps) + continue; // need to be opposite + + if ( + touching(convexes[(uint32_t)fi.convexNr], fi.faceNr, convexes[(uint32_t)fj.convexNr], eps) || + touching(convexes[(uint32_t)fj.convexNr], fj.faceNr, convexes[(uint32_t)fi.convexNr], eps)) + { + n.area = 0.5f*( fabsf(faceArea(convexes[(uint32_t)fi.convexNr], fi.faceNr)) + fabsf(faceArea(convexes[(uint32_t)fj.convexNr], fj.faceNr))); + if (computeFaceCoverage) { + float area = faceIntersectionArea(convexes[(uint32_t)fi.convexNr], fi.faceNr, convexes[(uint32_t)fj.convexNr], fj.faceNr); + mFaceCoverage[(uint32_t)fi.globalNr] += area; + mFaceCoverage[(uint32_t)fj.globalNr] += area; + } + + n.convexNr = fj.convexNr; + n.next = mFirstNeighbor[(uint32_t)fi.convexNr]; + mFirstNeighbor[(uint32_t)fi.convexNr] = (int32_t)mNeighbors.size(); + mNeighbors.pushBack(n); + + n.convexNr = fi.convexNr; + n.next = mFirstNeighbor[(uint32_t)fj.convexNr]; + mFirstNeighbor[(uint32_t)fj.convexNr] = (int32_t)mNeighbors.size(); + mNeighbors.pushBack(n); + } + } + } + + if (computeFaceCoverage) { + uint32_t globalNr = 0; + + for (uint32_t i = 0; i < convexes.size(); i++) { + const Convex *c = convexes[i]; + int numFaces = (int32_t)c->getPlanes().size(); + for (int j = 0; j < numFaces; j++) { + float total = faceArea(c, j); + if (total != 0.0f) + mFaceCoverage[globalNr] /= total; + globalNr++; + } + } + } + + mNeigborPairsDirty = true; +} + +// ----------------------------------------------------------------------------- +bool IslandDetector::axisOverlap(const Convex* c0, const Convex* c1, PxVec3 &dir) +{ + float off0 = c0->getMaterialOffset().dot(dir); + float off1 = c1->getMaterialOffset().dot(dir); + const nvidia::Array<PxVec3> &verts0 = c0->getVertices(); + const nvidia::Array<PxVec3> &verts1 = c1->getVertices(); + if (verts0.empty() || verts1.empty()) + return false; + + float d0 = dir.dot(verts0[0]) + off0; + float d1 = dir.dot(verts1[0]) + off1; + if (d0 < d1) { + float max0 = d0; + for (uint32_t i = 1; i < verts0.size(); i++) { + float d = verts0[i].dot(dir) + off0; + if (d > max0) max0 = d; + } + for (uint32_t i = 0; i < verts1.size(); i++) { + float d = verts1[i].dot(dir) + off1; + if (d < max0) + return true; + } + } + else { + float max1 = d1; + for (uint32_t i = 1; i < verts1.size(); i++) { + float d = verts1[i].dot(dir) + off1; + if (d > max1) max1 = d; + } + for (uint32_t i = 0; i < verts0.size(); i++) { + float d = verts0[i].dot(dir) + off0; + if (d < max1) + return true; + } + } + return false; +} + +// ----------------------------------------------------------------------------- +bool IslandDetector::overlap(const Convex* c0, const Convex* c1) +{ + PxVec3 off0 = c0->getMaterialOffset(); + PxVec3 off1 = c1->getMaterialOffset(); + PxVec3 center0 = c0->getCenter() + off0; + PxVec3 center1 = c1->getCenter() + off1; + PxVec3 dir = center1 - center0; + + if (!axisOverlap(c0, c1, dir)) + return false; + + // todo: test other axes + + return true; +} + +// ----------------------------------------------------------------------------- +void IslandDetector::addOverlapConnectivity(const nvidia::Array<Convex*> &convexes) +{ + mBounds.resize(convexes.size()); + PxVec3 off; + + for (uint32_t i = 0; i < convexes.size(); i++) { + const Convex *c = convexes[i]; + const PxBounds3 &cb = c->getBounds(); + off = c->getMaterialOffset(); + + PxBounds3 &b = mBounds[i]; + b.minimum = cb.minimum + off; + b.maximum = cb.maximum + off; + } + + // broad phase with AABBs + Axes axes; + axes.set(0,2,1); + mBoxPruning.completeBoxPruning(mBounds, mPairs, axes); + + for (uint32_t i = 0; i < mPairs.size(); i += 2) { + uint32_t i0 = mPairs[i]; + uint32_t i1 = mPairs[i+1]; + + if (convexes[i0]->getModelIslandNr() == convexes[i1]->getModelIslandNr()) + continue; + + // already detected? + bool found = false; + int nr = mFirstNeighbor[i0]; + while (nr >= 0) { + Neighbor &n = mNeighbors[(uint32_t)nr]; + nr = n.next; + if (n.convexNr == (int32_t)i1) { + found = true; + break; + } + } + if (found) + continue; + + if (overlap(convexes[i0], convexes[i1])) { + Neighbor n; + + // add link + n.convexNr = (int32_t)i0; + n.next = mFirstNeighbor[i1]; + mFirstNeighbor[i1] = (int32_t)mNeighbors.size(); + mNeighbors.pushBack(n); + + n.convexNr = (int32_t)i1; + n.next = mFirstNeighbor[i0]; + mFirstNeighbor[i0] = (int32_t)mNeighbors.size(); + mNeighbors.pushBack(n); + } + + } +} + +// ----------------------------------------------------------------------------- +void IslandDetector::createIslands() +{ + uint32_t numConvexes = mFirstNeighbor.size(); + mIslands.clear(); + mIslandConvexes.clear(); + + Island island; + + // color convexes + mColors.clear(); + mColors.resize(numConvexes,-1); + int color = -1; + + for (uint32_t i = 0; i < numConvexes; i++) { + if (mColors[i] >= 0) + continue; + mQueue.clear(); + mQueue.pushBack((int32_t)i); + color++; + island.firstNr = (int32_t)mIslandConvexes.size(); + island.size = 0; + + while (mQueue.size() > 0) { + int convexNr = mQueue[mQueue.size()-1]; + mQueue.popBack(); + if (mColors[(uint32_t)convexNr] >= 0) + continue; + mColors[(uint32_t)convexNr] = color; + mIslandConvexes.pushBack(convexNr); + island.size++; + + int nr = mFirstNeighbor[(uint32_t)convexNr]; + while (nr >= 0) { + int adj = mNeighbors[(uint32_t)nr].convexNr; + nr = mNeighbors[(uint32_t)nr].next; + if (mColors[(uint32_t)adj] < 0) + mQueue.pushBack(adj); + } + } + mIslands.pushBack(island); + } +} + +// ----------------------------------------------------------------------------- +float IslandDetector::faceArea(const Convex *c, int faceNr) +{ + const Convex::Face &face = c->getFaces()[(uint32_t)faceNr]; + const nvidia::Array<PxVec3> &verts = c->getVertices(); + const nvidia::Array<int> &indices = c->getIndices(); + + float area = 0.0f; + PxVec3 p0 = verts[(uint32_t)indices[(uint32_t)face.firstIndex]]; + for (int i = 1; i < face.numIndices-1; i++) { + PxVec3 p1 = verts[(uint32_t)indices[uint32_t(face.firstIndex+i)]]; + PxVec3 p2 = verts[(uint32_t)indices[uint32_t(face.firstIndex+i+1)]]; + area += (p1-p0).cross(p2-p0).magnitude(); + } + return 0.5f * area; +} + +// ----------------------------------------------------------------------------- +float IslandDetector::faceIntersectionArea(const Convex *c0, int faceNr0, const Convex *c1, int faceNr1) +{ + // vertices of the first face + mCutPolys[0].clear(); + mCutPolys[1].clear(); + + const Convex::Face &face0 = c0->getFaces()[(uint32_t)faceNr0]; + const nvidia::Array<PxVec3> &verts0 = c0->getVertices(); + const nvidia::Array<int> &indices0 = c0->getIndices(); + + const Convex::Face &face1 = c1->getFaces()[(uint32_t)faceNr1]; + const nvidia::Array<PxVec3> &verts1 = c1->getVertices(); + const nvidia::Array<int> &indices1 = c1->getIndices(); + + for (int i = 0; i < face0.numIndices; i++) + mCutPolys[0].pushBack(verts0[(uint32_t)indices0[uint32_t(face0.firstIndex + i)]]); + + const PxVec3 &n0 = c0->getPlanes()[(uint32_t)faceNr0].n; + + // cut face 0 polygon with face 1 polygon + for (int i = 0; i < face1.numIndices; i++) { + const PxVec3 &p0 = verts1[(uint32_t)indices1[uint32_t(face1.firstIndex + (i+1)%face1.numIndices)]]; + const PxVec3 &p1 = verts1[(uint32_t)indices1[uint32_t(face1.firstIndex + i)]]; + PxVec3 n = (p1-p0).cross(n0); + float d = n.dot(p0); + + nvidia::Array<PxVec3> &currPoly = mCutPolys[uint32_t(i%2)]; + nvidia::Array<PxVec3> &newPoly = mCutPolys[uint32_t(1 - (i%2))]; + newPoly.clear(); + + uint32_t num = currPoly.size(); + for (uint32_t j = 0; j < num; j++) { + PxVec3 &q0 = currPoly[j]; + PxVec3 &q1 = currPoly[(j+1) % num]; + + bool inside0 = q0.dot(n) < d; + bool inside1 = q1.dot(n) < d; + + if (inside0) + newPoly.pushBack(currPoly[j]); // point inside -> keep + + if (inside0 != inside1) { // intersection + float s = (d - q0.dot(n)) / (q1-q0).dot(n); + PxVec3 ps = q0 + s*(q1-q0); + newPoly.pushBack(ps); + } + } + } + + // measure area + float area = 0.0f; + nvidia::Array<PxVec3> &currPoly = mCutPolys[face1.numIndices%2]; + if (currPoly.size() < 3) + return 0.0f; + + PxVec3 &p0 = currPoly[0]; + for (uint32_t i = 1; i < currPoly.size()-1; i++) { + PxVec3 &p1 = currPoly[i]; + PxVec3 &p2 = currPoly[i+1]; + area += (p1-p0).cross(p2-p0).magnitude(); + } + return 0.5f * area; +} + +// ----------------------------------------------------------------------------- +const nvidia::Array<IslandDetector::Edge> &IslandDetector::getNeighborEdges() +{ + if (mNeigborPairsDirty) { + Edge e; + mNeighborPairs.clear(); + for (uint32_t i = 0; i < mFirstNeighbor.size(); i++) { + int nr = mFirstNeighbor[i]; + e.n0 = (int32_t)i; + while (nr >= 0) { + Neighbor &n = mNeighbors[(uint32_t)nr]; + nr = n.next; + if (n.convexNr > (int32_t)i) { + e.n1 = n.convexNr; + e.area = n.area; + mNeighborPairs.pushBack(e); + //mNeighborPairs.pushBack(i); + //mNeighborPairs.pushBack(n.convexNr); + } + } + } + mNeigborPairsDirty = false; + } + return mNeighborPairs; +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/IslandDetectorBase.h b/APEX_1.4/module/destructible/fracture/Core/IslandDetectorBase.h new file mode 100644 index 00000000..d13ed849 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/IslandDetectorBase.h @@ -0,0 +1,118 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef ISLAND_DETECTOR_BASE_H +#define ISLAND_DETECTOR_BASE_H + +// Matthias Muller-Fischer + +#include <PxVec3.h> +#include <PsArray.h> +#include "IceBoxPruningBase.h" +#include <PsUserAllocated.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +class SimScene; +class Convex; + +// --------------------------------------------------------------------------------------- +class IslandDetector : public UserAllocated { + friend class SimScene; +public: + // singleton pattern + //static IslandDetector* getInstance(); + //static void destroyInstance(); + + void detect(const nvidia::Array<Convex*> &convexes, bool computeFaceCoverage); + + struct Island { + int size; + int firstNr; + }; + const nvidia::Array<Island> &getIslands() { return mIslands; } + const nvidia::Array<int> &getIslandConvexes() { return mIslandConvexes; } + + const nvidia::Array<float> &getFaceCoverage() { return mFaceCoverage; } + + class Edge{ + public: + int n0, n1; + float area; + }; + const nvidia::Array<Edge> &getNeighborEdges(); + +protected: + IslandDetector(SimScene* scene); + virtual ~IslandDetector(){} + + void createConnectivity(const nvidia::Array<Convex*> &convexes, bool computeFaceCoverage); + static bool touching(const Convex *c0, int faceNr, const Convex *c1, float eps); + void createIslands(); + + float faceArea(const Convex *c, int faceNr); + float faceIntersectionArea(const Convex *c0, int faceNr0, const Convex *c1, int faceNr1); + + bool axisOverlap(const Convex* c0, const Convex* c1, PxVec3 &dir); + bool overlap(const Convex* c0, const Convex* c1); + + void addOverlapConnectivity(const nvidia::Array<Convex*> &convexes); + + SimScene* mScene; + + // auxiliary + nvidia::Array<int> mFirstNeighbor; + struct Neighbor { + int convexNr; + int next; + float area; + }; + nvidia::Array<Neighbor> mNeighbors; + struct Face { + int convexNr; + int faceNr; + float orderVal; + int globalNr; + bool operator < (const Face &f) const { return orderVal < f.orderVal; } + }; + bool mNeigborPairsDirty; + nvidia::Array<Edge> mNeighborPairs; + nvidia::Array<float> mNeighborAreaPairs; + nvidia::Array<Face> mFaces; + nvidia::Array<int> mColors; + nvidia::Array<int> mQueue; + + nvidia::Array<PxVec3> mCutPolys[2]; + + // overlaps + BoxPruning mBoxPruning; + nvidia::Array<PxBounds3> mBounds; + nvidia::Array<uint32_t> mPairs; + + // output + nvidia::Array<Island> mIslands; + nvidia::Array<int> mIslandConvexes; + nvidia::Array<float> mFaceCoverage; +}; + +} +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/MeshBase.cpp b/APEX_1.4/module/destructible/fracture/Core/MeshBase.cpp new file mode 100644 index 00000000..fecbd5d2 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/MeshBase.cpp @@ -0,0 +1,225 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include <PxBounds3.h> + +#include "MeshBase.h" +#include <algorithm> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace nvidia; + +// ---------------------------------------------------------------------- +void Mesh::updateNormals() +{ + if (mVertices.empty()) + return; + + PxVec3 zero(0.0f, 0.0f, 0.0f); + + mNormals.resize(mVertices.size()); + for (uint32_t i = 0; i < mNormals.size(); i++) + mNormals[i] = zero; + PxVec3 n; + + uint32_t *idx = &mIndices[0]; + uint32_t numTriangles = mIndices.size() / 3; + for (uint32_t i = 0; i < numTriangles; i++) { + uint32_t i0 = *idx++; + uint32_t i1 = *idx++; + uint32_t i2 = *idx++; + n = (mVertices[i1] - mVertices[i0]).cross(mVertices[i2] - mVertices[i0]); + mNormals[i0] += n; + mNormals[i1] += n; + mNormals[i2] += n; + } + for (uint32_t i = 0; i < mNormals.size(); i++) { + if (!mNormals[i].isZero()) + mNormals[i].normalize(); + } +} + +// ------------------------------------------------------------------------------ +void Mesh::getBounds(PxBounds3 &bounds, int subMeshNr) const +{ + bounds.setEmpty(); + if (subMeshNr < 0 || subMeshNr >= (int)mSubMeshes.size()) { + for (uint32_t i = 0; i < mVertices.size(); i++) + bounds.include(mVertices[i]); + } + else { + const SubMesh &sm = mSubMeshes[(uint32_t)subMeshNr]; + for (int i = 0; i < sm.numIndices; i++) { + bounds.include(mVertices[(uint32_t)mIndices[uint32_t(sm.firstIndex + i)]]); + } + } +} + +// ------------------------------------------------------------------------------ +void Mesh::normalize(const PxVec3 ¢er, float diagonal) +{ + if (mVertices.size() < 3) + return; + + PxBounds3 bounds; + getBounds(bounds); + + float s = diagonal / bounds.getDimensions().magnitude(); + PxVec3 c = 0.5f * (bounds.minimum + bounds.maximum); + + for (uint32_t i = 0; i < mVertices.size(); i++) + mVertices[i] = center + (mVertices[i] - c) * s; +} + +// ------------------------------------------------------------------------------ +void Mesh::scale(float diagonal) +{ + if (mVertices.size() < 3) + return; + + PxBounds3 bounds; + getBounds(bounds); + + float s = diagonal / bounds.getDimensions().magnitude(); + for (uint32_t i = 0; i < mVertices.size(); i++) + mVertices[i] *= s; +} + +// -------------------------------------------------------------------------------------------- +struct IdEdge { + void set(uint32_t &i0, uint32_t &i1, int faceNr, int edgeNr) { + if (i0 < i1) { this->i0 = i0; this->i1 = i1; } + else { this->i0 = i1; this->i1 = i0; } + this->faceNr = faceNr; this->edgeNr = edgeNr; + } + bool operator < (const IdEdge &e) const { + if (i0 < e.i0) return true; + if (i0 == e.i0 && i1 < e.i1) return true; + return false; + } + bool operator == (const IdEdge &e) const { return i0 == e.i0 && i1 == e.i1; } + uint32_t i0,i1; + int faceNr, edgeNr; +}; + +// ------------------------------------------------------------------------------ +bool Mesh::computeNeighbors() +{ + uint32_t numTris = mIndices.size() / 3; + + nvidia::Array<IdEdge> edges(3*numTris); + + for (uint32_t i = 0; i < numTris; i++) { + for (uint32_t j = 0; j < 3; j++) + edges[3*i+j].set(mIndices[3*i+j], mIndices[3*i + (j+1)%3], (int32_t)i, (int32_t)j); + } + std::sort(edges.begin(), edges.end()); + + mNeighbors.clear(); + mNeighbors.resize(mIndices.size(), -1); + bool manifold = true; + uint32_t i = 0; + while (i < edges.size()) { + IdEdge &e0 = edges[i]; + i++; + if (i < edges.size() && edges[i] == e0) { + IdEdge &e1 = edges[i]; + mNeighbors[uint32_t(3* e0.faceNr + e0.edgeNr)] = e1.faceNr; + mNeighbors[uint32_t(3* e1.faceNr + e1.edgeNr)] = e0.faceNr; + i++; + } + while (i < edges.size() && edges[i] == e0) { + manifold = false; + i++; + } + } + return manifold; +} + +// -------------------------------------------------------------------------------------------- +struct PosEdge { + // not using indices for edge match but positions + // so duplicated vertices are handled as one vertex + static bool smaller(const PxVec3 &v0, const PxVec3 &v1) { + if (v0.x < v1.x) return true; + if (v0.x > v1.x) return false; + if (v0.y < v1.y) return true; + if (v0.y > v1.y) return false; + return (v0.z < v1.z); + } + void set(const PxVec3 &v0, const PxVec3 &v1, int faceNr, int edgeNr) { + if (smaller(v0,v1)) { this->v0 = v0; this->v1 = v1; } + else { this->v0 = v1; this->v1 = v0; } + this->faceNr = faceNr; this->edgeNr = edgeNr; + } + bool operator < (const PosEdge &e) const { + if (smaller(v0, e.v0)) return true; + if (v0 == e.v0 && smaller(v1, e.v1)) return true; + return false; + } + bool operator == (const PosEdge &e) const { return v0 == e.v0 && v1 == e.v1; } + PxVec3 v0,v1; + int faceNr, edgeNr; +}; + +// ------------------------------------------------------------------------------ +bool Mesh::computeWeldedNeighbors() +{ + uint32_t numTris = mIndices.size() / 3; + nvidia::Array<PosEdge> edges(3*numTris); + + for (uint32_t i = 0; i < numTris; i++) { + for (uint32_t j = 0; j < 3; j++) + edges[3*i+j].set(mVertices[(uint32_t)mIndices[3*i+j]], mVertices[(uint32_t)mIndices[3*i + (j+1)%3]], (int32_t)i, (int32_t)j); + } + std::sort(edges.begin(), edges.end()); + + mNeighbors.clear(); + mNeighbors.resize(mIndices.size(), -1); + bool manifold = true; + uint32_t i = 0; + while (i < edges.size()) { + PosEdge &e0 = edges[i]; + i++; + if (i < edges.size() && edges[i] == e0) { + PosEdge &e1 = edges[i]; + mNeighbors[uint32_t(3* e0.faceNr + e0.edgeNr)] = e1.faceNr; + mNeighbors[uint32_t(3* e1.faceNr + e1.edgeNr)] = e0.faceNr; + i++; + } + while (i < edges.size() && edges[i] == e0) { + manifold = false; + i++; + } + } + return manifold; +} + +void Mesh::flipV() +{ + for(uint32_t i = 0; i < mTexCoords.size(); i++) + { + mTexCoords[i].y = 1.0f - mTexCoords[i].y; + } +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/MeshBase.h b/APEX_1.4/module/destructible/fracture/Core/MeshBase.h new file mode 100644 index 00000000..db4617c4 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/MeshBase.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef MESH_BASE +#define MESH_BASE + +#include <PxVec3.h> +#include <PxVec2.h> +#include <PsArray.h> +#include <PsUserAllocated.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +// ----------------------------------------------------------------------------------- +class Mesh : public UserAllocated +{ +public: + Mesh() {}; + virtual ~Mesh() {}; + + const nvidia::Array<PxVec3> &getVertices() const { return mVertices; } + const nvidia::Array<PxVec3> &getNormals() const { return mNormals; } + const nvidia::Array<PxVec2> &getTexCoords() const { return mTexCoords; } + const nvidia::Array<uint32_t> &getIndices() const { return mIndices; } + const nvidia::Array<int> &getNeighbors() const { return mNeighbors; } + + struct SubMesh { + void init() { /*name = "";*/ firstIndex = -1; numIndices = 0; } + //std::string name; + int firstIndex; + int numIndices; + }; + + const nvidia::Array<SubMesh> &getSubMeshes() const { return mSubMeshes; } + + void normalize(const PxVec3 ¢er, float diagonal); + void scale(float diagonal); + void getBounds(PxBounds3 &bounds, int subMeshNr = -1) const; + + void flipV(); // flips v values to hand coordinate system change (Assumes normalized coordinates) + + bool computeNeighbors(); + bool computeWeldedNeighbors(); + +protected: + void clear(); + void updateNormals(); + + nvidia::Array<PxVec3> mVertices; + nvidia::Array<PxVec3> mNormals; + nvidia::Array<PxVec2> mTexCoords; + + nvidia::Array<SubMesh> mSubMeshes; + nvidia::Array<uint32_t> mIndices; + nvidia::Array<int> mNeighbors; +}; + +} +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/MeshClipperBase.cpp b/APEX_1.4/module/destructible/fracture/Core/MeshClipperBase.cpp new file mode 100644 index 00000000..cccbb023 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/MeshClipperBase.cpp @@ -0,0 +1,1439 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "MeshClipperBase.h" +#include "PsSort.h" +#include "ConvexBase.h" +#include <PxAssert.h> + +#define DEBUG 0 +#if DEBUG +#include <stdio.h> +#else +#define printf(...) +#define fwrite(...) +#define fread(...) +#define fopen(...) +#define fclose(...) +#endif + +#include "SimSceneBase.h" + +#pragma warning(disable:4127) + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace nvidia; + +int vecFloor(float f ) { return (int)::floorf(f); } + +#define DUMP_PATH "c:\\meshClipDump.bin" + +// ----------------------------------------------------------------------------- +MeshClipper::MeshClipper(SimScene* scene) +{ + mScene = scene; + mMeshConvex = NULL; + mClipConvex = NULL; + mDumpOnError = false; +} + +// ----------------------------------------------------------------------------- +void MeshClipper::Mesh::clear() +{ + vertices.clear(); + normals.clear(); + tangents.clear(); + texCoords.clear(); + polyStarts.resize(1, 0); + polyIndices.clear(); + polyNeighbors.clear(); +} + +// ----------------------------------------------------------------------------- +//PxVec3 MeshClipper::conv(const Vec3 &v) +//{ +// return PxVec3((float)v.x, (float)v.y, (float)v.z); +//} +// +//Vec3 MeshClipper::conv(const PxVec3 &v) +//{ +// return Vec3((VecReal)v.x, (VecReal)v.y, (VecReal)v.z); +//} +// +//Plane MeshClipper::conv(const PxPlane &p) +//{ +// return Plane(conv(p.n), VecReal(p.d)); +//} +// +//Transform MeshClipper::conv(const PxTransform &t) +//{ +// return Transform(conv(t.p), Quat(t.q.x, t.q.y, t.q.z, t.q.w)); +//} + +// ----------------------------------------------------------------------------- +int MeshClipper::getNumMeshes() +{ + if (mOutMeshes.size() == 1) // no islands + return 1; + else + return (int32_t)mOutMeshes.size()-1; +} + +// ----------------------------------------------------------------------------- +const MeshClipper::Mesh& MeshClipper::getMesh(int meshNr) +{ + if (mOutMeshes.size() == 1) // no islands + return mOutMeshes[0]; + else + return mOutMeshes[1 + (uint32_t)meshNr]; +} + +// ----------------------------------------------------------------------------- +void MeshClipper::init(const Convex *meshConvex) +{ + if (!meshConvex->hasExplicitVisMesh()) { + mMeshConvex = NULL; + return; + } + + mMeshConvex = meshConvex; + const nvidia::Array<PxVec3> &verts = mMeshConvex->getVisVertices(); + mMeshVertices.resize(verts.size()); + for (uint32_t i = 0; i < verts.size(); i++) + mMeshVertices[i] = verts[i]; + + PxVec3 center(0.0, 0.0, 0.0); + for (uint32_t i = 0; i < mMeshVertices.size(); i++) + center += mMeshVertices[i]; + center /= (float)mMeshVertices.size(); + + for (uint32_t i = 0; i < mMeshVertices.size(); i++) { + mMeshVertices[i] = center + (mMeshVertices[i] - center) * 1.001f; + } + + const nvidia::Array<int> &meshPolyStarts = mMeshConvex->getVisPolyStarts(); + const nvidia::Array<int> &meshPolyIndices = mMeshConvex->getVisPolyIndices(); + uint32_t numPolys = meshPolyStarts.size()-1; + + mPolyBounds.resize(numPolys); + for (uint32_t i = 0; i < numPolys; i++) { + int first = meshPolyStarts[i]; + int last = meshPolyStarts[i+1]; + mPolyBounds[i].setEmpty(); + for (int k = first; k < last; k++) + mPolyBounds[i].include(mMeshVertices[(uint32_t)meshPolyIndices[(uint32_t)k]]); + } + + createGrid(); +} + +// -------------------------------------------------------------------------------------------- +void MeshClipper::createGrid() +{ + const uint32_t minGridPolys = 1000; + + uint32_t numPolys = mPolyBounds.size(); + mGridFirstPoly.clear(); + + if (numPolys < minGridPolys) + return; + + // determine grid dimensions + PxBounds3 meshBounds; + meshBounds.setEmpty(); + for (uint32_t i = 0; i < mMeshVertices.size(); i++) + meshBounds.include(mMeshVertices[i]); + PxVec3 meshExtent = meshBounds.maximum - meshBounds.minimum; + + // number of cells in the order of num polygons +// int targetNumCells = numPolys; + float targetNumCells = 10000; + float s3 = meshExtent.x * meshExtent.y * meshExtent.z / (float)targetNumCells; + mGridSpacing = PxPow((float)s3, 1.0f/3.0f); + + mGridBounds.minimum = meshBounds.minimum; + mGridNumX = vecFloor(meshExtent.x / mGridSpacing) + 1; + mGridNumY = vecFloor(meshExtent.y / mGridSpacing) + 1; + mGridNumZ = vecFloor(meshExtent.z / mGridSpacing) + 1; + uint32_t numCells = uint32_t(mGridNumX * mGridNumY * mGridNumZ); + mGridBounds.maximum = mGridBounds.minimum + + PxVec3(mGridNumX * mGridSpacing, mGridNumY * mGridSpacing, mGridNumZ * mGridSpacing); + + mGridFirstPoly.resize(numCells+1, -0); + mGridPolys.clear(); + + // histogram + //float h = mGridSpacing; + float h1 = 1.0f / mGridSpacing; + PxBounds3 polyBounds; + for (uint32_t i = 0; i < numPolys; i++) { + PxBounds3 &polyBounds = mPolyBounds[i]; + int x0 = (int)((polyBounds.minimum.x - mGridBounds.minimum.x) * h1); + int y0 = (int)((polyBounds.minimum.y - mGridBounds.minimum.y) * h1); + int z0 = (int)((polyBounds.minimum.z - mGridBounds.minimum.z) * h1); + int x1 = (int)((polyBounds.maximum.x - mGridBounds.minimum.x) * h1); + int y1 = (int)((polyBounds.maximum.y - mGridBounds.minimum.y) * h1); + int z1 = (int)((polyBounds.maximum.z - mGridBounds.minimum.z) * h1); + for (int xi = x0; xi <= x1; xi++) { + for (int yi = y0; yi <= y1; yi++) { + for (int zi = z0; zi <= z1; zi++) { + int nr = (xi * mGridNumY + yi) * mGridNumZ + zi; + mGridFirstPoly[(uint32_t)nr]++; + } + } + } + } + int first = 0; + for (uint32_t i = 0; i < numCells; i++) { + first += mGridFirstPoly[i]; + mGridFirstPoly[i] = first; + } + mGridFirstPoly[numCells] = first; + mGridPolys.resize((uint32_t)first); + + // fill in + for (uint32_t i = 0; i < numPolys; i++) { + PxBounds3 &polyBounds = mPolyBounds[i]; + int x0 = (int)((polyBounds.minimum.x - mGridBounds.minimum.x) * h1); + int y0 = (int)((polyBounds.minimum.y - mGridBounds.minimum.y) * h1); + int z0 = (int)((polyBounds.minimum.z - mGridBounds.minimum.z) * h1); + int x1 = (int)((polyBounds.maximum.x - mGridBounds.minimum.x) * h1); + int y1 = (int)((polyBounds.maximum.y - mGridBounds.minimum.y) * h1); + int z1 = (int)((polyBounds.maximum.z - mGridBounds.minimum.z) * h1); + for (int xi = x0; xi <= x1; xi++) { + for (int yi = y0; yi <= y1; yi++) { + for (int zi = z0; zi <= z1; zi++) { + int nr = (xi * mGridNumY + yi) * mGridNumZ + zi; + mGridFirstPoly[(uint32_t)nr]--; + mGridPolys[(uint32_t)mGridFirstPoly[(uint32_t)nr]] = (int32_t)i; + } + } + } + } + mGridPolyMarks.clear(); + mGridPolyMarks.resize(numPolys, 0); + mGridCurrentMark = 1; +} + +// -------------------------------------------------------------------------------------------- +void MeshClipper::computeClipFaceNeighbors() +{ + const nvidia::Array<int> &indices = mClipConvex->getIndices(); + const nvidia::Array<Convex::Face> &faces = mClipConvex->getFaces(); + + mClipFaceNeighbors.clear(); + mClipFaceNeighbors.resize(indices.size(), -1); + + mEdges.resize(indices.size()); + //int edgeNr = 0; + for (uint32_t i = 0; i < faces.size(); i++) { + const Convex::Face &f = faces[i]; + for (int j = 0; j < f.numIndices; j++) { + int edgeNr = f.firstIndex + j; + mEdges[(uint32_t)edgeNr].init(indices[uint32_t(f.firstIndex + j)], indices[uint32_t(f.firstIndex + (j+1)%f.numIndices)], edgeNr, (int32_t)i); + } + } + shdfnd::sort(mEdges.begin(), mEdges.size()); + uint32_t i = 0; + while (i < mEdges.size()) { + Edge &e0 = mEdges[i]; + i++; + if (i < mEdges.size() && mEdges[i] == e0) { + Edge &e1 = mEdges[i]; + mClipFaceNeighbors[(uint32_t)e0.edgeNr] = e1.faceNr; + mClipFaceNeighbors[(uint32_t)e1.edgeNr] = e0.faceNr; + i++; + } + while (i < mEdges.size() && mEdges[i] == e0) + i++; + } +} + +// -------------------------------------------------------------------------------------------- +bool MeshClipper::getGridCandidates(const PxBounds3 &bounds) +{ + if (mGridFirstPoly.empty()) + return false; // too few mesh polygons, no grid created + + float h1 = 1.0f / mGridSpacing; + mGridCurrentMark++; // make sure we return any poligon only once + + int x0 = vecFloor((bounds.minimum.x - mGridBounds.minimum.x) * h1); + int y0 = vecFloor((bounds.minimum.y - mGridBounds.minimum.y) * h1); + int z0 = vecFloor((bounds.minimum.z - mGridBounds.minimum.z) * h1); + int x1 = vecFloor((bounds.maximum.x - mGridBounds.minimum.x) * h1); + int y1 = vecFloor((bounds.maximum.y - mGridBounds.minimum.y) * h1); + int z1 = vecFloor((bounds.maximum.z - mGridBounds.minimum.z) * h1); + + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (z0 < 0) z0 = 0; + if (x1 >= mGridNumX) x1 = mGridNumX-1; + if (y1 >= mGridNumY) y1 = mGridNumY-1; + if (z1 >= mGridNumZ) z1 = mGridNumZ-1; + + + mPolyCandidates.clear(); + + for (int xi = x0; xi <= x1; xi++) { + for (int yi = y0; yi <= y1; yi++) { + for (int zi = z0; zi <= z1; zi++) { + int nr = (xi * mGridNumY + yi) * mGridNumZ + zi; + int first = mGridFirstPoly[(uint32_t)nr]; + int last = mGridFirstPoly[(uint32_t)nr+1]; + for (int i = first; i < last; i++) { + int polyNr = mGridPolys[(uint32_t)i]; + if (mGridPolyMarks[(uint32_t)polyNr] != mGridCurrentMark) { + mGridPolyMarks[(uint32_t)polyNr] = mGridCurrentMark; + mPolyCandidates.pushBack(polyNr); + } + } + } + } + } + return true; +} + +// -------------------------------------------------------------------------------------------- +void MeshClipper::generateCandidates(const PxTransform &pxTrans) +{ + // cull polys that are completely outside of at least one convex plane + // determine polys that are completely inside of all convex planes + + const nvidia::Array<int> &meshPolyStarts = mMeshConvex->getVisPolyStarts(); + const nvidia::Array<int> &meshPolyIndices = mMeshConvex->getVisPolyIndices(); + + const nvidia::Array<PxPlane> &clipPlanes = mClipConvex->getPlanes(); + const nvidia::Array<PxVec3> &clipConvexVertices = mClipConvex->getVertices(); + + PxTransform trans = (pxTrans); + PxTransform invTrans = trans.getInverse(); + + PxBounds3 clipBounds; + clipBounds.setEmpty(); + for (uint32_t i = 0; i < clipConvexVertices.size(); i++) + clipBounds.include(invTrans.transform((clipConvexVertices[i]))); + + uint32_t numPolys = meshPolyStarts.size()-1; + + // use grid for initial culling + if (!getGridCandidates(clipBounds)) { + mPolyCandidates.resize(numPolys); // no grid, start with all polys + for (uint32_t i = 0; i < numPolys; i++) + mPolyCandidates[i] = (int32_t)i; + } + + // use bounding boxes for further culling + PxBounds3 polyBounds; + uint32_t numCandidates = 0; + for (uint32_t i = 0; i < mPolyCandidates.size(); i++) { + int polyNr = mPolyCandidates[i]; + PxBounds3 &polyBounds = mPolyBounds[(uint32_t)polyNr]; + if (polyBounds.intersects(clipBounds)) { + mPolyCandidates[numCandidates] = polyNr; + numCandidates++; + } + } + mPolyCandidates.resize(numCandidates); + + // use clip planes for further culling + mPolyInside.resize(0); + mPolyInside.resize(numPolys, true); + + for (uint32_t i = 0; i < clipPlanes.size(); i++) { + PxPlane plane = (clipPlanes[i]); + plane.n = invTrans.rotate(plane.n); + plane.d = plane.d + invTrans.p.dot(plane.n); + + uint32_t numCandidates = 0; + for (uint32_t j = 0; j < mPolyCandidates.size(); j++) { + uint32_t polyNr = (uint32_t)mPolyCandidates[j]; + int first = meshPolyStarts[polyNr]; + int last = meshPolyStarts[polyNr+1]; + bool outside = true; + for (int k = first; k < last; k++) { + PxVec3 &p = mMeshVertices[(uint32_t)meshPolyIndices[(uint32_t)k]]; + float dot = plane.n.dot(p); + if (dot > plane.d) + mPolyInside[polyNr] = false; + if (dot < plane.d) + outside = false; + if (!mPolyInside[polyNr] && !outside) + break; + } + if (!outside) { + mPolyCandidates[numCandidates] = (int32_t)polyNr; + numCandidates++; + } + } + mPolyCandidates.resize(numCandidates); + } +} + +// -------------------------------------------------------------------------------------------- +bool MeshClipper::createInternalPolygons(const PxTransform &pxTrans) +{ +#if VEC3_DOUBLE + const float eps = 1e-8f; +#else + const float eps = 1e-4f; +#endif + + PxTransform trans = (pxTrans); + + const nvidia::Array<PxVec3> &meshNormals = mMeshConvex->getVisNormals(); + const nvidia::Array<PxVec3> &meshTangents = mMeshConvex->getVisTangents(); + const nvidia::Array<float> &meshTexCoords = mMeshConvex->getVisTexCoords(); + + const nvidia::Array<int> &meshPolyStarts = mMeshConvex->getVisPolyStarts(); + const nvidia::Array<int> &meshPolyIndices = mMeshConvex->getVisPolyIndices(); + const nvidia::Array<int> &meshPolyNeighbors = mMeshConvex->getVisPolyNeighbors(); + + const nvidia::Array<PxPlane> &clipPlanes = mClipConvex->getPlanes(); + //const nvidia::Array<Convex::Face> &clipConvexFaces = mClipConvex->getFaces(); + + uint32_t current = 0; + Mesh &out = mOutMeshes[0]; + + for (uint32_t i = 0; i < mPolyCandidates.size(); i++) { + uint32_t polyNr = (uint32_t)mPolyCandidates[i]; + + int first = meshPolyStarts[polyNr]; + int last = meshPolyStarts[polyNr+1]; + int polySize = last - first; + PX_ASSERT(polySize >= 3); + + // initialize working poly with original poly + // todo: fast poly for insides + + mClipPolyStarts[current].resize(2, 0); + mClipPolyStarts[current][1] = polySize; + + mClipPolyVerts[current].resize((uint32_t)polySize); + + if (mPolyInside[polyNr]) { // fast path for polygons completely inside convex + + mFirstOutPoly[polyNr] = (int32_t)out.polyStarts.size()-1; + mNumOutPolys[polyNr] = 1; + + for (int j = 0; j < polySize; j++) { + uint32_t id = (uint32_t)meshPolyIndices[uint32_t(first + j)]; + if (mOutVertNr[id] < 0) { + mOutVertNr[id] = (int32_t)out.vertices.size(); + out.vertices.pushBack((trans.transform(mMeshVertices[id]))); + out.normals.pushBack(pxTrans.rotate(meshNormals[id])); + out.tangents.pushBack(pxTrans.rotate(meshTangents[id])); + out.texCoords.pushBack(meshTexCoords[2*id]); + out.texCoords.pushBack(meshTexCoords[2*id+1]); + } + out.polyIndices.pushBack(mOutVertNr[id]); + out.polyNeighbors.pushBack(meshPolyNeighbors[uint32_t(first + j)]); + } + out.polyStarts.pushBack((int32_t)out.polyIndices.size()); + continue; + } + + for (int j = 0; j < polySize; j++) { + PolyVert &pv = mClipPolyVerts[current][(uint32_t)j]; + pv.init(); + pv.id = meshPolyIndices[uint32_t(first + j)]; + pv.pos = trans.transform(mMeshVertices[(uint32_t)pv.id]); + pv.normal = trans.rotate((meshNormals[(uint32_t)pv.id])); + pv.tangent = trans.rotate((meshTangents[(uint32_t)pv.id])); + pv.u = meshTexCoords[2 * (uint32_t)pv.id]; + pv.v = meshTexCoords[2 * (uint32_t)pv.id + 1]; + pv.edgeNeighbor = meshPolyNeighbors[uint32_t(first + j)]; + pv.edgeOnFace = false; + } + + // determine face normal + PxVec3 faceNormal(0.0, 0.0, 0.0); + PxVec3 &p0 = mClipPolyVerts[current][0].pos; + for (int j = 1; j < polySize-1; j++) { + PxVec3 &p1 = mClipPolyVerts[current][(uint32_t)j].pos; + PxVec3 &p2 = mClipPolyVerts[current][(uint32_t)j+1].pos; + faceNormal += (p1-p0).cross(p2-p0); + } + faceNormal.normalize(); + + // clip working poly against all planes + for (uint32_t j = 0; j < clipPlanes.size(); j++) { + + const PxPlane plane = (clipPlanes[j]); + PxVec3 cutNormal = faceNormal.cross(plane.n); + if (cutNormal.magnitudeSquared() < eps * eps) + continue; + + uint32_t prev = current; + current = 1-current; + + mClipPolyStarts[current].clear(); + mClipPolyStarts[current].pushBack(0); + mClipPolyVerts[current].clear(); + + uint32_t numPrevPolys = mClipPolyStarts[prev].size()-1; + if (numPrevPolys == 0) + break; + + for (uint32_t k = 0; k < numPrevPolys; k++) { + int prevFirst = mClipPolyStarts[prev][k]; + int prevLast = mClipPolyStarts[prev][k+1]; + int prevNum = prevLast - prevFirst; + + // determine cuts + mCuts.clear(); + bool anyIn = false; + + for (int l = 0; l < prevNum; l++) { + PolyVert &pv0 = mClipPolyVerts[prev][uint32_t(prevFirst + l)]; + PolyVert &pv1 = mClipPolyVerts[prev][uint32_t(prevFirst + (l+1)%prevNum)]; + pv0.nextVert = -1; + + bool sign0 = plane.n.dot(pv0.pos) > plane.d; + bool sign1 = plane.n.dot(pv1.pos) > plane.d; + + if (!sign0 || !sign1) + anyIn = true; + + if (sign0 == sign1) + continue; + + PxVec3 p0 = pv0.pos; + PxVec3 p1 = pv1.pos; + + // compute in unique order such that cut positions are identical on shared edges + bool smaller = + (p0.x < p1.x) || + (p0.x == p1.x && p0.y < p1.y) || + (p0.x == p1.x && p0.y == p1.y && p0.z < p1.z); + if (smaller) { + p0 = pv1.pos; + p1 = pv0.pos; + } + + float t = (p1 - p0).dot(plane.n); + if (t == 0.0) + continue; + t = (plane.d - p0.dot(plane.n)) / t; + + PolyVert cut; + cut.init(); + cut.pos = p0 + (p1 - p0) * t; + if (smaller) { + cut.normal = pv1.normal + (pv0.normal - pv1.normal) * t; + cut.tangent = pv1.tangent + (pv0.tangent - pv1.tangent) * t; + cut.u = pv1.u + (pv0.u - pv1.u) * t; + cut.v = pv1.v + (pv0.v - pv1.v) * t; + } + else { + cut.normal = pv0.normal + (pv1.normal - pv0.normal) * t; + cut.tangent = pv0.tangent + (pv1.tangent - pv0.tangent) * t; + cut.u = pv0.u + (pv1.u - pv0.u) * t; + cut.v = pv0.v + (pv1.v - pv0.v) * t; + } + cut.normal.normalize(); + cut.tangent.normalize(); + cut.id = -1; + + // vertex following this cut + if (sign1) { + cut.edgeOnFace = true; + cut.edgeNeighbor = (int32_t)j; // planeNr + cut.nextVert = -1; // exit convex + } + else { + cut.edgeOnFace = pv0.edgeOnFace; + cut.edgeNeighbor = pv0.edgeNeighbor; + cut.nextVert = (l+1)%prevNum; // enter convex + } + + pv0.nextVert = (int32_t)mCuts.size(); + mCuts.pushBack(cut); + } + if (!anyIn) + continue; + + // poly not cut, copy 1:1 + if (mCuts.empty()) { + for (int l = 0; l < prevNum; l++) { + PolyVert &pv = mClipPolyVerts[prev][uint32_t(prevFirst + l)]; + mClipPolyVerts[current].pushBack(pv); + } + mClipPolyStarts[current].pushBack((int32_t)mClipPolyVerts[current].size()); + continue; + } + + // construct new polygon(s) + for (uint32_t l = 0; l < mCuts.size(); l++) + { + if (mCuts[l].nextVert < 0) // exit polygon + continue; + + // start a polygon from this cut + int nr = mCuts[l].nextVert; + mCuts[l].nextVert = -1; // visited + mClipPolyVerts[current].pushBack(mCuts[l]); + + int safetyCnt = 0; + + while ( true ) + { + if (!check(safetyCnt < prevNum + (int)mCuts.size(), "construct new polygons infinite loop")) + return false; + safetyCnt++; + + if (!check(nr >= 0, "construct new polygons loop not closed")) + return false; + + if(nr >= (int)mClipPolyVerts[prev].size()) // prevents a crash + return false; + + mClipPolyVerts[current].pushBack(mClipPolyVerts[prev][(uint32_t)nr]); + int cutNr = mClipPolyVerts[prev][(uint32_t)nr].nextVert; + if (cutNr < 0) { + nr = (nr+1) % prevNum; + continue; + } + // we reached the next cut + mClipPolyVerts[current].pushBack(mCuts[(uint32_t)cutNr]); + + // find the closest cut to the left + float s0 = mCuts[(uint32_t)cutNr].pos.dot(cutNormal); + float sMax = -FLT_MAX; + float sMin = FLT_MAX; + int minNr = -1; + int maxNr = -1; + for (int m = 0; m < (int)mCuts.size(); m++) { + float s = mCuts[(uint32_t)m].pos.dot(cutNormal); + if (s > s0 && s < sMin) { + sMin = s; + minNr = m; + } + if (s > sMax) { + sMax = s; + maxNr = m; + } + } + uint32_t nextCutNr = uint32_t((minNr >= 0) ? minNr : maxNr); + + if (nextCutNr == l) + break; // loop closed + + PolyVert &nextCut = mCuts[nextCutNr]; + nr = nextCut.nextVert; + nextCut.nextVert = -1; // visited + mClipPolyVerts[current].pushBack(nextCut); + } + // close poly + mClipPolyStarts[current].pushBack((int32_t)mClipPolyVerts[current].size()); + } + } + } // next plane + + // map from old to new poly numbers + mFirstOutPoly[polyNr] = (int32_t)out.polyStarts.size()-1; + mNumOutPolys[polyNr] = (int32_t)mClipPolyStarts[current].size()-1; + // separate num needed because we do not process the polys with candidate list, not in order + + // clipped poly empty? + if (mNumOutPolys[polyNr] <= 0) + continue; + + // create visual polygon(s) + for (uint32_t j = 0; j < mClipPolyStarts[current].size()-1; j++) { + int first = mClipPolyStarts[current][j]; + int last = mClipPolyStarts[current][j+1]; + int num = last - first; + for (int k = 0; k < num; k++) { + PolyVert &pv0 = mClipPolyVerts[current][uint32_t(first + k)]; + PolyVert &pv1 = mClipPolyVerts[current][uint32_t(first + (k+1)%num)]; + + int id = -1; + int faceId = -1; + + if (!pv0.edgeOnFace && !pv1.edgeOnFace) { // existing vertex, duplicate + if (!check(pv1.id >= 0, "internal vertex with id < 0")) + return false; + + if (mOutVertNr[(uint32_t)pv1.id] < 0) { + mOutVertNr[(uint32_t)pv1.id] = (int32_t)out.vertices.size(); + out.vertices.pushBack((pv1.pos)); + out.normals.pushBack((pv1.normal)); + out.tangents.pushBack((pv1.tangent)); + out.texCoords.pushBack((float)pv1.u); + out.texCoords.pushBack((float)pv1.v); + } + id = mOutVertNr[(uint32_t)pv1.id]; + faceId = -1; + } + else if (pv0.edgeOnFace && pv1.edgeOnFace) { // new, non shared + id = (int32_t)out.vertices.size(); + out.vertices.pushBack((pv1.pos)); + out.normals.pushBack((pv1.normal)); + out.tangents.pushBack((pv1.tangent)); + out.texCoords.pushBack((float)pv1.u); + out.texCoords.pushBack((float)pv1.v); + faceId = id; + } + else { // new, shared + int edgeNeighbor = pv0.edgeOnFace ? pv1.edgeNeighbor : pv0.edgeNeighbor; + int sharedId = -1; + int numPolys = mNumOutPolys[(uint32_t)edgeNeighbor]; + + // new neighbor exists, search shared vertex + if (numPolys > 0) { + int firstPoly = mFirstOutPoly[(uint32_t)edgeNeighbor]; + for (int l = 0; l < numPolys; l++) { + int newPolyNr = firstPoly + l; + int first = out.polyStarts[(uint32_t)newPolyNr]; + int last = out.polyStarts[(uint32_t)newPolyNr+1]; + for (int m = first; m < last; m++) { + int testId = out.polyIndices[(uint32_t)m]; + if (out.vertices[(uint32_t)testId] == (pv1.pos)) { + sharedId = testId; + break; + } + } + if (sharedId >= 0) + break; + } + } + if (sharedId >= 0 && out.normals[(uint32_t)sharedId] == (pv1.normal)) // share it + id = sharedId; + else { + id = (int32_t)out.vertices.size(); // create new + out.vertices.pushBack((pv1.pos)); + out.normals.pushBack((pv1.normal)); + out.tangents.pushBack((pv1.tangent)); + out.texCoords.pushBack((float)pv1.u); + out.texCoords.pushBack((float)pv1.v); + } + if (sharedId >= 0) + faceId = sharedId; // on the convex surface we need the shared id to make the surface poly connected + else + faceId = id; + } + out.polyIndices.pushBack(id); + out.polyNeighbors.pushBack(pv1.edgeOnFace ? -1 : pv1.edgeNeighbor); + pv1.id = faceId; + } + out.polyStarts.pushBack((int32_t)out.polyIndices.size()); // close poly + + // create face vertices + for (int k = 0; k < num; k++) { + PolyVert &pv0 = mClipPolyVerts[current][uint32_t(first + k)]; + PolyVert &pv1 = mClipPolyVerts[current][uint32_t(first + (k+1)%num)]; + if (!pv0.edgeOnFace && !pv1.edgeOnFace) + continue; + + if (pv1.id >= (int)mFaceVertNrs.size()) + mFaceVertNrs.resize((uint32_t)pv1.id + 1, -1); + + int &vertNr = mFaceVertNrs[(uint32_t)pv1.id]; + if (vertNr < 0) { + FaceVert newSv; + newSv.init(); + vertNr = (int32_t)mFaceVerts.size(); + mFaceVerts.pushBack(newSv); + } + FaceVert &sv = mFaceVerts[(uint32_t)vertNr]; + sv.id = pv1.id; + } + + // create face polyline + for (int k = 0; k < num; k++) { + PolyVert &pv0 = mClipPolyVerts[current][uint32_t(first + k)]; + PolyVert &pv1 = mClipPolyVerts[current][uint32_t(first + (k+1)%num)]; + + if (pv1.id < 0) // not on surface + continue; + + FaceVert &sv = mFaceVerts[(uint32_t)mFaceVertNrs[(uint32_t)pv1.id]]; + if (pv0.edgeOnFace) { + sv.nextFaceNr = pv0.edgeNeighbor; + sv.neighborPos = out.polyStarts[out.polyStarts.size()-2] + (k+num-1)%num; + sv.neighborPolyNr = (int32_t)out.polyStarts.size()-2; + sv.nextVert = mFaceVertNrs[(uint32_t)pv0.id]; + } + if (pv1.edgeOnFace) { + sv.prevFaceNr = pv1.edgeNeighbor; + } + } + } + } // next polygon candidate + + // fix neighbors + for (int i = 0; i < (int)out.polyStarts.size()-1; i++) { + int first = out.polyStarts[(uint32_t)i]; + int num = out.polyStarts[(uint32_t)i+1] - first; + for (int j = 0; j < num; j++) { + int oldNr = out.polyNeighbors[uint32_t(first + j)]; + if (oldNr < 0) + continue; + + int numNew = mNumOutPolys[(uint32_t)oldNr]; + if (!check(numNew > 0, "fix internal neighbors, no new polygond created")) + return false; + + if (numNew == 1) { // simple mapping + out.polyNeighbors[uint32_t(first + j)] = mFirstOutPoly[(uint32_t)oldNr]; + } + else { // find correct new poly + PxVec3 v1 = out.vertices[(uint32_t)out.polyIndices[uint32_t(first + (j+1)%num)]]; + float minD2 = PX_MAX_F32; + int minNr = -1; + + for (int k = 0; k < numNew; k++) { + int newNr = mFirstOutPoly[(uint32_t)oldNr] + k; + int firstNew = out.polyStarts[(uint32_t)newNr]; + int lastNew = out.polyStarts[(uint32_t)newNr+1]; + for (int l = firstNew; l < lastNew; l++) { + PxVec3 v0 = out.vertices[(uint32_t)out.polyIndices[(uint32_t)l]]; + float d2 = (v1-v0).magnitudeSquared(); + if (d2 < minD2) { + minD2 = d2; + minNr = newNr; + } + } + } + out.polyNeighbors[uint32_t(first + j)] = minNr; + } + } + } + + return true; +} + +// -------------------------------------------------------------------------------------------- +bool MeshClipper::createFacePolys() +{ + const nvidia::Array<PxPlane> &clipPlanes = mClipConvex->getPlanes(); + const nvidia::Array<Convex::Face> &clipConvexFaces = mClipConvex->getFaces(); + const nvidia::Array<PxVec3> &clipConvexVertices = mClipConvex->getVertices(); + const nvidia::Array<int> &clipConvexIndices = mClipConvex->getIndices(); + + mFaceTypes.clear(); + mFaceTypes.resize(clipConvexFaces.size(), 0); + mFaceOfPoly.clear(); + + Mesh &out = mOutMeshes[0]; + int firstFacePoly = (int32_t)out.polyStarts.size()-1; + + + // create face polys + for (uint32_t i = 0; i < mFaceVerts.size(); i++) { + FaceVert &startSv = mFaceVerts[i]; + if (startSv.visited) + continue; + + int faceNr = startSv.nextFaceNr; + if (!check(faceNr >= 0, "create face polygons, loop interrupted")) + return false; + + mFaceTypes[(uint32_t)faceNr] = 1; // has visual mesh + + PxVec3 faceNormal = clipPlanes[(uint32_t)faceNr].n; + PxVec3 t0,t1; + // tangents + if (fabs(faceNormal.x) < fabs(faceNormal.y) && fabs(faceNormal.x) < fabs(faceNormal.z)) + t0 = PxVec3(1.0f, 0.0f, 0.0f); + else if (fabs(faceNormal.y) < fabs(faceNormal.z)) + t0 = PxVec3(0.0f, 1.0f, 0.0); + else + t0 = PxVec3(0.0f, 0.0f, 1.0f); + t1 = faceNormal.cross(t0); + t1.normalize(); + t0 = t1.cross(faceNormal); + + const Convex::Face &face = clipConvexFaces[(uint32_t)faceNr]; + int thisPolyNr = (int32_t)out.polyStarts.size()-1; + + int vertNr = (int32_t)i; + int safetyCnt = 0; + + while (true) { + if (!check(safetyCnt <= (int)mFaceVerts.size() + (int)clipConvexVertices.size(), "create face polygons infinite loop")) + return false; + safetyCnt++; + + if (!check(vertNr >= 0, "create face polygons loop interrupted")) + return false; + + FaceVert &sv = mFaceVerts[(uint32_t)vertNr]; + + out.polyIndices.pushBack((int32_t)out.vertices.size()); + PxVec3 temp = out.vertices[(uint32_t)sv.id]; + out.vertices.pushBack(temp); + out.normals.pushBack(faceNormal); + out.tangents.pushBack(t0); + out.texCoords.pushBack(out.vertices[(uint32_t)sv.id].dot(t0) * mTexScale); + out.texCoords.pushBack(out.vertices[(uint32_t)sv.id].dot(t1) * mTexScale); + + if (sv.nextFaceNr == faceNr) { // continues on this face + sv.visited = true; + out.polyNeighbors.pushBack(sv.neighborPolyNr); + out.polyNeighbors[(uint32_t)sv.neighborPos] = thisPolyNr; + vertNr = sv.nextVert; + if (vertNr == (int32_t)i) + break; // start reached + else + continue; + } + + // on convex edge, find next entry vert + int edgeNr = 0; + while (edgeNr < face.numIndices && mClipFaceNeighbors[uint32_t(face.firstIndex + edgeNr)] != sv.nextFaceNr) + edgeNr++; + if (!check(edgeNr < face.numIndices, "create face polys, find next entry vert not successfull")) + return false; + + vertNr = -1; + int numCorners = 0; + + for (int j = 0; j <= face.numIndices; j++) { + int adjFaceNr = mClipFaceNeighbors[uint32_t(face.firstIndex + edgeNr)]; + out.polyNeighbors.pushBack(-1-adjFaceNr); + + PxVec3 edgeDir = clipPlanes[(uint32_t)faceNr].n.cross(clipPlanes[(uint32_t)adjFaceNr].n); + float s0 = out.vertices[out.vertices.size()-1].dot(edgeDir); + float minS = PX_MAX_F32; + int minK = -1; + for (uint32_t k = 0; k < mFaceVerts.size(); k++) { // todo: create edge face vert list to speed up + FaceVert &vk = mFaceVerts[k]; +// if (vk.id < 0) continue; + if (vk.nextFaceNr != faceNr || vk.prevFaceNr != adjFaceNr) + continue; + float si = out.vertices[(uint32_t)vk.id].dot(edgeDir); + if (si > s0 && si < minS) { + minS = si; + minK = (int32_t)k; + } + } + + if (minK >= 0) { + vertNr = minK; + break; + } + + // no entry found, add corner of convex + PxVec3 pos = clipConvexVertices[(uint32_t)clipConvexIndices[uint32_t(face.firstIndex + (edgeNr+1)%face.numIndices)]]; + out.vertices.pushBack(pos); + out.normals.pushBack(faceNormal); + out.tangents.pushBack(t0); + out.texCoords.pushBack(pos.dot(t0) * mTexScale); + out.texCoords.pushBack(pos.dot(t1) * mTexScale); + + out.polyIndices.pushBack((int32_t)out.vertices.size()-1); + if (numCorners > 0) { + if (mFaceTypes[(uint32_t)mClipFaceNeighbors[uint32_t(face.firstIndex + edgeNr)]] == 0) + mFaceTypes[(uint32_t)mClipFaceNeighbors[uint32_t(face.firstIndex + edgeNr)]] = 2; // inside visual mesh + } + + numCorners++; + edgeNr = (edgeNr+1) % face.numIndices; + } + if (vertNr == (int32_t)i) + break; // loop closed + } + + mFaceOfPoly.pushBack(faceNr); + out.polyStarts.pushBack((int32_t)out.polyIndices.size()); // close face poly + } + + // determine faces completely inside the visual mesh via flood fill + // start at faces of type 2 and fill all faces of type 0 + // reagion is bounded by faces of type 1 containing the visual mesh + for (uint32_t i = 0; i < mFaceTypes.size(); i++) { + if (mFaceTypes[i] != 2) + continue; + mFaceTypes[i] = 0; + mFaceQueue.resize(1, (int32_t)i); + while (mFaceQueue.size() > 0) { + uint32_t faceNr = (uint32_t)mFaceQueue[mFaceQueue.size()-1]; + mFaceQueue.popBack(); + if (mFaceTypes[faceNr] != 0) + continue; + mFaceTypes[faceNr] = 2; + const Convex::Face &face = clipConvexFaces[faceNr]; + for (int j = 0; j < face.numIndices; j++) { + int adjFaceNr = mClipFaceNeighbors[uint32_t(face.firstIndex + j)]; + if (mFaceTypes[(uint32_t)adjFaceNr] == 0) + mFaceQueue.pushBack(adjFaceNr); + } + } + } + + // create a polygon for each complete face inside the mesh + for (uint32_t i = 0; i < clipConvexFaces.size(); i++) { + if (mFaceTypes[i] != 2) + continue; + const Convex::Face &face = clipConvexFaces[i]; + PxVec3 faceNormal = clipPlanes[i].n; + + // tangents + PxVec3 t0,t1; + if (fabs(faceNormal.x) < fabs(faceNormal.y) && fabs(faceNormal.x) < fabs(faceNormal.z)) + t0 = PxVec3(1.0f, 0.0f, 0.0f); + else if (fabs(faceNormal.y) < fabs(faceNormal.z)) + t0 = PxVec3(0.0f, 1.0f, 0.0); + else + t0 = PxVec3(0.0f, 0.0f, 1.0f); + t1 = faceNormal.cross(t0); + t1.normalize(); + t0 = t1.cross(faceNormal); + + for (int j = 0; j < (int)face.numIndices; j++) { + PxVec3 pos = clipConvexVertices[(uint32_t)clipConvexIndices[uint32_t(face.firstIndex + j)]]; + out.vertices.pushBack(pos); + out.normals.pushBack(faceNormal); + out.tangents.pushBack(t0); + out.texCoords.pushBack(pos.dot(t0) * mTexScale); + out.texCoords.pushBack(pos.dot(t1) * mTexScale); + + out.polyIndices.pushBack((int32_t)out.vertices.size()-1); + out.polyNeighbors.pushBack(-1-mClipFaceNeighbors[uint32_t(face.firstIndex+j)]); + } + mFaceOfPoly.pushBack((int32_t)i); + out.polyStarts.pushBack((int32_t)out.polyIndices.size()); + } + + // fix face polygon neighbors + for (uint32_t i = (uint32_t)firstFacePoly; i < out.polyStarts.size()-1; i++) { + int first = out.polyStarts[i]; + int num = out.polyStarts[i+1] - first; + for (int j = 0; j < num; j++) { + int adjFaceNr = out.polyNeighbors[uint32_t(first + j)]; + if (adjFaceNr >= 0) + continue; + adjFaceNr = -1 - adjFaceNr; + PxVec3 &p0 = out.vertices[(uint32_t)out.polyIndices[uint32_t(first + (j+1)%num)]]; + float minD2 = PX_MAX_F32; + int minAdjPolyNr = -1; + + for (uint32_t k = 0; k < mFaceOfPoly.size(); k++) { + if (mFaceOfPoly[k] != adjFaceNr) + continue; + int adjPolyNr = firstFacePoly + (int32_t)k; + int adjFirst = out.polyStarts[(uint32_t)adjPolyNr]; + int adjLast = out.polyStarts[(uint32_t)adjPolyNr+1]; + for (int l = adjFirst; l < adjLast; l++) { + PxVec3 &p1 = out.vertices[(uint32_t)out.polyIndices[(uint32_t)l]]; + float d2 = (p0 - p1).magnitudeSquared(); + if (d2 < minD2) { + minD2 = d2; + minAdjPolyNr = adjPolyNr; + } + } + } + if (!check(minAdjPolyNr >= 0, "create face polys, fix neighbors")) + return false; + + out.polyNeighbors[uint32_t(first + j)] = minAdjPolyNr; + } + } + return true; +} + +// -------------------------------------------------------------------------------------------- +bool MeshClipper::clip(const Convex *clipConvex, const PxTransform &trans, float texScale, bool splitIslands, + bool &empty, bool &completelyInside) +{ + if (mMeshConvex == NULL) + return false; + + mTexScale = texScale; + + mClipConvex = clipConvex; + computeClipFaceNeighbors(); + + empty = true; + completelyInside = false; + + mOutMeshes.resize(1); + Mesh &out = mOutMeshes[0]; + mOutMeshes[0].clear(); + + mFaceVertNrs.clear(); // necessary? + mFaceVerts.clear(); + + const nvidia::Array<int> &meshPolyStarts = mMeshConvex->getVisPolyStarts(); + //const nvidia::Array<PxPlane> &clipPlanes = mClipConvex->getPlanes(); + const nvidia::Array<Convex::Face> &clipConvexFaces = mClipConvex->getFaces(); + const nvidia::Array<PxVec3> &clipConvexVertices = mClipConvex->getVertices(); + + int numPolys = (int32_t)meshPolyStarts.size()-1; + + mScene->profileBegin("generate poly candidates"); + generateCandidates(trans); + mScene->profileEnd("generate poly candidates"); + + mFirstOutPoly.clear(); // speed up, use only local mesh part + mFirstOutPoly.resize((uint32_t)numPolys, -1); + mNumOutPolys.clear(); + mNumOutPolys.resize((uint32_t)numPolys, 0); + + mOutVertNr.clear(); + mOutVertNr.resize(mMeshVertices.size(), -1); + mFirstOutFacePoly.clear(); + mFirstOutFacePoly.resize(clipConvexFaces.size(), -1); + mNumOutFacePolys.clear(); + mNumOutFacePolys.resize(clipConvexFaces.size(), 0); + + mScene->profileBegin("create internal polygons"); + if (!createInternalPolygons(trans)) { + empty = true; + mScene->profileEnd("create internal polygons"); + return false; + } + mScene->profileEnd("create internal polygons"); + + if (out.polyStarts.size() <= 1) { // cut empty + + // inside visual mesh? + + PxVec3 center(0.0f, 0.0f, 0.0f); + for (uint32_t i = 0; i < clipConvexVertices.size(); i++) + center += clipConvexVertices[i]; + center /= (float)clipConvexVertices.size(); + if (mMeshConvex->insideVisualMesh(trans.transformInv(center))) { + empty = false; + completelyInside = true; + return true; + } + else { + empty = true; + completelyInside = false; + return true; + } + } + + empty = true; + + mScene->profileBegin("create face polys"); + bool OK = createFacePolys(); + mScene->profileEnd("create face polys"); + if (!OK) + return false; + + //if (!testNeighbors()) + // return false; + + if (splitIslands) + this->splitIslands(); + + empty = false; + return true; +} + + + +// -------------------------------------------------------------------------------------------- +bool MeshClipper::splitIslands() +{ + if (mOutMeshes.size() < 1) + return false; + + uint32_t numPolys = mOutMeshes[0].polyStarts.size()-1; + mColors.clear(); + mColors.resize(numPolys, -1); + mQueue.clear(); + + int numIslands = 0; + + // color islands + for (uint32_t i = 0; i < numPolys; i++) { + if (mColors[i] >= 0) + continue; + numIslands++; + mQueue.clear(); + mQueue.pushBack((int32_t)i); + while (!mQueue.empty()) { + uint32_t polyNr = (uint32_t)mQueue[mQueue.size()-1]; + mQueue.popBack(); + if (mColors[polyNr] >= 0) + continue; + mColors[polyNr] = numIslands-1; + int first = mOutMeshes[0].polyStarts[polyNr]; + int last = mOutMeshes[0].polyStarts[polyNr+1]; + for (int j = first; j < last; j++) { + int neighborNr = mOutMeshes[0].polyNeighbors[(uint32_t)j]; + if (mColors[(uint32_t)neighborNr] >= 0) + continue; + mQueue.pushBack(neighborNr); + } + } + } + + // only one island? + if (numIslands <= 1) + return false; + + // create child meshes + mOutMeshes.resize((uint32_t)numIslands+1); + for (uint32_t i = 0; i < (uint32_t)numIslands; i++) { + mOutMeshes[1+i].clear(); + } + + // distribute visual mesh + mNewVertNr.clear(); + mNewVertNr.resize(mOutMeshes[0].vertices.size(), -1); + mNewPolyNr.clear(); + mNewPolyNr.resize(numPolys, -1); + + for (uint32_t i = 0; i < numPolys; i++) { + int meshNr = mColors[i]; + Mesh &parent = mOutMeshes[0]; + Mesh &child = mOutMeshes[(uint32_t)meshNr+1]; + int first = parent.polyStarts[i]; + int last = parent.polyStarts[i+1]; + for (int j = first; j < last; j++) { + uint32_t id = (uint32_t)parent.polyIndices[(uint32_t)j]; + if (mNewVertNr[id] < 0) { + mNewVertNr[id] = (int32_t)child.vertices.size(); + child.vertices.pushBack(parent.vertices[id]); + child.normals.pushBack(parent.normals[id]); + child.tangents.pushBack(parent.tangents[id]); + child.texCoords.pushBack(parent.texCoords[2*id]); + child.texCoords.pushBack(parent.texCoords[2*id+1]); + } + child.polyIndices.pushBack(mNewVertNr[id]); + child.polyNeighbors.pushBack(parent.polyNeighbors[(uint32_t)j]); // cannot adjust neighbor number yet + } + mNewPolyNr[i] = (int32_t)child.polyStarts.size()-1; + child.polyStarts.pushBack((int32_t)child.polyIndices.size()); + } + + // adjust neighbor numbers + //int num = 0; + for (int i = 0; i < numIslands; i++) { + Mesh &child = mOutMeshes[1+(uint32_t)i]; + for (int j = 0; j < (int)child.polyStarts.size()-1; j++) { + int first = child.polyStarts[(uint32_t)j]; + int last = child.polyStarts[(uint32_t)j+1]; + for (int k = first; k < last; k++) { + child.polyNeighbors[(uint32_t)k] = mNewPolyNr[(uint32_t)child.polyNeighbors[(uint32_t)k]]; + } + } + } + return true; +} + +// -------------------------------------------------------------------------------------------- +bool MeshClipper::insideVisualMesh(const PxVec3 & /*pos*/) const +{ + //if (mMeshConvex == NULL) + // return false; + + //const nvidia::Array<PxVec3> &meshNormals = mMeshConvex->getVisNormals(); + //const nvidia::Array<int> &meshPolyStarts = mMeshConvex->getVisPolyStarts(); + //const nvidia::Array<int> &meshPolyIndices = mMeshConvex->getVisPolyIndices(); + //const nvidia::Array<int> &meshPolyNeighbors = mMeshConvex->getVisPolyNeighbors(); + + //int num[6] = {0,0,0,0,0,0}; + //const int numAxes = 2; // max 3: the nigher the more robust but slower + + //for (int i = 0; i < (int)mVisTriIndices.size(); i += 3) { + // const PxVec3 &p0 = mVisVertices[mVisTriIndices[i]]; + // const PxVec3 &p1 = mVisVertices[mVisTriIndices[i+1]]; + // const PxVec3 &p2 = mVisVertices[mVisTriIndices[i+2]]; + // PxVec3 n = (p1-p0).cross(p2-p0); + // float d = n.dot(p0); + // float ds = d - pos.dot(n); + + // // for all axes, cound the hits of the ray starting from pos with the mesh + // for (int j = 0; j < numAxes; j++) { + // if (n[j] == 0.0f) + // continue; + + // int j0 = (j+1)%3; + // int j1 = (j+2)%3; + // float x0 = p0[j0]; + // float y0 = p0[j1]; + // float x1 = p1[j0]; + // float y1 = p1[j1]; + // float x2 = p2[j0]; + // float y2 = p2[j1]; + + // float px = pos[j0]; + // float py = pos[j1]; + + // // inside triangle? + // float d0 = (x1-x0) * (py-y0) - (y1-y0) * (px-x0); + // float d1 = (x2-x1) * (py-y1) - (y2-y1) * (px-x1); + // float d2 = (x0-x2) * (py-y2) - (y0-y2) * (px-x2); + // bool inside = + // (d0 <= 0.0f && d1 <= 0.0f && d2 <= 0.0f) || + // (d0 >= 0.0f && d1 >= 0.0f && d2 >= 0.0f); + // if (!inside) + // continue; + + // float s = ds / n[j]; + // if (s > 0.0f) + // num[2*j] += (n[j] > 0.0f) ? +1 : -1; + // else + // num[2*j+1] += (n[j] < 0.0f) ? +1 : -1; + // } + //} + //int numVotes = 0; + //for (int i = 0; i < 6; i++) { + // if (num[i] > 0) + // numVotes++; + //} + //return numVotes > numAxes; + return false; +} + +// -------------------------------------------------------------------------------------------- +bool MeshClipper::testNeighbors(int meshNr) +{ + if (meshNr >= (int)mOutMeshes.size()) + return false; + Mesh &mesh = mOutMeshes[(uint32_t)meshNr]; + + for (int i = 0; i < (int)mesh.polyStarts.size()-1; i++) { + int first = mesh.polyStarts[(uint32_t)i]; + int num = mesh.polyStarts[(uint32_t)i+1] - first; + for (int j = 0; j < num; j++) { + uint32_t i0 = (uint32_t)mesh.polyIndices[uint32_t(first+j)]; + uint32_t i1 = (uint32_t)mesh.polyIndices[uint32_t(first + (j+1)%num)]; + PxVec3 p0 = mesh.vertices[i0]; + PxVec3 p1 = mesh.vertices[i1]; + + int adj = mesh.polyNeighbors[uint32_t(first + j)]; + if (adj < 0) + return false; + + int adjFirst = mesh.polyStarts[(uint32_t)adj]; + int adjNum = mesh.polyStarts[(uint32_t)adj+1] - adjFirst; + bool found = false; + for (int k = 0; k < adjNum; k++) { + if (mesh.polyNeighbors[uint32_t(adjFirst+k)] == i) { + uint32_t j0 = (uint32_t)mesh.polyIndices[uint32_t(adjFirst+k)]; + uint32_t j1 = (uint32_t)mesh.polyIndices[uint32_t(adjFirst + (k+1)%adjNum)]; + PxVec3 q0 = mesh.vertices[j0]; + PxVec3 q1 = mesh.vertices[j1]; + if (p0 == q1 && p1 == q0) + found = true; + } + } + if (!found) + return false; + } + } + return true; +} + +// ----------------------------------------------------------------------------- +bool MeshClipper::check(bool test, const char* /*message*/) +{ +#ifndef _DEBUG + return test; +#else + + if (test) + return true; + + printf("\nerror in MeshClipper.cpp: %s\n", message); + + if (!mDumpOnError) + return test; +#endif + +#if DEBUG + FILE *f = fopen(DUMP_PATH, "wb"); + if (f == NULL) + return test; +#endif + +#ifdef _DEBUG + + printf("dump file saved: %s\n", DUMP_PATH); + + const nvidia::Array<PxVec3> &meshVertices = mMeshConvex->getVisVertices(); + //const nvidia::Array<PxVec3> &meshNormals = mMeshConvex->getVisNormals(); + const nvidia::Array<int> &meshPolyStarts = mMeshConvex->getVisPolyStarts(); + const nvidia::Array<int> &meshPolyIndices = mMeshConvex->getVisPolyIndices(); + //const nvidia::Array<int> &meshPolyNeighbors = mMeshConvex->getVisPolyNeighbors(); + + int cnt = (int)meshVertices.size(); + fwrite(&cnt, sizeof(int), 1, f); + fwrite(&meshVertices[0], sizeof(PxVec3), meshVertices.size(), f); + fwrite(&meshNormals[0], sizeof(PxVec3), meshNormals.size(), f); + + cnt = (int)meshPolyStarts.size(); + fwrite(&cnt, sizeof(int), 1, f); + fwrite(&meshPolyStarts[0], sizeof(int), meshPolyStarts.size(), f); + + cnt = (int)meshPolyIndices.size(); + fwrite(&cnt, sizeof(int), 1, f); + fwrite(&meshPolyIndices[0], sizeof(int), meshPolyIndices.size(), f); + + fclose(f); + return false; +#endif +} + +// ----------------------------------------------------------------------------- +bool MeshClipper::loadDump() +{ +#if DEBUG + FILE *f = fopen(DUMP_PATH, "rb"); + if (f == NULL) + return false; +#endif + + nvidia::Array<PxVec3> vertices; + nvidia::Array<PxVec3> normals; + nvidia::Array<int> polyStarts; + nvidia::Array<int> polyIndices; + nvidia::Array<int> polyNeighbors; + + uint32_t cnt = 0; + fread(&cnt, sizeof(int), 1, f); + vertices.resize(cnt); + fread(&vertices[0], sizeof(PxVec3), vertices.size(), f); + normals.resize(cnt); + fread(&normals[0], sizeof(PxVec3), normals.size(), f); + + fread(&cnt, sizeof(int), 1, f); + polyStarts.resize(cnt); + fread(&polyStarts[0], sizeof(int), polyStarts.size(), f); + + fread(&cnt, sizeof(int), 1, f); + polyIndices.resize(cnt); + fread(&polyIndices[0], sizeof(int), polyIndices.size(), f); + + fclose(f); + + Convex *c = mScene->createConvex(); + + bool isManifold = c->setExplicitVisMeshFromPolygons( + (int32_t)vertices.size(), &vertices[0], &normals[0], NULL, NULL, // todo, save as well + (int32_t)polyStarts.size()-1, &polyStarts[0], + (int32_t)polyIndices.size(), &polyIndices[0]); + + mMeshConvex = c; + + return isManifold; +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/MeshClipperBase.h b/APEX_1.4/module/destructible/fracture/Core/MeshClipperBase.h new file mode 100644 index 00000000..70cd8d03 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/MeshClipperBase.h @@ -0,0 +1,190 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef MESH_CLIPPER_BASE_H +#define MESH_CLIPPER_BASE_H + +// Matthias Muller-Fischer + +#include <PxVec3.h> +#include <PsArray.h> +#include <PxTransform.h> +#include <PxBounds3.h> +#include <PsUserAllocated.h> + +//#include "Vec3.h" +//#include "Bounds3.h" +//#include "Transform.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ +//using namespace ::M; +class Convex; +class SimScene; + +// --------------------------------------------------------------------------------------- +class MeshClipper : public UserAllocated { + friend class SimScene; +public: + // singleton pattern + //static MeshClipper* getInstance(); + //static void destroyInstance(); + + void init(const Convex *meshConvex); + bool clip(const Convex *clipConvex, const PxTransform &pxTrans, float texScale, bool splitIslands, + bool &empty, bool &completelyInside); + + struct Mesh { + void clear(); + nvidia::Array<PxVec3> vertices; + nvidia::Array<PxVec3> normals; + nvidia::Array<PxVec3> tangents; + nvidia::Array<float> texCoords; + nvidia::Array<int> polyStarts; + nvidia::Array<int> polyIndices; + nvidia::Array<int> polyNeighbors; + }; + + int getNumMeshes(); + const Mesh &getMesh(int meshNr); + + bool loadDump(); + +protected: + MeshClipper(SimScene* scene); + virtual ~MeshClipper() {} + + //static PxVec3 conv(const Vec3 &v); + //static Vec3 conv(const PxVec3 &v); + //static Transform conv(const PxTransform &t); + //static Plane conv(const PxPlane &p); + + void createGrid(); + bool getGridCandidates(const PxBounds3 &bounds); + + void generateCandidates(const PxTransform &pxTrans); + bool createInternalPolygons(const PxTransform &pxTrans); + bool createFacePolys(); + bool testNeighbors(int meshNr); + + bool splitIslands(); + + bool insideVisualMesh(const PxVec3 &pos) const; + + void computeClipFaceNeighbors(); + + SimScene* mScene; + + // input + const Convex *mMeshConvex; + const Convex *mClipConvex; + nvidia::Array<int> mClipFaceNeighbors; + float mTexScale; + + // output + nvidia::Array<Mesh> mOutMeshes; + + // auxiliaries + struct PolyVert { + void init() { + pos = normal = tangent = PxVec3(0.0, 0.0, 0.0); u = 0.0f; v = 0.0f; + id = -1; edgeNeighbor = -1; edgeOnFace = false; nextVert = -1; + } + PxVec3 pos; + PxVec3 normal; + PxVec3 tangent; + double u, v; + int id; + int edgeNeighbor; + bool edgeOnFace; + int nextVert; + }; + + struct FaceVert { + void init() { + id = -1; prevFaceNr = -1; nextFaceNr = -1; neighborPolyNr = -1; neighborPos = -1; + nextVert = -1; visited = false; + } + int id; + int prevFaceNr, nextFaceNr; + int neighborPolyNr; + int neighborPos; + int nextVert; + bool visited; + }; + + nvidia::Array<PxVec3> mMeshVertices; + nvidia::Array<bool> mPolyInside; + nvidia::Array<int> mPolyCandidates; + + nvidia::Array<PolyVert> mClipPolyVerts[2]; + nvidia::Array<int> mClipPolyStarts[2]; + nvidia::Array<PolyVert> mCuts; + nvidia::Array<int> mFaceVertNrs; + nvidia::Array<FaceVert> mFaceVerts; + nvidia::Array<PxBounds3> mPolyBounds; + + struct Edge { + void init(int i0, int i1, int edgeNr, int faceNr) { + if (i0 < i1) { this->i0 = i0; this->i1 = i1; } + else { this->i0 = i1; this->i1 = i0; } + this->edgeNr = edgeNr; this->faceNr = faceNr; + } + bool operator == (const Edge &e) const { return i0 == e.i0 && i1 == e.i1; } + bool operator < (const Edge &e) const { return i0 < e.i0 || (i0 == e.i0 && i1 < e.i1); } + int i0, i1; + int edgeNr, faceNr; + }; + nvidia::Array<Edge> mEdges; + + // map from int to out mesh + nvidia::Array<int> mFirstOutPoly; + nvidia::Array<int> mNumOutPolys; + nvidia::Array<int> mOutVertNr; + nvidia::Array<int> mFirstOutFacePoly; + nvidia::Array<int> mNumOutFacePolys; + + nvidia::Array<int> mFaceTypes; + nvidia::Array<int> mFaceOfPoly; + nvidia::Array<int> mFaceQueue; + + // split islands + nvidia::Array<int> mColors; + nvidia::Array<int> mQueue; + nvidia::Array<int> mNewVertNr; + nvidia::Array<int> mNewPolyNr; + + // grid + nvidia::Array<int> mGridFirstPoly; + nvidia::Array<int> mGridPolys; + int mGridNumX, mGridNumY, mGridNumZ; + float mGridSpacing; + PxBounds3 mGridBounds; + nvidia::Array<int> mGridPolyMarks; + int mGridCurrentMark; + + // error handling + bool check(bool test, const char *message); + bool mDumpOnError; +}; + +} +} +} + +#endif +#endif diff --git a/APEX_1.4/module/destructible/fracture/Core/PolygonTriangulatorBase.cpp b/APEX_1.4/module/destructible/fracture/Core/PolygonTriangulatorBase.cpp new file mode 100644 index 00000000..5a1d892b --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/PolygonTriangulatorBase.cpp @@ -0,0 +1,285 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "PolygonTriangulatorBase.h" +#include <PxAssert.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace nvidia; + +// ------ singleton pattern ----------------------------------------------------------- + +//static PolygonTriangulator *gPolygonTriangulator = NULL; +// +//PolygonTriangulator* PolygonTriangulator::getInstance() +//{ +// if (gPolygonTriangulator == NULL) { +// gPolygonTriangulator = PX_NEW(PolygonTriangulator)(); +// } +// return gPolygonTriangulator; +//} +// +//void PolygonTriangulator::destroyInstance() +//{ +// if (gPolygonTriangulator != NULL) { +// PX_DELETE(gPolygonTriangulator); +// } +// gPolygonTriangulator = NULL; +//} + +// ------------------------------------------------------------------------------------- +PolygonTriangulator::PolygonTriangulator(SimScene* scene): + mScene(scene) +{ +} + +// ------------------------------------------------------------------------------------- +PolygonTriangulator::~PolygonTriangulator() +{ +} + +// ------------------------------------------------------------------------------------- +float PolygonTriangulator::cross(const PxVec3 &p0, const PxVec3 &p1) +{ + return p0.x * p1.y - p0.y * p1.x; +} + +// ------------------------------------------------------------------------------------- +bool PolygonTriangulator::inTriangle(const PxVec3 &p, const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2) +{ + float d0 = cross(p1 - p0, p - p0); + float d1 = cross(p2 - p1, p - p1); + float d2 = cross(p0 - p2, p - p2); + return (d0 >= 0.0f && d1 >= 0.0f && d2 >= 0.0f) || + (d0 <= 0.0f && d1 <= 0.0f && d2 <= 0.0f); +} + +// ------------------------------------------------------------------------------------- +void PolygonTriangulator::triangulate(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal) +{ + mIndices.clear(); + + if (numPoints < 3) + return; + if (numPoints == 3) { + if (indices == NULL) { + mIndices.pushBack(0); + mIndices.pushBack(1); + mIndices.pushBack(2); + } + else { + mIndices.pushBack(indices[0]); + mIndices.pushBack(indices[1]); + mIndices.pushBack(indices[2]); + } + return; + } + + bool isConvex; + importPoints(points, numPoints, indices, planeNormal, isConvex); + + if (isConvex) { // fast path + mIndices.resize(3*((uint32_t)numPoints-2)); + for (int i = 0; i < numPoints-2; i++) { + mIndices[3*(uint32_t)i] = 0; + mIndices[3*(uint32_t)i+1] = i+1; + mIndices[3*(uint32_t)i+2] = i+2; + } + } + else + clipEars(); + + if (indices != NULL) { + for (uint32_t i = 0; i < mIndices.size(); i++) { + mIndices[i] = indices[(uint32_t)mIndices[i]]; + } + } +} + +// ------------------------------------------------------------------------------------- +void PolygonTriangulator::importPoints(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal, bool &isConvex) +{ + // find projection 3d -> 2d; + PxVec3 n; + + isConvex = true; + + if (planeNormal) + n = *planeNormal; + else { + PX_ASSERT(numPoints >= 3); + n = PxVec3(0.0f, 0.0f, 0.0f); + + for (int i = 1; i < numPoints-1; i++) { + int i0 = 0; + int i1 = i; + int i2 = i+1; + if (indices) { + i0 = indices[i0]; + i1 = indices[i1]; + i2 = indices[i2]; + } + const PxVec3 &p0 = points[i0]; + const PxVec3 &p1 = points[i1]; + const PxVec3 &p2 = points[i2]; + PxVec3 ni = (p1-p0).cross(p2-p0); + if (i > 1 && ni.dot(n) < 0.0f) + isConvex = false; + n += ni; + } + } + + n.normalize(); + PxVec3 t0,t1; + + if (fabs(n.x) < fabs(n.y) && fabs(n.x) < fabs(n.z)) + t0 = PxVec3(1.0f, 0.0f, 0.0f); + else if (fabs(n.y) < fabs(n.z)) + t0 = PxVec3(0.0f, 1.0f, 0.0f); + else + t0 = PxVec3(0.0f, 0.0f, 1.0f); + t1 = n.cross(t0); + t1.normalize(); + t0 = t1.cross(n); + + mPoints.resize((uint32_t)numPoints); + if (indices == NULL) { + for (uint32_t i = 0; i < (uint32_t)numPoints; i++) + mPoints[i] = PxVec3(points[i].dot(t0), points[i].dot(t1), 0.0f); + } + else { + for (uint32_t i = 0; i < (uint32_t)numPoints; i++) { + const PxVec3 &p = points[(uint32_t)indices[i]]; + mPoints[i] = PxVec3(p.dot(t0), p.dot(t1), 0.0f); + } + } +} + +// ------------------------------------------------------------------------------------- +void PolygonTriangulator::clipEars() +{ + // init + int32_t num = (int32_t)mPoints.size(); + + mCorners.resize((uint32_t)num); + + for (int i = 0; i < num; i++) { + Corner &c = mCorners[(uint32_t)i]; + c.prev = (i > 0) ? i-1 : num-1; + c.next = (i < num-1) ? i + 1 : 0; + c.isEar = false; + c.angle = 0.0f; + PxVec3 &p0 = mPoints[(uint32_t)c.prev]; + PxVec3 &p1 = mPoints[(uint32_t)i]; + PxVec3 &p2 = mPoints[(uint32_t)c.next]; + PxVec3 n1 = p1-p0; + PxVec3 n2 = p2-p1; + if (cross(n1, n2) > 0.0f) { + n1.normalize(); + n2.normalize(); + c.angle = n1.dot(n2); + + c.isEar = true; + int nr = (i+2) % num; + for (int j = 0; j < num-3; j++) { + if (inTriangle(mPoints[(uint32_t)nr], p0,p1,p2)) { + c.isEar = false; + break; + } + nr = (nr+1) % num; + } + } + } + + int firstCorner = 0; + int numCorners = num; + + while (numCorners > 3) { + + // find best ear + float minAng = FLT_MAX; + int minNr = -1; + + int nr = firstCorner; + for (int i = 0; i < numCorners; i++) { + Corner &c = mCorners[(uint32_t)nr]; + if (c.isEar && c.angle < minAng) { + minAng = c.angle; + minNr = nr; + } + nr = c.next; + } + + // cut ear +// assert(minNr >= 0); +if (minNr < 0) +break; + Corner &cmin = mCorners[(uint32_t)minNr]; + mIndices.pushBack(cmin.prev); + mIndices.pushBack(minNr); + mIndices.pushBack(cmin.next); + mCorners[(uint32_t)cmin.prev].next = cmin.next; + mCorners[(uint32_t)cmin.next].prev = cmin.prev; + + if (firstCorner == minNr) + firstCorner = cmin.next; + numCorners--; + if (numCorners == 3) + break; + + // new ears? + for (int i = 0; i < 2; i++) { + uint32_t i1 = uint32_t((i == 0) ? cmin.prev : cmin.next); + uint32_t i0 = (uint32_t)mCorners[i1].prev; + uint32_t i2 = (uint32_t)mCorners[i1].next; + + PxVec3 &p0 = mPoints[i0]; + PxVec3 &p1 = mPoints[i1]; + PxVec3 &p2 = mPoints[i2]; + PxVec3 n1 = p1-p0; + PxVec3 n2 = p2-p1; + if (cross(n1, n2) > 0.0f) { + n1.normalize(); + n2.normalize(); + mCorners[i1].angle = n1.dot(n2); + + mCorners[i1].isEar = true; + int nr = mCorners[i2].next; + for (int j = 0; j < numCorners-3; j++) { + if (inTriangle(mPoints[(uint32_t)nr], p0,p1,p2)) { + mCorners[i1].isEar = false; + break; + } + nr = mCorners[(uint32_t)nr].next; + } + } + } + } + int id = firstCorner; + mIndices.pushBack(id); + id = mCorners[(uint32_t)id].next; + mIndices.pushBack(id); + id = mCorners[(uint32_t)id].next; + mIndices.pushBack(id); +} + +} +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Core/PolygonTriangulatorBase.h b/APEX_1.4/module/destructible/fracture/Core/PolygonTriangulatorBase.h new file mode 100644 index 00000000..b6441ff2 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/PolygonTriangulatorBase.h @@ -0,0 +1,71 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef POLYGON_TRIANGULATOR_BASE_H +#define POLYGON_TRIANGULATOR_BASE_H + +#include <PxVec3.h> +#include <PsArray.h> +#include <PsUserAllocated.h> +#include <PxMath.h> + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + class SimScene; + +// ------------------------------------------------------------------------------ + +class PolygonTriangulator : public UserAllocated { + friend class SimScene; +public: + // singleton pattern + //static PolygonTriangulator* getInstance(); + //static void destroyInstance(); + + void triangulate(const PxVec3 *points, int numPoints, const int *indices = NULL, PxVec3 *planeNormal = NULL); + const nvidia::Array<int> &getIndices() const { return mIndices; } + +protected: + void importPoints(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal, bool &isConvex); + void clipEars(); + + inline float cross(const PxVec3 &p0, const PxVec3 &p1); + bool inTriangle(const PxVec3 &p, const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2); + + PolygonTriangulator(SimScene* scene); + virtual ~PolygonTriangulator(); + + SimScene* mScene; + + nvidia::Array<PxVec3> mPoints; + nvidia::Array<int> mIndices; + + struct Corner { + int prev; + int next; + bool isEar; + float angle; + }; + nvidia::Array<Corner> mCorners; +}; + +} +} +} + +#endif +#endif diff --git a/APEX_1.4/module/destructible/fracture/Core/SimSceneBase.cpp b/APEX_1.4/module/destructible/fracture/Core/SimSceneBase.cpp new file mode 100644 index 00000000..e8b1a7be --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/SimSceneBase.cpp @@ -0,0 +1,654 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "SimSceneBase.h" +#include <PxMat44.h> +#include "PxRigidBodyExt.h" +#include "PxPhysics.h" +#include "PxCooking.h" +#include "PxShape.h" +#include "PxScene.h" +#include "PxMaterial.h" + +#include "ActorBase.h" +#include "CompoundBase.h" +#include "ConvexBase.h" +#include "CompoundCreatorBase.h" +#include "Delaunay2dBase.h" +#include "Delaunay3dBase.h" +#include "PolygonTriangulatorBase.h" +#include "IslandDetectorBase.h" +#include "MeshClipperBase.h" +#include "FracturePatternBase.h" + +#include "RTdef.h" + +#define USE_CONVEX_RENDERER 1 +#define NUM_NO_SOUND_FRAMES 1 + +//#define REL_VEL_FRACTURE_THRESHOLD 5.0f +#define REL_VEL_FRACTURE_THRESHOLD 0.1f + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +using namespace physx; + +SimScene* SimScene::createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, PxScene *scene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath) +{ + SimScene* s = PX_NEW(SimScene)(pxPhysics,pxCooking,scene,minConvexSize,defaultMat,resourcePath); + s->createSingletons(); + return s; +} + +void SimScene::createSingletons() +{ + mCompoundCreator = PX_NEW(CompoundCreator)(this); + mDelaunay2d = PX_NEW(Delaunay2d)(this); + mDelaunay3d = PX_NEW(Delaunay3d)(this); + mPolygonTriangulator = PX_NEW(PolygonTriangulator)(this); + mIslandDetector = PX_NEW(IslandDetector)(this); + mMeshClipper = PX_NEW(MeshClipper)(this); + addActor(createActor()); // make default actor +} + +Convex* SimScene::createConvex() +{ + return PX_NEW(Convex)(this); +} + +Compound* SimScene::createCompound(const FracturePattern *pattern, const FracturePattern *secondaryPattern, float contactOffset, float restOffset) +{ + return PX_NEW(Compound)(this,pattern,secondaryPattern,contactOffset,restOffset); +} + +FracturePattern* SimScene::createFracturePattern() +{ + return PX_NEW(FracturePattern)(this); +} + +Actor* SimScene::createActor() +{ + return PX_NEW(Actor)(this); +} + +nvidia::Array<Compound*> SimScene::getCompounds() +{ + return mActors[0]->getCompounds(); +} + +///*extern*/ std::vector<Compound*> delCompoundList; + +// -------------------------------------------------------------------------------------------- +SimScene::SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, PxScene *scene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath) +{ + mPxPhysics = pxPhysics; // used for cooking + mPxCooking = pxCooking; + mScene = scene; + mPxDefaultMaterial = defaultMat; + if (mPxDefaultMaterial != NULL) + { + mPxDefaultMaterial->acquireReference(); + } + else + { + mPxDefaultMaterial = pxPhysics->createMaterial(0.5f, 0.5f, 0.1f); + } + mResourcePath = resourcePath; + + clear(); + mRenderBuffers.init(); + mSceneVersion = 1; + mRenderBufferVersion = 0; + mOptixBufferVersion = 0; + + //create3dTexture(); + + mFractureForceThreshold = 500.0f; + mContactImpactRadius = 0.5f; + + mNoFractureFrames = 0; + mNoSoundFrames = 0; + mFrameNr = 0; + mDebugDraw = false; +// mDebugDraw = true; // foo + + mPickDepth = 0.0f; + mPickActor = NULL; + mPickPos = mPickLocalPos = PxVec3(0.0f, 0.0f, 0.0f); + + mMinConvexSize = minConvexSize; + mNumNoFractureFrames = 2; + + bumpTextureUVScale = 0.1f; + roughnessScale = 0.2f; + extraNoiseScale = 2.0f; + + particleBumpTextureUVScale = 0.2f; + particleRoughnessScale = 0.8f; + particleExtraNoiseScale = 2.0f; + + + mPlaySounds = false; + mRenderDebris = true; + + mCompoundCreator = NULL; + mDelaunay2d = NULL; + mDelaunay3d = NULL; + mPolygonTriangulator = NULL; + mIslandDetector = NULL; + + mAppNotify = NULL; + + //SDLWrapper::init(); +} + +// -------------------------------------------------------------------------------------------- +SimScene::~SimScene() +{ + clear(); + + if (mPxDefaultMaterial) + { + mPxDefaultMaterial->release(); + mPxDefaultMaterial = NULL; + } + + // Delete actors if not already deleted + for(int i = ((int)mActors.size() - 1) ; i >= 0; i--) + { + PX_DELETE(mActors[(uint32_t)i]); + } + + PX_DELETE(mCompoundCreator); + PX_DELETE(mDelaunay2d); + PX_DELETE(mDelaunay3d); + PX_DELETE(mPolygonTriangulator); + PX_DELETE(mIslandDetector); + PX_DELETE(mMeshClipper); + + mCompoundCreator = NULL; + mDelaunay2d = NULL; + mDelaunay3d = NULL; + mPolygonTriangulator = NULL; + mIslandDetector = NULL; + mMeshClipper = NULL; + + //SDLWrapper::done(); +} + +// -------------------------------------------------------------------------------------------- +void SimScene::restoreUserCallbacks() +{ + if (mScene != NULL) + { + // restore user callbacks + mScene->lockWrite(); + mScene->setSimulationEventCallback(mAppNotify); + mScene->unlockWrite(); + } +} + +// -------------------------------------------------------------------------------------------- +void SimScene::clear() +{ + for(uint32_t i = 0 ; i < mActors.size(); i++) + { + mActors[i]->clear(); + } + deleteCompounds(); + mPickActor = NULL; + + ++mSceneVersion; +} + +void SimScene::addActor(Actor* a) +{ + mActors.pushBack(a); +} + +void SimScene::removeActor(Actor* a) +{ + for(uint32_t i = 0; i < mActors.size(); i++) + { + if( a == mActors[i] ) + { + mActors[i] = mActors[mActors.size()-1]; + mActors.popBack(); + } + } +} + +// -------------------------------------------------------------------------------------------- +void SimScene::addCompound(Compound *c) +{ + mActors[0]->addCompound(c); +} + +// -------------------------------------------------------------------------------------------- +void SimScene::removeCompound(Compound *c) +{ + mActors[0]->removeCompound(c); +} + +// -------------------------------------------------------------------------------------------- +void SimScene::deleteCompounds() +{ + for (uint32_t i = 0; i < delCompoundList.size(); i++) + { + PX_DELETE(delCompoundList[i]); + } + delCompoundList.clear(); +} + +// -------------------------------------------------------------------------------------------- +void SimScene::preSim(float dt) +{ + const float pickStiffness = 2.0f; + + if (mPickActor != NULL) { + PxVec3 pos = mPickActor->getGlobalPose().transform(mPickLocalPos); + float m = mPickActor->getMass(); + + PxRigidBodyExt::addForceAtPos(*mPickActor, (mPickPos - pos) * pickStiffness * m, pos, PxForceMode::eIMPULSE); + } + + for(uint32_t i = 0 ; i < mActors.size(); i++) + { + mActors[i]->preSim(dt); + } + + mFractureEvents.clear(); + + // make sure we use the apex user notify... if the application + // changes their custom one make sure we map to it. + if (mScene != NULL) + { + mScene->lockWrite(); + PxSimulationEventCallback* userNotify = mScene->getSimulationEventCallback(); + if (userNotify != this) + { + mAppNotify = userNotify; + mScene->setSimulationEventCallback(this); + } + mScene->unlockWrite(); + } +} + +//float4* posVelG = 0; +//int numPosVelG = 0; +// -------------------------------------------------------------------------------------------- +void SimScene::postSim(float dt) +{ +// Profiler *p = Profiler::getInstance(); + + //processFractureEvents(fluidSim); + for(uint32_t i = 0 ; i < mActors.size(); i++) + { + mActors[i]->postSim(dt); + } + //posVelG = &posVel[0]; + //numPosVelG = posVel.size(); +// mFractureEvents.clear(); // foo + + mFrameNr++; + mNoFractureFrames--; + mNoSoundFrames--; +} + +// -------------------------------------------------------------------------------------------- +bool SimScene::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &actorNr , int &compoundNr, int &convexNr, PxVec3 &normal) const +{ + dist = PX_MAX_F32; + actorNr = -1; + compoundNr = -1; + convexNr = -1; + + for (int i = 0; i < (int)mActors.size(); i++) + { + float d; + int comNr; + int conNr; + PxVec3 n; + if (mActors[(uint32_t)i]->rayCast(orig,dir,d,comNr,conNr,n)) + { + if( d < dist ) + { + dist = d; + actorNr = i; + compoundNr = comNr; + convexNr = conNr; + normal = n; + } + } + } + + return actorNr >= 0; +} + +//----------------------------------------------------------------------------- +bool SimScene::pickStart(const PxVec3 &orig, const PxVec3 &dir) +{ + float dist; + int actorNr, compoundNr, convexNr; + PxVec3 normal; + + if (!rayCast(orig, dir, dist, actorNr, compoundNr, convexNr, normal)) + return false; + + mPickActor = mActors[(uint32_t)actorNr]->mCompounds[(uint32_t)compoundNr]->getPxActor(); + mPickPos = orig + dir * dist; + mPickLocalPos = mPickActor->getGlobalPose().transformInv(mPickPos); + mPickDepth = dist; + return true; +} + +//----------------------------------------------------------------------------- +void SimScene::pickMove(const PxVec3 &orig, const PxVec3 &dir) +{ + if (mPickActor == NULL) + return; + + mPickPos = orig + dir * mPickDepth; +} + +//----------------------------------------------------------------------------- +void SimScene::pickRelease() +{ + mPickActor = NULL; +} + +// -------------------------------------------------------------------------------------------- +bool SimScene::patternFracture(const PxVec3 &orig, const PxVec3 &dir, const PxMat33 patternTransform, float impactRadius, float radialImpulse, float directionalImpulse) +{ + float dist; + //float objectSize = 0.0f; + int actorNr; + int compoundNr; + int convexNr; + PxVec3 normal; + + if (!rayCast(orig, dir, dist, actorNr, compoundNr, convexNr, normal)) + return false; + + return mActors[(uint32_t)actorNr]->patternFracture(orig+dist*dir,normal,compoundNr,patternTransform,impactRadius,radialImpulse,directionalImpulse); +} + +bool SimScene::findCompound(const Compound* c, int& actorNr, int& compoundNr) +{ + actorNr = -1; + compoundNr = -1; + for(uint32_t i = 0; i < mActors.size(); i++) + { + if (mActors[i]->findCompound(c,compoundNr)) + { + actorNr = (int32_t)i; + return true; + } + } + return false; +} + +// -------------------------------------------------------------------------------------------- +void SimScene::processFractureEvents(bool& valid,bool* addFireDustP) +{ + valid = false; + debugPoints.clear(); + int numPieces = 0; + + if (mFractureEvents.size() <= 0) + return; + + nvidia::Array<Compound*> compounds; + ++mSceneVersion; + + float objectSize = 0.0f; + + // here the fracture pattern could be randomized + float scale = 1.0f; + PxMat33 fractureTransform; + fractureTransform = PxMat33(PxIdentity); + fractureTransform *= scale; + + bool addFireDust = false; + + for (uint32_t i = 0; i < mFractureEvents.size(); i++) { + const FractureEvent &e = mFractureEvents[i]; + + if (!e.compound->patternFracture(e.pos, mMinConvexSize, compounds, fractureTransform, debugPoints, mContactImpactRadius, + e.additionalRadialImpulse, -e.normal * e.additionalNormalImpulse)) + continue; + + if (e.additionalNormalImpulse > 0.0f || e.additionalRadialImpulse > 0.0f) { + addFireDust = true; + playSound("explosion", 1); + } + else { +// playSound("explosion", 1); + } + + if (compounds.empty()) + continue; + + PxBounds3 bounds; + e.compound->getWorldBounds(bounds); + float size = bounds.getDimensions().magnitude(); + if (size > objectSize) + objectSize = size; + + for (uint32_t j = 0; j < compounds.size(); j++) { + PxRigidDynamic *a = compounds[j]->getPxActor(); +// a->setContactReportFlags(Px_NOTIFY_ON_TOUCH_FORCE_THRESHOLD); + a->setContactReportThreshold(mFractureForceThreshold); + } + + //int compoundNr = 0; + //while (compoundNr < (int)mCompounds.size() && mCompounds[compoundNr] != e.compound) + // compoundNr++; + + //int first = 0; + //if (compoundNr < (int)mCompounds.size()) { + // mCompounds[compoundNr] = compounds[0]; + // first++; + //} + + int first = 0; + int actorNr = 0; + int compoundNr = 0; + if (findCompound(e.compound,actorNr,compoundNr) ) + { + mActors[(uint32_t)actorNr]->mCompounds[(uint32_t)compoundNr] = compounds[0]; + first++; + } + + if (e.compound->getPxActor() == mPickActor) + mPickActor = NULL; + + e.compound->clear(); + //delCompoundList.push_back(e.compound); + delCompoundList.pushBack(e.compound); + + //delete e.compound; + + for (int j = first; j < (int)compounds.size(); j++) + mActors[(uint32_t)actorNr]->mCompounds.pushBack(compounds[(uint32_t)j]); + + numPieces += compounds.size(); + } + + mFractureEvents.clear(); + + if (objectSize > 0.0f) { + // playShatterSound(objectSize); + mNoFractureFrames = mNumNoFractureFrames; + } + if(addFireDustP) + { + *addFireDustP = addFireDust; + } + valid = true; + return; +} + +void SimScene::onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, uint32_t nbPairs) +{ + // Pass along to application's callback, if defined + if (mAppNotify != NULL) + { + mAppNotify->onContact(pairHeader, pairs, nbPairs); + } + + if (mNoFractureFrames > 0) + return; + + for (int i = 0; i < (int)nbPairs; i++) { + + const PxContactPair &pair = pairs[i]; + uint32_t num = pair.contactCount; + if (num == 0) + continue; + + mContactPoints.resize(num); + pairs[i].extractContacts(&mContactPoints[0], num); + + // pick first point (arbitrary) + Convex* convexes[2]; + convexes[0] = findConvexForShape(*pair.shapes[0]); + convexes[1] = findConvexForShape(*pair.shapes[1]); + + PxVec3 &pos = mContactPoints[0].position; + PxVec3 &normal = mContactPoints[0].normal; + + PxVec3 relVel(0.0f, 0.0f, 0.0f); + + for (int j = 0; j < 2; j++) { + if (convexes[j] == NULL) + continue; + PxRigidDynamic *a = convexes[j]->getParent()->getPxActor(); + PxVec3 v = PxRigidBodyExt::getVelocityAtPos(*a, pos); + relVel += (j == 0) ? v : -v; + } + + float normalImpulse = 0; + float radialImpulse = 0; + for (int j = 0; j < 2; j++) { + if (convexes[j] != NULL) { + normalImpulse = PxMax(normalImpulse, convexes[j]->getParent()->getAdditionalImpactNormalImpulse()); + radialImpulse = PxMax(radialImpulse, convexes[j]->getParent()->getAdditionalImpactRadialImpulse()); + } + } + + for (int j = 0; j < 2; j++) { + Convex *c = convexes[j]; + if (c == NULL) + continue; + if (relVel.magnitude() < REL_VEL_FRACTURE_THRESHOLD) + continue; + + Compound *compound = c->getParent(); + + FractureEvent e; + e.init(); + e.compound = compound; + e.pos = pos; + e.normal = normal; + e.withStatic = (convexes[1-j] == NULL); + e.additionalNormalImpulse = normalImpulse; + e.additionalRadialImpulse = radialImpulse; + + uint32_t k = 0; + while (k < mFractureEvents.size() && mFractureEvents[k].compound != compound) + k++; + + if (k < mFractureEvents.size()) { + if (mFractureEvents[k].withStatic && !e.withStatic) // prioritize dynamic collisions + mFractureEvents[k] = e; + } + else + mFractureEvents.pushBack(e); + } + } +} + +void SimScene::onAdvance(const PxRigidBody*const* bodyBuffer, const PxTransform* poseBuffer, const PxU32 count) +{ + PX_UNUSED(bodyBuffer); + PX_UNUSED(poseBuffer); + PX_UNUSED(count); +} + +void SimScene::onTrigger(PxTriggerPair* pairs, uint32_t count) +{ + // Pass along to application's callback, if defined + if (mAppNotify != NULL) + { + mAppNotify->onTrigger(pairs, count); + } +} + +void SimScene::onWake(PxActor** actors, uint32_t count) +{ + // Pass along to application's callback, if defined + if (mAppNotify != NULL) + { + mAppNotify->onWake(actors, count); + } +} + +void SimScene::onSleep(PxActor** actors, uint32_t count) +{ + // Pass along to application's callback, if defined + if (mAppNotify != NULL) + { + mAppNotify->onSleep(actors, count); + } +} + +void SimScene::onConstraintBreak(physx::PxConstraintInfo* constraints, uint32_t count) +{ + // Pass along to application's callback, if defined + if (mAppNotify != NULL) + { + mAppNotify->onConstraintBreak(constraints, count); + } +} + +nvidia::Array<PxVec3>& SimScene::getDebugPoints() { + return debugPoints; +} + +bool SimScene::mapShapeToConvex(const PxShape& shape, Convex& convex) +{ + return mShapeMap.insert(&shape, &convex); +} + +bool SimScene::unmapShape(const PxShape& shape) +{ + return mShapeMap.erase(&shape); +} + +Convex* SimScene::findConvexForShape(const PxShape& shape) +{ + const shdfnd::HashMap<const PxShape*, Convex*>::Entry* entry = mShapeMap.find(&shape); + return entry != NULL ? entry->second : NULL; // Since we don't expect *entry to be NULL, we shouldn't lose information here +} + +} +} +} + +#endif diff --git a/APEX_1.4/module/destructible/fracture/Core/SimSceneBase.h b/APEX_1.4/module/destructible/fracture/Core/SimSceneBase.h new file mode 100644 index 00000000..2170c19e --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Core/SimSceneBase.h @@ -0,0 +1,271 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef SIM_SCENE_BASE +#define SIM_SCENE_BASE + +#include "PxSimulationEventCallback.h" +#include <PsArray.h> +#include <PsUserAllocated.h> +#include <PsHashMap.h> + +#include "RTdef.h" + +namespace nvidia +{ +namespace fracture +{ +namespace base +{ + +class Actor; +class Compound; +class Convex; +class FracturePattern; +class CompoundCreator; +class Delaunay2d; +class Delaunay3d; +class PolygonTriangulator; +class IslandDetector; +class MeshClipper; + +// ----------------------------------------------------------------------------------- +class SimScene : + public PxSimulationEventCallback, public UserAllocated +{ + friend class Actor; +public: + static SimScene* createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, PxScene *scene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath); +protected: + SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, PxScene *scene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath); +public: + // Allow the Destructible module to release things in a proper order + void restoreUserCallbacks(); + virtual ~SimScene(); + + // Creates Scene Level Singletons + virtual void createSingletons(); + // Access singletons + CompoundCreator* getCompoundCreator() {return mCompoundCreator;} + Delaunay2d* getDelaunay2d() {return mDelaunay2d;} + Delaunay3d* getDelaunay3d() {return mDelaunay3d;} + PolygonTriangulator* getPolygonTriangulator() {return mPolygonTriangulator;} + IslandDetector* getIslandDetector() {return mIslandDetector;} + MeshClipper* getMeshClipper() {return mMeshClipper;} + + // Create non-Singletons + virtual Actor* createActor(); + virtual Convex* createConvex(); + virtual Compound* createCompound(const FracturePattern *pattern, const FracturePattern *secondaryPattern = NULL, float contactOffset = 0.005f, float restOffset = -0.001f); + virtual FracturePattern* createFracturePattern(); + virtual void clear(); + void addCompound(Compound *m); + void removeCompound(Compound *m); + // perform deferred deletion + void deleteCompounds(); + // + bool findCompound(const Compound* c, int& actorNr, int& compoundNr); + + void removeActor(Actor* a); + + // Profiler hooks + virtual void profileBegin(const char* /*name*/) {} + virtual void profileEnd(const char* /*name*/) {} + + bool rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &actorNr, int &compoundNr, int &convexNr, PxVec3 &normal) const; + + bool patternFracture(const PxVec3 &orig, const PxVec3 &dir, + const PxMat33 patternTransform, float impactRadius = 0.0f, float radialImpulse = 0.0f, float directionalImpulse = 0.0f); + + virtual void playSound(const char * /*name*/, int /*nr*/ = -1) {} + + // accessors + nvidia::Array<Compound*> getCompounds(); //{ return mCompounds; } + nvidia::Array<Actor*> getActors() { return mActors; } + PxPhysics* getPxPhysics() { return mPxPhysics; } + PxCooking* getPxCooking() { return mPxCooking; } + PxScene* getScene() { return mScene; } + + //ConvexRenderer &getConvexRenderer() { return mConvexRenderer; } + + void preSim(float dt); + void postSim(float dt); //, RegularCell3D* fluidSim); + + void setPlaySounds(bool play) { mPlaySounds = play; } + void setContactImpactRadius(float radius) { mContactImpactRadius = radius; } + void setNumNoFractureFrames(int num) { mNumNoFractureFrames = num; } + + void setCamera(const PxVec3 &pos, const PxVec3 &dir, const PxVec3 &up, float fov ) { + mCameraPos = pos; mCameraDir = dir; mCameraUp = up; mCameraFov = fov; + } + + //void draw(bool useShader, Shader* particleShader = NULL) {} + //void setShaderMaterial(Shader* shader, const ShaderMaterial& mat) {this->mShader = shader; this->mShaderMat = mat;} + //void setFractureForceThreshold(float threshold) { mFractureForceThreshold = threshold; } + + PxMaterial *getPxDefaultMaterial() { return mPxDefaultMaterial; } + + void toggleDebugDrawing() { mDebugDraw = !mDebugDraw; } + + virtual bool pickStart(const PxVec3 &orig, const PxVec3 &dir); + virtual void pickMove(const PxVec3 &orig, const PxVec3 &dir); + virtual void pickRelease(); + PxRigidDynamic* getPickActor() { return mPickActor; } + const PxVec3 &getPickPos() { return mPickPos; } + const PxVec3 &getPickLocalPos() { return mPickLocalPos; } + + // callback interface + + void onContactNotify(unsigned int arraySizes, void ** shape0Array, void ** shape1Array, void ** actor0Array, void ** actor1Array, float * positionArray, float * normalArray); + void onConstraintBreak(physx::PxConstraintInfo* constraints, uint32_t count); + void onWake(PxActor** actors, uint32_t count); + void onSleep(PxActor** actors, uint32_t count); + void onTrigger(physx::PxTriggerPair* pairs, uint32_t count); + void onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, uint32_t nbPairs); + void onAdvance(const PxRigidBody*const* bodyBuffer, const PxTransform* poseBuffer, const PxU32 count); + + void toggleRenderDebris() {mRenderDebris = !mRenderDebris;} + bool getRenderDebrs() {return mRenderDebris;} + //virtual void dumpSceneGeometry() {} + nvidia::Array<PxVec3>& getDebugPoints(); + //virtual void createRenderBuffers() {} + //void loadAndCreateTextureArrays(); + + nvidia::Array<PxVec3>& getCrackNormals() {return crackNormals;} + nvidia::Array<PxVec3>& getTmpPoints() {return tmpPoints;} + + bool mapShapeToConvex(const PxShape& shape, Convex& convex); + bool unmapShape(const PxShape& shape); + Convex* findConvexForShape(const PxShape& shape); + bool owns(const PxShape& shape) {return NULL != findConvexForShape(shape);} + +protected: + //virtual void create3dTexture() {} + //virtual void updateConvexesTex() {} + //void playShatterSound(float objectSize); + + void addActor(Actor* a); // done internally upon creation + + PxPhysics *mPxPhysics; + PxCooking *mPxCooking; + PxScene *mScene; + const char *mResourcePath; + bool mPlaySounds; + + //nvidia::Array<Compound*> mCompounds; + nvidia::Array<Actor*> mActors; + + float mFractureForceThreshold; + float mContactImpactRadius; + + nvidia::Array<physx::PxContactPairPoint> mContactPoints; + struct FractureEvent { + void init() { + compound = NULL; + pos = normal = PxVec3(0.0f, 0.0f, 0.0f); + additionalRadialImpulse = additionalNormalImpulse = 0.0f; + withStatic = false; + } + Compound *compound; + PxVec3 pos; + PxVec3 normal; + float additionalRadialImpulse; + float additionalNormalImpulse; + bool withStatic; + }; + nvidia::Array<FractureEvent> mFractureEvents; + void processFractureEvents(bool& valid,bool* addFireDust = NULL); + + struct RenderBuffers { + void init() { + numVertices = 0; numIndices = 0; + VBO = 0; IBO = 0; matTex = 0; volTex = 0; + texSize = 0; numConvexes = -1; + } + nvidia::Array<float> tmpVertices; + nvidia::Array<unsigned int> tmpIndices; + nvidia::Array<float> tmpTexCoords; + int numVertices, numIndices; + unsigned int VBO; + unsigned int IBO; + unsigned int volTex; + unsigned int matTex; + int texSize; + int numConvexes; + }; + RenderBuffers mRenderBuffers; + unsigned int mSceneVersion; // changed on each update + unsigned int mRenderBufferVersion; // to handle updates + unsigned int mOptixBufferVersion; // to handle updates + + PxMaterial *mPxDefaultMaterial; + + //ConvexRenderer mConvexRenderer; + + int mNoFractureFrames; + int mNoSoundFrames; + int mFrameNr; + bool mDebugDraw; + + float mPickDepth; + PxRigidDynamic *mPickActor; + PxVec3 mPickPos; + PxVec3 mPickLocalPos; + + float mMinConvexSize; + int mNumNoFractureFrames; // > 1 to prevent a slow down by too many fracture events + + PxVec3 mCameraPos, mCameraDir, mCameraUp; + float mCameraFov; + + float bumpTextureUVScale; + float extraNoiseScale; + float roughnessScale; + + float particleBumpTextureUVScale; + float particleRoughnessScale; + float particleExtraNoiseScale; + nvidia::Array<PxVec3> debugPoints; + bool mRenderDebris; + + PxSimulationEventCallback* mAppNotify; + + //GLuint diffuseTexArray, bumpTexArray, specularTexArray, emissiveReflectSpecPowerTexArray; + + //GLuint loadTextureArray(std::vector<std::string>& names); + + //Singletons + CompoundCreator* mCompoundCreator; + Delaunay2d* mDelaunay2d; + Delaunay3d* mDelaunay3d; + PolygonTriangulator* mPolygonTriangulator; + IslandDetector* mIslandDetector; + MeshClipper* mMeshClipper; + + //Array for use by Compound (effectively static) + nvidia::Array<PxVec3> crackNormals; + nvidia::Array<PxVec3> tmpPoints; + + // Deferred Deletion list + nvidia::Array<Compound*> delCompoundList; + + // Map used to determine SimScene ownership of shape + shdfnd::HashMap<const PxShape*,Convex*> mShapeMap; +}; + +} +} +} + +#endif +#endif diff --git a/APEX_1.4/module/destructible/fracture/Delaunay2d.cpp b/APEX_1.4/module/destructible/fracture/Delaunay2d.cpp new file mode 100644 index 00000000..efa26e4d --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Delaunay2d.cpp @@ -0,0 +1,24 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "Delaunay2d.h" + +namespace nvidia +{ +namespace fracture +{ + +} +} + +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Delaunay2d.h b/APEX_1.4/module/destructible/fracture/Delaunay2d.h new file mode 100644 index 00000000..7776214e --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Delaunay2d.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef DELAUNAY_2D_H +#define DELAUNAY_2D_H + +#include <PxVec3.h> +#include <PsArray.h> + +#include "Delaunay2dBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class Delaunay2d : public base::Delaunay2d +{ + friend class SimScene; +protected: + Delaunay2d(base::SimScene* scene): base::Delaunay2d((base::SimScene*)scene) {} +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Delaunay3d.cpp b/APEX_1.4/module/destructible/fracture/Delaunay3d.cpp new file mode 100644 index 00000000..2ab81157 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Delaunay3d.cpp @@ -0,0 +1,23 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "Delaunay3d.h" + +namespace nvidia +{ +namespace fracture +{ + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Delaunay3d.h b/APEX_1.4/module/destructible/fracture/Delaunay3d.h new file mode 100644 index 00000000..628e071d --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Delaunay3d.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef DELAUNAY_3D_H +#define DELAUNAY_3D_H + +#include <PxVec3.h> +#include <PsArray.h> + +#include "CompoundGeometry.h" + +#include "Delaunay3dBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class Delaunay3d : public base::Delaunay3d +{ + friend class SimScene; +protected: + Delaunay3d(base::SimScene* scene): base::Delaunay3d((base::SimScene*)scene) {} +}; + +} +} + +#endif +#endif diff --git a/APEX_1.4/module/destructible/fracture/FracturePattern.cpp b/APEX_1.4/module/destructible/fracture/FracturePattern.cpp new file mode 100644 index 00000000..08133f41 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/FracturePattern.cpp @@ -0,0 +1,17 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "FracturePattern.h" + +// Empty until base has code proven to be non-portable +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/FracturePattern.h b/APEX_1.4/module/destructible/fracture/FracturePattern.h new file mode 100644 index 00000000..ddf9911b --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/FracturePattern.h @@ -0,0 +1,45 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef FRACTURE_PATTERN +#define FRACTURE_PATTERN + +#include "Delaunay3d.h" +#include "Delaunay2d.h" +#include "CompoundGeometry.h" +#include "PxTransform.h" +#include "PxBounds3.h" + +#include "FracturePatternBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class Convex; +class Compound; +class CompoundGeometry; + +class FracturePattern : public base::FracturePattern +{ + friend class SimScene; +protected: + FracturePattern(base::SimScene* scene): base::FracturePattern((base::SimScene*)scene) {} +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/IceBoxPruning.cpp b/APEX_1.4/module/destructible/fracture/IceBoxPruning.cpp new file mode 100644 index 00000000..65ecc1b6 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/IceBoxPruning.cpp @@ -0,0 +1,25 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "IceBoxPruning.h" + +// Empty until base has code proven to be non-portable + +namespace nvidia +{ +namespace fracture +{ + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/IceBoxPruning.h b/APEX_1.4/module/destructible/fracture/IceBoxPruning.h new file mode 100644 index 00000000..b5d2f0f1 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/IceBoxPruning.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef ICEBOXPRUNING_H +#define ICEBOXPRUNING_H + +#include "IceRevisitedRadix.h" +#include "PxVec3.h" +#include "PxBounds3.h" + +#include "IceBoxPruningBase.h" + +namespace nvidia +{ +namespace fracture +{ + +struct Axes : public base::Axes +{ +}; + +class BoxPruning : public base::BoxPruning +{ + +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/IceRevisitedRadix.cpp b/APEX_1.4/module/destructible/fracture/IceRevisitedRadix.cpp new file mode 100644 index 00000000..331c7ee6 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/IceRevisitedRadix.cpp @@ -0,0 +1,23 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "IceRevisitedRadix.h" + +namespace nvidia +{ +namespace fracture +{ + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/IceRevisitedRadix.h b/APEX_1.4/module/destructible/fracture/IceRevisitedRadix.h new file mode 100644 index 00000000..19bc8d25 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/IceRevisitedRadix.h @@ -0,0 +1,32 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef ICERADIXSORT_H +#define ICERADIXSORT_H + +#include "IceRevisitedRadixBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class RadixSort : public nvidia::fracture::base::RadixSort +{ +}; + +} +} + +#endif // __ICERADIXSORT_H__ +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/IslandDetector.cpp b/APEX_1.4/module/destructible/fracture/IslandDetector.cpp new file mode 100644 index 00000000..c09dfa80 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/IslandDetector.cpp @@ -0,0 +1,23 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "IslandDetector.h" + +namespace nvidia +{ +namespace fracture +{ + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/IslandDetector.h b/APEX_1.4/module/destructible/fracture/IslandDetector.h new file mode 100644 index 00000000..889e5050 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/IslandDetector.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef ISLAND_DETECTOR_H +#define ISLAND_DETECTOR_H + +#include <PxVec3.h> +#include <PsArray.h> +#include "IceBoxPruning.h" + +#include "IslandDetectorBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class IslandDetector : public base::IslandDetector +{ + friend class SimScene; +protected: + IslandDetector(base::SimScene* scene): base::IslandDetector((base::SimScene*)scene) {} +}; + +} +} + +#endif +#endif diff --git a/APEX_1.4/module/destructible/fracture/Mesh.cpp b/APEX_1.4/module/destructible/fracture/Mesh.cpp new file mode 100644 index 00000000..04ffbbd8 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Mesh.cpp @@ -0,0 +1,125 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include <RenderMeshAsset.h> + +#include "Mesh.h" + +namespace nvidia +{ +namespace fracture +{ + +void Mesh::gatherPartMesh(Array<PxVec3>& vertices, + nvidia::Array<uint32_t>& indices, + nvidia::Array<PxVec3>& normals, + nvidia::Array<PxVec2>& texcoords, + nvidia::Array<SubMesh>& subMeshes, + const RenderMeshAsset& renderMeshAsset, + uint32_t partIndex) + +{ + if (partIndex >= renderMeshAsset.getPartCount()) + { + vertices.resize(0); + indices.resize(0); + normals.resize(0); + texcoords.resize(0); + subMeshes.resize(0); + return; + } + + subMeshes.resize(renderMeshAsset.getSubmeshCount()); + + // Pre-count vertices and indices so we can allocate once + uint32_t vertexCount = 0; + uint32_t indexCount = 0; + for (uint32_t submeshIndex = 0; submeshIndex < renderMeshAsset.getSubmeshCount(); ++submeshIndex) + { + const RenderSubmesh& submesh = renderMeshAsset.getSubmesh(submeshIndex); + vertexCount += submesh.getVertexCount(partIndex); + indexCount += submesh.getIndexCount(partIndex); + } + + vertices.resize(vertexCount); + normals.resize(vertexCount); + texcoords.resize(vertexCount); + indices.resize(indexCount); + + vertexCount = 0; + indexCount = 0; + for (uint32_t submeshIndex = 0; submeshIndex < renderMeshAsset.getSubmeshCount(); ++submeshIndex) + { + const RenderSubmesh& submesh = renderMeshAsset.getSubmesh(submeshIndex); + const uint32_t submeshVertexCount = submesh.getVertexCount(partIndex); + if (submeshVertexCount > 0) + { + const VertexBuffer& vertexBuffer = submesh.getVertexBuffer(); + const VertexFormat& vertexFormat = vertexBuffer.getFormat(); + + enum { MESH_SEMANTIC_COUNT = 3 }; + struct { + RenderVertexSemantic::Enum semantic; + RenderDataFormat::Enum format; + uint32_t sizeInBytes; + void* dstBuffer; + } semanticData[MESH_SEMANTIC_COUNT] = { + { RenderVertexSemantic::POSITION, RenderDataFormat::FLOAT3, sizeof(PxVec3), &vertices[vertexCount] }, + { RenderVertexSemantic::NORMAL, RenderDataFormat::FLOAT3, sizeof(PxVec3), &normals[vertexCount] }, + { RenderVertexSemantic::TEXCOORD0, RenderDataFormat::FLOAT2, sizeof(PxVec2), &texcoords[vertexCount] } + }; + + for (uint32_t i = 0; i < MESH_SEMANTIC_COUNT; ++i) + { + const int32_t bufferIndex = vertexFormat.getBufferIndexFromID(vertexFormat.getSemanticID(semanticData[i].semantic)); + if (bufferIndex >= 0) + vertexBuffer.getBufferData(semanticData[i].dstBuffer, + semanticData[i].format, + semanticData[i].sizeInBytes, + (uint32_t)bufferIndex, + submesh.getFirstVertexIndex(partIndex), + submesh.getVertexCount(partIndex)); + else + memset(semanticData[i].dstBuffer, 0, submesh.getVertexCount(partIndex)*semanticData[i].sizeInBytes); + } + + /* + const uint32_t firstVertexIndex = submesh.getFirstVertexIndex(partIndex); + fillBuffer<PxVec3>(vertexBuffer, vertexFormat, RenderVertexSemantic::POSITION, RenderDataFormat::FLOAT3, + firstVertexIndex, submeshVertexCount, &vertices[vertexCount]); + fillBuffer<PxVec3>(vertexBuffer, vertexFormat, RenderVertexSemantic::NORMAL, RenderDataFormat::FLOAT3, + firstVertexIndex, submeshVertexCount, &normals[vertexCount]); + fillBuffer<PxVec2>(vertexBuffer, vertexFormat, RenderVertexSemantic::TEXCOORD0, RenderDataFormat::FLOAT2, + firstVertexIndex, submeshVertexCount, &texcoords[vertexCount]);*/ + + const uint32_t* partIndexBuffer = submesh.getIndexBuffer(partIndex); + const uint32_t partIndexCount = submesh.getIndexCount(partIndex); + subMeshes[submeshIndex].firstIndex = (int32_t)partIndexCount; + for (uint32_t indexNum = 0; indexNum < partIndexCount; ++indexNum) + { + indices[indexCount++] = partIndexBuffer[indexNum] + vertexCount - submesh.getFirstVertexIndex(partIndex); + } + vertexCount += submeshVertexCount; + } + } +} + + +void Mesh::loadFromRenderMesh(const RenderMeshAsset& mesh, uint32_t partIndex) +{ + gatherPartMesh(mVertices, mIndices, mNormals, mTexCoords, mSubMeshes, mesh, partIndex); +} + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Mesh.h b/APEX_1.4/module/destructible/fracture/Mesh.h new file mode 100644 index 00000000..59231566 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Mesh.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef MESH +#define MESH + +#include <PxVec3.h> +#include <PsArray.h> +#include <PsAllocator.h> + +#include "MeshBase.h" + +namespace nvidia +{ +namespace apex +{ + class RenderMeshAsset; +} +} + +namespace nvidia +{ +namespace fracture +{ + +using namespace ::nvidia::shdfnd; + +class Mesh : public base::Mesh +{ +public: + void loadFromRenderMesh(const apex::RenderMeshAsset& mesh, uint32_t partIndex); +protected: + static void gatherPartMesh(Array<PxVec3>& vertices, Array<uint32_t>& indices, Array<PxVec3>& normals, + Array<PxVec2>& texcoords, nvidia::Array<SubMesh>& subMeshes, const apex::RenderMeshAsset& renderMeshAsset, uint32_t partIndex); +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/MeshClipper.cpp b/APEX_1.4/module/destructible/fracture/MeshClipper.cpp new file mode 100644 index 00000000..b5e42b7a --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/MeshClipper.cpp @@ -0,0 +1,23 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "MeshClipper.h" + +namespace nvidia +{ +namespace fracture +{ + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/MeshClipper.h b/APEX_1.4/module/destructible/fracture/MeshClipper.h new file mode 100644 index 00000000..e52d5f3d --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/MeshClipper.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef MESH_CLIPPER_H +#define MESH_CLIPPER_H + +#include <PxVec3.h> +#include <PsArray.h> +#include <PxTransform.h> +#include <PxBounds3.h> + +#include "MeshClipperBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class MeshClipper : public base::MeshClipper +{ + friend class SimScene; +protected: + MeshClipper(base::SimScene* scene): base::MeshClipper((base::SimScene*)scene) {} +}; + +} +} + +#endif +#endif diff --git a/APEX_1.4/module/destructible/fracture/PolygonTriangulator.cpp b/APEX_1.4/module/destructible/fracture/PolygonTriangulator.cpp new file mode 100644 index 00000000..c8012cdd --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/PolygonTriangulator.cpp @@ -0,0 +1,23 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "PolygonTriangulator.h" + +namespace nvidia +{ +namespace fracture +{ + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/PolygonTriangulator.h b/APEX_1.4/module/destructible/fracture/PolygonTriangulator.h new file mode 100644 index 00000000..3d142351 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/PolygonTriangulator.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef POLYGON_TRIANGULATOR_H +#define POLYGON_TRIANGULATOR_H + +#include <PxVec3.h> +#include <PsArray.h> + +#include "PolygonTriangulatorBase.h" + +namespace nvidia +{ +namespace fracture +{ + +class PolygonTriangulator : public base::PolygonTriangulator +{ + friend class SimScene; +protected: + PolygonTriangulator(base::SimScene* scene): base::PolygonTriangulator((base::SimScene*)scene) {} +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/RTdef.h b/APEX_1.4/module/destructible/fracture/RTdef.h new file mode 100644 index 00000000..0a8b9561 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/RTdef.h @@ -0,0 +1,26 @@ +/* + * 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. + */ + + +// This file exists primarily for APEX integration + +#ifndef RT_DEF_H +#define RT_DEF_H + +#include "ApexDefs.h" +#include "ModuleDestructible.h" + +#if APEX_RUNTIME_FRACTURE +#define RT_COMPILE 1 +#else +#define RT_COMPILE 0 +#endif + +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Renderable.cpp b/APEX_1.4/module/destructible/fracture/Renderable.cpp new file mode 100644 index 00000000..5e8ba01b --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Renderable.cpp @@ -0,0 +1,467 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include "DestructibleActorImpl.h" + +#include "Actor.h" +#include "Compound.h" +#include "Convex.h" + +#include "../fracture/Renderable.h" + +namespace nvidia +{ +namespace fracture +{ + +Renderable::Renderable(): + mVertexBuffer(NULL), + mIndexBuffer(NULL), + mBoneBuffer(NULL), + mVertexBufferSize(0), + mIndexBufferSize(0), + mBoneBufferSize(0), + mVertexBufferSizeLast(0), + mIndexBufferSizeLast(0), + mBoneBufferSizeLast(0), + mFullBufferDirty(true), + valid(false) +{ + +} + +Renderable::~Renderable() +{ + UserRenderResourceManager* rrm = GetInternalApexSDK()->getUserRenderResourceManager(); + if (mVertexBuffer != NULL ) + { + rrm->releaseVertexBuffer(*mVertexBuffer); + } + if (mIndexBuffer != NULL ) + { + rrm->releaseIndexBuffer(*mIndexBuffer); + } + if (mBoneBuffer != NULL) + { + rrm->releaseBoneBuffer(*mBoneBuffer); + } + for (uint32_t k = 0; k < mConvexGroups.size(); k++) + { + ConvexGroup& g = mConvexGroups[k]; + for (uint32_t j = 0; j < g.mSubMeshes.size(); j++) + { + SubMesh& s = g.mSubMeshes[j]; + if(s.renderResource != NULL) + { + rrm->releaseResource(*s.renderResource); + s.renderResource = NULL; + } + } + } +} + +void Renderable::updateRenderResources(bool rewriteBuffers, void* userRenderData) +{ + UserRenderResourceManager* rrm = GetInternalApexSDK()->getUserRenderResourceManager(); + ResourceProviderIntl* nrp = GetInternalApexSDK()->getInternalResourceProvider(); + + PX_ASSERT(rrm != NULL && nrp != NULL); + if (rrm == NULL || nrp == NULL || mConvexGroups.empty()) + { + valid = false; + return; + } + + if (rewriteBuffers) + { + mFullBufferDirty = true; + } + + // Resize buffers if necessary: TODO: intelligently oversize + // vertex buffer + if (mVertexBufferSize > mVertexBufferSizeLast) + { + if (mVertexBuffer != NULL ) + { + rrm->releaseVertexBuffer(*mVertexBuffer); + } + { + UserRenderVertexBufferDesc desc; + desc.uvOrigin = nvidia::apex::TextureUVOrigin::ORIGIN_BOTTOM_LEFT; + desc.hint = RenderBufferHint::DYNAMIC; + desc.maxVerts = mVertexBufferSize; + desc.buffersRequest[RenderVertexSemantic::POSITION] = RenderDataFormat::FLOAT3; + desc.buffersRequest[RenderVertexSemantic::NORMAL] = RenderDataFormat::FLOAT3; + desc.buffersRequest[RenderVertexSemantic::TEXCOORD0] = RenderDataFormat::FLOAT2; + desc.buffersRequest[RenderVertexSemantic::BONE_INDEX] = RenderDataFormat::USHORT1; + mVertexBuffer = rrm->createVertexBuffer(desc); + PX_ASSERT(mVertexBuffer); + } + mFullBufferDirty = true; + } + // index buffer + if (mIndexBufferSize > mIndexBufferSizeLast) + { + if (mIndexBuffer != NULL ) + { + rrm->releaseIndexBuffer(*mIndexBuffer); + } + UserRenderIndexBufferDesc desc; + desc.hint = RenderBufferHint::DYNAMIC; + desc.maxIndices = mIndexBufferSize; + desc.format = RenderDataFormat::UINT1; + mIndexBuffer = rrm->createIndexBuffer(desc); + PX_ASSERT(mIndexBuffer); + mFullBufferDirty = true; + } + // bone buffer + if (mBoneBufferSize > mBoneBufferSizeLast) + { + if (mBoneBuffer != NULL) + { + rrm->releaseBoneBuffer(*mBoneBuffer); + } + UserRenderBoneBufferDesc desc; + desc.hint = RenderBufferHint::DYNAMIC; + desc.maxBones = mBoneBufferSize; + desc.buffersRequest[RenderBoneSemantic::POSE] = RenderDataFormat::FLOAT3x4; + mBoneBuffer = rrm->createBoneBuffer(desc); + PX_ASSERT(mBoneBuffer); + mFullBufferDirty = true; + } + // Fill buffers + if (mFullBufferDirty) + { + uint32_t vertexIdx = 0; + uint32_t indexIdx = 0; + uint32_t boneIdx = 0; + for (uint32_t k = 0; k < mConvexGroups.size(); k++) + { + ConvexGroup& g = mConvexGroups[k]; + for (uint32_t j = 0; j < g.mSubMeshes.size(); j++) + { + SubMesh& s = g.mSubMeshes[j]; + if(s.renderResource != NULL) + { + rrm->releaseResource(*s.renderResource); + s.renderResource = NULL; + } + UserRenderResourceDesc desc; + desc.primitives = RenderPrimitiveType::TRIANGLES; + // configure vertices + desc.vertexBuffers = &mVertexBuffer; + desc.numVertexBuffers = 1; + desc.numVerts = g.mVertexCache.size(); + desc.firstVertex = vertexIdx; + // configure indices; + desc.indexBuffer = mIndexBuffer; + desc.firstIndex = indexIdx; + desc.numIndices = s.mIndexCache.size(); + // configure bones; + desc.boneBuffer = mBoneBuffer; + desc.numBones = g.mBoneCache.size(); + desc.firstBone = boneIdx; + // configure other info + desc.material = nrp->getResource(mMaterialInfo[j].mMaterialID); + desc.submeshIndex = j; + desc.userRenderData = userRenderData; + // create + s.renderResource = rrm->createResource(desc); + PX_ASSERT(s.renderResource); + // copy indices into buffer + PX_ASSERT(indexIdx+s.mIndexCache.size() <= mIndexBufferSize); + mIndexBuffer->writeBuffer(s.mIndexCache.begin(),sizeof(*s.mIndexCache.begin()),indexIdx,s.mIndexCache.size()); + indexIdx += s.mIndexCache.size(); + } + // copy vertices and bones + { + RenderVertexBufferData data; + data.setSemanticData(RenderVertexSemantic::POSITION, g.mVertexCache.begin(), sizeof(*g.mVertexCache.begin()), RenderDataFormat::FLOAT3); + data.setSemanticData(RenderVertexSemantic::NORMAL, g.mNormalCache.begin(), sizeof(*g.mNormalCache.begin()), RenderDataFormat::FLOAT3); + data.setSemanticData(RenderVertexSemantic::TEXCOORD0, g.mTexcoordCache.begin(), sizeof(*g.mTexcoordCache.begin()), RenderDataFormat::FLOAT2); + data.setSemanticData(RenderVertexSemantic::BONE_INDEX,g.mBoneIndexCache.begin(),sizeof(*g.mBoneIndexCache.begin()),RenderDataFormat::USHORT1); + PX_ASSERT(vertexIdx + g.mVertexCache.size() <= mVertexBufferSize); + mVertexBuffer->writeBuffer(data,vertexIdx,g.mVertexCache.size()); + } + { + RenderBoneBufferData data; + data.setSemanticData(RenderBoneSemantic::POSE,g.mBoneCache.begin(),sizeof(*g.mBoneCache.begin()),RenderDataFormat::FLOAT4x4); + PX_ASSERT(boneIdx + g.mBoneCache.size() <= mBoneBufferSize); + mBoneBuffer->writeBuffer(data,boneIdx,g.mBoneCache.size()); + } + vertexIdx += g.mVertexCache.size(); + boneIdx += g.mBoneCache.size(); + } + mFullBufferDirty = false; + } + else // Bones only + { + uint32_t boneIdx = 0; + for (uint32_t k = 0; k < mConvexGroups.size(); k++) + { + ConvexGroup& g = mConvexGroups[k]; + { + RenderBoneBufferData data; + data.setSemanticData(RenderBoneSemantic::POSE,g.mBoneCache.begin(),sizeof(*g.mBoneCache.begin()),RenderDataFormat::FLOAT4x4); + mBoneBuffer->writeBuffer(data,boneIdx,g.mBoneCache.size()); + } + boneIdx += g.mBoneCache.size(); + } + } + mVertexBufferSizeLast = mVertexBufferSize; + mIndexBufferSizeLast = mIndexBufferSize; + mBoneBufferSizeLast = mBoneBufferSize; + valid = true; +} + +void Renderable::dispatchRenderResources(UserRenderer& api) +{ + if (!valid) + { + return; + } + RenderContext ctx; + ctx.local2world = PxMat44(PxIdentity); + ctx.world2local = PxMat44(PxIdentity); + for (uint32_t k = 0; k < mConvexGroups.size(); k++) + { + ConvexGroup& g = mConvexGroups[k]; + for (uint32_t j = 0; j < g.mSubMeshes.size(); j++) + { + SubMesh& s = g.mSubMeshes[j]; + if(s.renderResource && !s.mIndexCache.empty()) + { + ctx.renderResource = s.renderResource; + api.renderResource(ctx); + } + } + } +} + +// -----------------------Cache Update----------------------------------- +void Renderable::updateRenderCacheFull(Actor* actor) +{ + mVertexBufferSize = 0; + mIndexBufferSize = 0; + mBoneBufferSize = 0; + // Resize SubMeshes if necessary + const uint32_t numSubMeshes = actor->mActor->getRenderSubmeshCount(); + if( numSubMeshes == 0 ) + { + return; + } + if( numSubMeshes != mMaterialInfo.size() ) + { + mMaterialInfo.resize(numSubMeshes); + } + // grab material information + if (ResourceProviderIntl* nrp = GetInternalApexSDK()->getInternalResourceProvider()) + { + if (UserRenderResourceManager* rrm = GetInternalApexSDK()->getUserRenderResourceManager()) + { + ResID materialNS = GetInternalApexSDK()->getMaterialNameSpace(); + for(uint32_t i = 0; i < numSubMeshes; i++) + { + if(mMaterialInfo[i].mMaxBones == 0) + { + mMaterialInfo[i].mMaterialID = nrp->createResource(materialNS,actor->mActor->getDestructibleAsset()->getRenderMeshAsset()->getMaterialName(i),false); + mMaterialInfo[i].mMaxBones = rrm->getMaxBonesForMaterial(nrp->getResource(mMaterialInfo[i].mMaterialID)); + } + } + } + } + // Find bone limit + uint32_t maxBones = mMaterialInfo[0].mMaxBones; + for (uint32_t i = 1; i < mMaterialInfo.size(); i++) + { + if (mMaterialInfo[i].mMaxBones < maxBones) + { + maxBones = mMaterialInfo[i].mMaxBones; + } + } + //maxBones = 1; // TEMPORARY: FIXES TEXTURE MAPPING PROBLEM + //maxBones = rand(1,maxBones-1); + // Count Convexes + uint32_t numConvexes = 0; + const Array<base::Compound*>& compounds = actor->getCompounds(); + for (uint32_t k = 0; k < compounds.size(); k++) + { + const Array<base::Convex*>& convexes = compounds[k]->getConvexes(); + numConvexes += convexes.size(); + } + mBoneBufferSize += numConvexes; + + //maxBones is 0 when VTF rendering method is used for destructible(only) + if(maxBones == 0) + maxBones = mBoneBufferSize; + + // Create more groups if necessary + uint32_t numGroups = numConvexes/maxBones + ((numConvexes%maxBones)?1:0); + if (numGroups != mConvexGroups.size()) + { + mConvexGroups.resize(numGroups); + } + // Resize convex caches and subMeshes if necessary + for (uint32_t k = 0; k < mConvexGroups.size(); k++) + { + ConvexGroup& g = mConvexGroups[k]; + g.mConvexCache.clear(); + if( g.mConvexCache.capacity() <= maxBones ) + { + g.mConvexCache.reserve(maxBones); + } + if( g.mSubMeshes.size() != mMaterialInfo.size()) + { + g.mSubMeshes.resize(mMaterialInfo.size()); + } + } + // Populate convex cache + { + uint32_t idx = 0; + const Array<base::Compound*>& compounds = actor->getCompounds(); + for (uint32_t k = 0; k < compounds.size(); k++) + { + const Array<base::Convex*>& convexes = compounds[k]->getConvexes(); + for (uint32_t j = 0; j < convexes.size(); j++) + { + mConvexGroups[idx/maxBones].mConvexCache.pushBack((Convex*)convexes[j]); + idx++; + } + } + } + // Fill other caches + for (uint32_t k = 0; k < mConvexGroups.size(); k++) + { + ConvexGroup& g = mConvexGroups[k]; + // Calculate number of vertices + uint32_t numVertices = 0; + for (uint32_t j = 0; j < g.mConvexCache.size(); j++) + { + numVertices += g.mConvexCache[j]->getVisVertices().size(); + } + mVertexBufferSize += numVertices; + // Resize if necessary + g.mVertexCache.clear(); + g.mNormalCache.clear(); + g.mTexcoordCache.clear(); + g.mBoneIndexCache.clear(); + if (numVertices >= g.mVertexCache.capacity()) + { + g.mVertexCache.reserve(numVertices); + g.mNormalCache.reserve(numVertices); + g.mBoneIndexCache.reserve(numVertices); + g.mTexcoordCache.reserve(numVertices); + } + g.mBoneCache.clear(); + if (maxBones >= g.mBoneCache.capacity()) + { + g.mBoneCache.reserve(maxBones); + } + // Calculate index buffer sizes + for (uint32_t i = 0; i < g.mSubMeshes.size(); i++) + { + uint32_t numIndices = 0; + for (uint32_t j = 0; j < g.mConvexCache.size(); j++) + { + numIndices += g.mConvexCache[j]->getVisTriIndices().size(); + } + g.mSubMeshes[i].mIndexCache.clear(); + if (numIndices >= g.mSubMeshes[i].mIndexCache.capacity()) + { + g.mSubMeshes[i].mIndexCache.reserve(numIndices); + } + mIndexBufferSize += numIndices; + } + // Fill for each convex + for (uint32_t j = 0; j < g.mConvexCache.size(); j++) + { + Convex* c = g.mConvexCache[j]; + uint32_t off = g.mVertexCache.size(); + // fill vertices + const Array<PxVec3>& verts = c->getVisVertices(); + const Array<PxVec3>& norms = c->getVisNormals(); + const Array<float>& texcs = c->getVisTexCoords(); + PX_ASSERT(verts.size() == norms.size() && verts.size() == (texcs.size()/2)); + for (uint32_t i = 0; i < verts.size(); i++) + { + g.mVertexCache.pushBack(verts[i]); + g.mNormalCache.pushBack(norms[i]); + g.mTexcoordCache.pushBack(PxVec2(texcs[2*i],texcs[2*i+1])); + g.mBoneIndexCache.pushBack((uint16_t)j); + } + // fill indicies for each submesh + for (uint32_t i = 0; i < g.mSubMeshes.size(); i++) + { + const Array<int32_t>& indices = c->getVisTriIndices(); + PX_ASSERT(indices.size()%3 == 0); + for (uint32_t a = 0; a < indices.size()/3; a++) + { + uint32_t subMeshID = 0; // <<<--- TODO: acquire subMeshID for triangle + if (subMeshID == i) + { + g.mSubMeshes[i].mIndexCache.pushBack(indices[3*a+0]+off); + g.mSubMeshes[i].mIndexCache.pushBack(indices[3*a+1]+off); + g.mSubMeshes[i].mIndexCache.pushBack(indices[3*a+2]+off); + } + } + } + g.mBoneCache.pushBack(c->getGlobalPose()); + } + } +} + +void Renderable::updateRenderCache(Actor* actor) +{ + if( actor == NULL ) return; + actor->mScene->getScene()->lockRead(); + //actor->mRenderResourcesDirty = true; + if( actor->mRenderResourcesDirty) + { + updateRenderCacheFull(actor); + mFullBufferDirty = true; + actor->mRenderResourcesDirty = false; + } + // Fill other caches + for (uint32_t k = 0; k < mConvexGroups.size(); k++) + { + ConvexGroup& g = mConvexGroups[k]; + g.mBoneCache.clear(); + // Fill bones for each convex + for (uint32_t j = 0; j < g.mConvexCache.size(); j++) + { + Convex* c = g.mConvexCache[j]; + g.mBoneCache.pushBack(c->getGlobalPose()); + } + } + actor->mScene->getScene()->unlockRead(); +} + +PxBounds3 Renderable::getBounds() const +{ + PxBounds3 bounds; + bounds.setEmpty(); + for (uint32_t k = 0; k < mConvexGroups.size(); k++) + { + const ConvexGroup& g = mConvexGroups[k]; + for (uint32_t j = 0; j < g.mConvexCache.size(); j++) + { + const Convex* c = g.mConvexCache[j]; + bounds.include(c->getBounds()); + } + } + return bounds; +} + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/Renderable.h b/APEX_1.4/module/destructible/fracture/Renderable.h new file mode 100644 index 00000000..9a2af07c --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/Renderable.h @@ -0,0 +1,107 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef RT_RENDERABLE_H +#define RT_RENDERABLE_H + +#include "PsArray.h" +#include "PsUserAllocated.h" +#include "PxVec2.h" + +namespace nvidia +{ +namespace apex +{ + class UserRenderer; + class UserRenderVertexBuffer; + class UserRenderIndexBuffer; + class UserRenderBoneBuffer; + class UserRenderResource; +} +using namespace shdfnd; + +namespace fracture +{ + +class Actor; +class Convex; + +class Renderable : public UserAllocated +{ +public: + Renderable(); + ~Renderable(); + + // Called by rendering thread + void updateRenderResources(bool rewriteBuffers, void* userRenderData); + void dispatchRenderResources(UserRenderer& api); + + // Per tick bone update, unless Actor is dirty + void updateRenderCache(Actor* actor); + + // Returns the bounds of all of the convexes + PxBounds3 getBounds() const; + +private: + // Called by actor after a patternFracture (On Game Thread) + void updateRenderCacheFull(Actor* actor); + + // To Handle Multiple Materials + struct SubMesh + { + SubMesh(): renderResource(NULL) {} + + Array<uint32_t> mIndexCache; + UserRenderResource* renderResource; + }; + // To Handle Bone Limit + struct ConvexGroup + { + Array<SubMesh> mSubMeshes; + Array<Convex*> mConvexCache; + Array<PxVec3> mVertexCache; + Array<PxVec3> mNormalCache; + Array<PxVec2> mTexcoordCache; + Array<uint16_t> mBoneIndexCache; + Array<PxMat44> mBoneCache; + }; + // Shared by SubMeshes + struct MaterialInfo + { + MaterialInfo(): mMaxBones(0), mMaterialID(0) {} + + uint32_t mMaxBones; + ResID mMaterialID; + }; + // + Array<ConvexGroup> mConvexGroups; + Array<MaterialInfo> mMaterialInfo; + + UserRenderVertexBuffer* mVertexBuffer; + UserRenderIndexBuffer* mIndexBuffer; + UserRenderBoneBuffer* mBoneBuffer; + uint32_t mVertexBufferSize; + uint32_t mIndexBufferSize; + uint32_t mBoneBufferSize; + uint32_t mVertexBufferSizeLast; + uint32_t mIndexBufferSizeLast; + uint32_t mBoneBufferSizeLast; + bool mFullBufferDirty; + bool valid; +}; + +} +} + +#endif +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/SimScene.cpp b/APEX_1.4/module/destructible/fracture/SimScene.cpp new file mode 100644 index 00000000..9d651093 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/SimScene.cpp @@ -0,0 +1,155 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#include <PsUserAllocated.h> + +#include "DestructibleActorImpl.h" + +#include "Actor.h" +#include "Compound.h" +#include "Convex.h" +#include "CompoundCreator.h" +#include "Delaunay2d.h" +#include "Delaunay3d.h" +#include "PolygonTriangulator.h" +#include "IslandDetector.h" +#include "MeshClipper.h" +#include "FracturePattern.h" + +#include "SimScene.h" + +namespace nvidia +{ +namespace fracture +{ + +void SimScene::onWake(PxActor** actors, uint32_t count){ + if(mAppNotify != NULL) + mAppNotify->onWake(actors,count); + + for(uint32_t i = 0; i < count; i++) + { + PxActor* actor = actors[i]; + if(actor != NULL && actor->is<physx::PxRigidDynamic>()) + { + uint32_t shapeCount = actor->is<physx::PxRigidDynamic>()->getNbShapes(); + PxShape** shapes = (PxShape**)PX_ALLOC(sizeof(PxShape*)*shapeCount,"onWake Shapes Temp Buffer"); + actor->is<physx::PxRigidDynamic>()->getShapes(shapes,sizeof(PxShape*)*shapeCount,0); + ::nvidia::destructible::DestructibleActorImpl* prevActor = NULL; + for(uint32_t j = 0; j < shapeCount; j++) + { + nvidia::fracture::base::Convex* convex = findConvexForShape(*shapes[j]); + if(convex == NULL || convex->getParent() == NULL) + continue; + nvidia::fracture::Compound* parent = (nvidia::fracture::Compound*)convex->getParent(); + ::nvidia::destructible::DestructibleActorImpl* curActor = parent->getDestructibleActor(); + if(convex && convex->getParent() && curActor != prevActor && curActor) + { + curActor->incrementWakeCount(); + prevActor = curActor; + } + + } + PX_FREE(shapes); + } + } +} + +void SimScene::onSleep(PxActor** actors, uint32_t count){ + if(mAppNotify != NULL) + mAppNotify->onSleep(actors,count); + + for(uint32_t i = 0; i < count; i++) + { + PxActor* actor = actors[i]; + if(actor != NULL && actor->is<physx::PxRigidDynamic>()) + { + uint32_t shapeCount = actor->is<physx::PxRigidDynamic>()->getNbShapes(); + PxShape** shapes = (PxShape**)PX_ALLOC(sizeof(PxShape*)*shapeCount,"onSleep Shapes Temp Buffer"); + actor->is<physx::PxRigidDynamic>()->getShapes(shapes,sizeof(PxShape*)*shapeCount,0); + ::nvidia::destructible::DestructibleActorImpl* prevActor = NULL; + for(uint32_t j = 0; j < shapeCount; j++) + { + nvidia::fracture::base::Convex* convex = findConvexForShape(*shapes[j]); + if(convex == NULL || convex->getParent() == NULL) + continue; + nvidia::fracture::Compound* parent = (nvidia::fracture::Compound*)convex->getParent(); + ::nvidia::destructible::DestructibleActorImpl* curActor = parent->getDestructibleActor(); + if(convex && convex->getParent() && curActor != prevActor && curActor) + { + curActor->decrementWakeCount();; + prevActor = curActor; + } + + } + PX_FREE(shapes); + } + } +} +SimScene* SimScene::createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, PxScene *scene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath) +{ + SimScene* s = PX_NEW(SimScene)(pxPhysics,pxCooking,scene,minConvexSize,defaultMat,resourcePath); + s->createSingletons(); + return s; +} + +void SimScene::createSingletons() +{ + mCompoundCreator = PX_NEW(CompoundCreator)(this); + mDelaunay2d = PX_NEW(Delaunay2d)(this); + mDelaunay3d = PX_NEW(Delaunay3d)(this); + mPolygonTriangulator = PX_NEW(PolygonTriangulator)(this); + mIslandDetector = PX_NEW(IslandDetector)(this); + mMeshClipper = PX_NEW(MeshClipper)(this); + mDefaultGlass = PX_NEW(FracturePattern)(this); + mDefaultGlass->createGlass(10.0f,0.25f,30,0.3f,0.03f,1.4f,0.3f); + //mDefaultGlass->create3dVoronoi(PxVec3(10.0f, 10.0f, 10.0f), 50, 10.0f); + addActor(createActor(NULL)); +} + +base::Actor* SimScene::createActor(::nvidia::destructible::DestructibleActorImpl* actor) +{ + return (base::Actor*)PX_NEW(Actor)(this,actor); +} + +base::Convex* SimScene::createConvex() +{ + return (base::Convex*)PX_NEW(Convex)(this); +} + +base::Compound* SimScene::createCompound(const base::FracturePattern *pattern, const base::FracturePattern *secondaryPattern, float contactOffset, float restOffset) +{ + return (base::Compound*)PX_NEW(Compound)(this,pattern,secondaryPattern,contactOffset,restOffset); +} + +base::FracturePattern* SimScene::createFracturePattern() +{ + return (base::FracturePattern*)PX_NEW(FracturePattern)(this); +} + +SimScene::SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, PxScene *scene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath): + base::SimScene(pxPhysics,pxCooking,scene,minConvexSize,defaultMat,resourcePath) +{ +} + +// -------------------------------------------------------------------------------------------- +SimScene::~SimScene() +{ + PX_DELETE(mDefaultGlass); + + mDefaultGlass = NULL; +} + +} +} +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/fracture/SimScene.h b/APEX_1.4/module/destructible/fracture/SimScene.h new file mode 100644 index 00000000..fd0e82e6 --- /dev/null +++ b/APEX_1.4/module/destructible/fracture/SimScene.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + + +#include "RTdef.h" +#if RT_COMPILE +#ifndef SIM_SCENE +#define SIM_SCENE + +#include "SimSceneBase.h" + +namespace nvidia +{ +namespace destructible +{ + class DestructibleActorImpl; +} + +namespace fracture +{ + +class FracturePattern; +class Actor; + +class SimScene : public base::SimScene +{ +public: + static SimScene* createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, PxScene *scene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath); +protected: + SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, PxScene *scene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath); +public: + virtual ~SimScene(); + + virtual void createSingletons(); + + virtual base::Actor* createActor(nvidia::destructible::DestructibleActorImpl* actor); + virtual base::Convex* createConvex(); + virtual base::Compound* createCompound(const base::FracturePattern *pattern, const base::FracturePattern *secondaryPattern = NULL, float contactOffset = 0.005f, float restOffset = -0.001f); + virtual base::FracturePattern* createFracturePattern(); + virtual void onWake(PxActor** actors, uint32_t count); + virtual void onSleep(PxActor** actors, uint32_t count); + + FracturePattern* getDefaultGlass() {return mDefaultGlass;} + +protected: + FracturePattern* mDefaultGlass; +}; + +} +} + +#endif +#endif
\ No newline at end of file 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__ diff --git a/APEX_1.4/module/destructible/include/DestructibleActorJointImpl.h b/APEX_1.4/module/destructible/include/DestructibleActorJointImpl.h new file mode 100644 index 00000000..e1abcee3 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleActorJointImpl.h @@ -0,0 +1,52 @@ +/* + * 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 __DESTRUCTIBLE_ACTOR_JOINT_IMPL_H__ +#define __DESTRUCTIBLE_ACTOR_JOINT_IMPL_H__ + +#include "Apex.h" + +namespace nvidia +{ +namespace apex +{ +class DestructibleActorJointDesc; +} +namespace destructible +{ +class DestructibleStructure; +class DestructibleScene; + +class DestructibleActorJointImpl : public ApexResource +{ +public: + DestructibleActorJointImpl(const DestructibleActorJointDesc& destructibleActorJointDesc, DestructibleScene& dscene); + + virtual ~DestructibleActorJointImpl(); + + PxJoint* getJoint() + { + return joint; + } + + bool updateJoint(); + +protected: + + PxJoint* joint; + DestructibleStructure* structure[2]; + int32_t attachmentChunkIndex[2]; +}; + +} +} // end namespace nvidia + +#endif // __DESTRUCTIBLE_ACTOR_JOINT_IMPL_H__ diff --git a/APEX_1.4/module/destructible/include/DestructibleActorJointProxy.h b/APEX_1.4/module/destructible/include/DestructibleActorJointProxy.h new file mode 100644 index 00000000..2ea9721a --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleActorJointProxy.h @@ -0,0 +1,77 @@ +/* + * 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 __DESTRUCTIBLEACTORJOINT_PROXY_H__ +#define __DESTRUCTIBLEACTORJOINT_PROXY_H__ + +#include "Apex.h" +#include "DestructibleActorJoint.h" +#include "DestructibleActorJointImpl.h" +#include "PsUserAllocated.h" +#include "ApexRWLockable.h" +#include "ReadCheck.h" +#include "WriteCheck.h" + +namespace nvidia +{ +namespace destructible +{ + +class DestructibleScene; // Forward declaration + +class DestructibleActorJointProxy : public DestructibleActorJoint, public ApexResourceInterface, public UserAllocated, public ApexRWLockable +{ +public: + APEX_RW_LOCKABLE_BOILERPLATE + + DestructibleActorJointImpl impl; + +#pragma warning(disable : 4355) // disable warning about this pointer in argument list + DestructibleActorJointProxy(const DestructibleActorJointDesc& destructibleActorJointDesc, DestructibleScene& dscene, ResourceList& list) : + impl(destructibleActorJointDesc, dscene) + { + list.add(*this); + }; + + ~DestructibleActorJointProxy() + { + }; + + // DestructibleActorJoint methods + virtual PxJoint* joint() + { + WRITE_ZONE(); + return impl.getJoint(); + } + + virtual void release() + { + // impl.release(); + delete this; + }; + + // ApexResourceInterface methods + virtual void setListIndex(ResourceList& list, uint32_t index) + { + impl.m_listIndex = index; + impl.m_list = &list; + } + + virtual uint32_t getListIndex() const + { + return impl.m_listIndex; + } +}; + +} +} // end namespace nvidia + +#endif // __DESTRUCTIBLEACTORJOINT_PROXY_H__ diff --git a/APEX_1.4/module/destructible/include/DestructibleActorProxy.h b/APEX_1.4/module/destructible/include/DestructibleActorProxy.h new file mode 100644 index 00000000..66aa7aa2 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleActorProxy.h @@ -0,0 +1,620 @@ +/* + * 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_PROXY_H__ +#define __DESTRUCTIBLEACTOR_PROXY_H__ + +#include "Apex.h" +#include "DestructibleActor.h" +#include "DestructibleActorJointProxy.h" +#include "DestructibleActorImpl.h" +#include "DestructibleScene.h" +#include "PsUserAllocated.h" +#include "ApexActor.h" +#if APEX_USE_PARTICLES +#include "EmitterActor.h" +#endif + +#include "ApexRWLockable.h" +#include "ReadCheck.h" +#include "WriteCheck.h" + +namespace nvidia +{ +namespace destructible +{ + +class DestructibleActorProxy : public DestructibleActor, public ApexResourceInterface, public UserAllocated, public ApexRWLockable +{ +public: + APEX_RW_LOCKABLE_BOILERPLATE + + DestructibleActorImpl impl; + +#pragma warning(disable : 4355) // disable warning about this pointer in argument list + DestructibleActorProxy(const NvParameterized::Interface& input, DestructibleAssetImpl& asset, ResourceList& list, DestructibleScene& scene) + : impl(this, asset, scene) + { + WRITE_ZONE(); + NvParameterized::Interface* clonedInput = NULL; + input.clone(clonedInput); + list.add(*this); // Doing this before impl.initialize, since the render proxy created in that function wants a unique ID (only needs to be unique at any given time, can be recycled) + impl.initialize(clonedInput); + } + + DestructibleActorProxy(NvParameterized::Interface* input, DestructibleAssetImpl& asset, ResourceList& list, DestructibleScene& scene) + : impl(this, asset, scene) + { + WRITE_ZONE(); + impl.initialize(input); + list.add(*this); + } + + ~DestructibleActorProxy() + { + } + + virtual const DestructibleParameters& getDestructibleParameters() const + { + READ_ZONE(); + return impl.getDestructibleParameters(); + } + + virtual void setDestructibleParameters(const DestructibleParameters& destructibleParameters) + { + WRITE_ZONE(); + impl.setDestructibleParameters(destructibleParameters); + } + + virtual const RenderMeshActor* getRenderMeshActor(DestructibleActorMeshType::Enum type = DestructibleActorMeshType::Skinned) const + { + READ_ZONE(); + return impl.getRenderMeshActor(type); + } + + virtual PxMat44 getInitialGlobalPose() const + { + READ_ZONE(); + return impl.getInitialGlobalPose(); + } + + virtual void setInitialGlobalPose(const PxMat44& pose) + { + WRITE_ZONE(); + impl.setInitialGlobalPose(pose); + } + + virtual PxVec3 getScale() const + { + READ_ZONE(); + return impl.getScale(); + } + + virtual void applyDamage(float damage, float momentum, const PxVec3& position, const PxVec3& direction, int32_t chunkIndex = ModuleDestructibleConst::INVALID_CHUNK_INDEX, void* damageActorUserData = NULL) + { + WRITE_ZONE(); + return impl.applyDamage(damage, momentum, position, direction, chunkIndex, damageActorUserData); + } + + virtual void applyRadiusDamage(float damage, float momentum, const PxVec3& position, float radius, bool falloff, void* damageActorUserData = NULL) + { + WRITE_ZONE(); + return impl.applyRadiusDamage(damage, momentum, position, radius, falloff, damageActorUserData); + } + + virtual void getChunkVisibilities(uint8_t* visibilityArray, uint32_t visibilityArraySize) const + { + READ_ZONE(); + impl.getChunkVisibilities(visibilityArray, visibilityArraySize); + } + + virtual uint32_t getNumVisibleChunks() const + { + READ_ZONE(); + return impl.getNumVisibleChunks(); + } + + virtual const uint16_t* getVisibleChunks() const + { + READ_ZONE(); + return impl.getVisibleChunks(); + } + + virtual bool acquireChunkEventBuffer(const DestructibleChunkEvent*& buffer, uint32_t& bufferSize) + { + READ_ZONE(); + return impl.acquireChunkEventBuffer(buffer, bufferSize); + } + + virtual bool releaseChunkEventBuffer(bool clearBuffer = true) + { + READ_ZONE(); + return impl.releaseChunkEventBuffer(clearBuffer); + } + + virtual bool acquirePhysXActorBuffer(physx::PxRigidDynamic**& buffer, uint32_t& bufferSize, uint32_t flags = DestructiblePhysXActorQueryFlags::AllStates) + { + READ_ZONE(); + return impl.acquirePhysXActorBuffer(buffer, bufferSize, flags); + } + + virtual bool releasePhysXActorBuffer() + { + READ_ZONE(); + return impl.releasePhysXActorBuffer(); + } + + virtual physx::PxRigidDynamic* getChunkPhysXActor(uint32_t index) + { + READ_ZONE(); + physx::PxActor* actor = impl.getChunkActor(index); + PX_ASSERT(actor == NULL || actor->is<physx::PxRigidDynamic>()); + return (physx::PxRigidDynamic*)actor; + } + + virtual uint32_t getChunkPhysXShapes(physx::PxShape**& shapes, uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getChunkPhysXShapes(shapes, chunkIndex); + } + + virtual PxTransform getChunkPose(uint32_t index) const + { + READ_ZONE(); + return impl.getChunkPose(index); + } + + virtual PxTransform getChunkTransform(uint32_t index) const + { + READ_ZONE(); + return impl.getChunkTransform(index); + } + + virtual PxVec3 getChunkLinearVelocity(uint32_t index) const + { + READ_ZONE(); + return impl.getChunkLinearVelocity(index); + } + + virtual PxVec3 getChunkAngularVelocity(uint32_t index) const + { + READ_ZONE(); + return impl.getChunkAngularVelocity(index); + } + + virtual const PxMat44 getChunkTM(uint32_t index) const + { + READ_ZONE(); + return impl.getChunkTM(index); + } + + virtual int32_t getChunkBehaviorGroupIndex(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getBehaviorGroupIndex(chunkIndex); + } + + virtual uint32_t getChunkActorFlags(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getChunkActorFlags(chunkIndex); + } + + virtual bool isChunkDestroyed(int32_t chunkIndex) const + { + READ_ZONE(); + return impl.isChunkDestroyed((uint32_t)chunkIndex); + } + + virtual void setSkinnedOverrideMaterial(uint32_t index, const char* overrideMaterialName) + { + WRITE_ZONE(); + impl.setSkinnedOverrideMaterial(index, overrideMaterialName); + } + + virtual void setStaticOverrideMaterial(uint32_t index, const char* overrideMaterialName) + { + WRITE_ZONE(); + impl.setStaticOverrideMaterial(index, overrideMaterialName); + } + + virtual void setRuntimeFractureOverridePattern(const char* overridePatternName) + { + WRITE_ZONE(); + impl.setRuntimeFracturePattern(overridePatternName); + } + + virtual bool isInitiallyDynamic() const + { + READ_ZONE(); + return impl.isInitiallyDynamic(); + } + + virtual void setLinearVelocity(const PxVec3& linearVelocity) + { + WRITE_ZONE(); + impl.setLinearVelocity(linearVelocity); + } + + virtual void setGlobalPose(const PxMat44& pose) + { + WRITE_ZONE(); + impl.setGlobalPose(pose); + } + + virtual bool getGlobalPose(PxMat44& pose) + { + READ_ZONE(); + return impl.getGlobalPoseForStaticChunks(pose); + } + + virtual void setAngularVelocity(const PxVec3& angularVelocity) + { + WRITE_ZONE(); + impl.setAngularVelocity(angularVelocity); + } + + virtual void setDynamic(int32_t chunkIndex = ModuleDestructibleConst::INVALID_CHUNK_INDEX) + { + WRITE_ZONE(); + impl.setDynamic(chunkIndex); + } + + virtual bool isDynamic(uint32_t chunkIndex) const + { + READ_ZONE(); + if (impl.getDestructibleAsset() != NULL && chunkIndex < impl.getDestructibleAsset()->getChunkCount()) + { + return impl.getDynamic((int32_t)chunkIndex); + } + return false; + } + + virtual void enableHardSleeping() + { + WRITE_ZONE(); + impl.enableHardSleeping(); + } + + virtual void disableHardSleeping(bool wake = false) + { + WRITE_ZONE(); + impl.disableHardSleeping(wake); + } + + virtual bool isHardSleepingEnabled() const + { + READ_ZONE(); + return impl.useHardSleeping(); + } + + virtual bool setChunkPhysXActorAwakeState(uint32_t chunkIndex, bool awake) + { + WRITE_ZONE(); + return impl.setChunkPhysXActorAwakeState(chunkIndex, awake); + } + + virtual bool addForce(uint32_t chunkIndex, const PxVec3& force, physx::PxForceMode::Enum mode, const PxVec3* position = NULL, bool wakeup = true) + { + WRITE_ZONE(); + return impl.addForce(chunkIndex, force, mode, position, wakeup); + } + + virtual int32_t rayCast(float& time, PxVec3& normal, const PxVec3& worldRayOrig, const PxVec3& worldRayDir, DestructibleActorRaycastFlags::Enum flags, int32_t parentChunkIndex = ModuleDestructibleConst::INVALID_CHUNK_INDEX) const + { + READ_ZONE(); + return impl.rayCast(time, normal, worldRayOrig, worldRayDir, flags, parentChunkIndex); + } + + virtual int32_t obbSweep(float& time, PxVec3& normal, const PxVec3& worldBoxCenter, const PxVec3& worldBoxExtents, const PxMat33& worldBoxRot, const PxVec3& worldDisplacement, DestructibleActorRaycastFlags::Enum flags) const + { + READ_ZONE(); + return impl.obbSweep(time, normal, worldBoxCenter, worldBoxExtents, worldBoxRot, worldDisplacement, flags); + } + + virtual void cacheModuleData() const + { + READ_ZONE(); + return impl.cacheModuleData(); + } + + virtual PxBounds3 getLocalBounds() const + { + READ_ZONE(); + return impl.getLocalBounds(); + } + + virtual PxBounds3 getOriginalBounds() const + { + READ_ZONE(); + return impl.getOriginalBounds(); + } + + virtual bool isChunkSolitary(int32_t chunkIndex) const + { + READ_ZONE(); + return impl.isChunkSolitary( chunkIndex ); + } + + virtual PxBounds3 getChunkBounds(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getChunkBounds( chunkIndex ); + } + + virtual PxBounds3 getChunkLocalBounds(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getChunkLocalBounds( chunkIndex ); + } + + virtual uint32_t getSupportDepthChunkIndices(uint32_t* const OutChunkIndices, uint32_t MaxOutIndices) const + { + READ_ZONE(); + return impl.getSupportDepthChunkIndices( OutChunkIndices, MaxOutIndices ); + } + + virtual uint32_t getSupportDepth() const + { + READ_ZONE(); + return impl.getSupportDepth(); + } + + // Actor methods + virtual Asset* getOwner() const + { + READ_ZONE(); + return impl.mAsset->getAsset(); + } + virtual void release() + { + impl.release(); + } + virtual void destroy() + { + impl.destroy(); + + delete this; + } + + virtual DestructibleRenderable* acquireRenderableReference() + { + return impl.acquireRenderableReference(); + } + + // Renderable methods + virtual void updateRenderResources(bool rewriteBuffers, void* userRenderData) + { + URR_SCOPE; + impl.updateRenderResources(rewriteBuffers, userRenderData); + } + + virtual void dispatchRenderResources(UserRenderer& api) + { + impl.dispatchRenderResources(api); + } + + virtual void lockRenderResources() + { + Renderable* renderable = impl.getRenderable(); + if (renderable != NULL) + { + renderable->lockRenderResources(); + } + } + + virtual void unlockRenderResources() + { + Renderable* renderable = impl.getRenderable(); + if (renderable != NULL) + { + renderable->unlockRenderResources(); + } + } + + virtual PxBounds3 getBounds() const + { + READ_ZONE(); + Renderable* renderable = const_cast<DestructibleActorImpl*>(&impl)->getRenderable(); + if (renderable != NULL) + { + return renderable->getBounds(); + } + return impl.getBounds(); + } + + virtual void setPhysX3Template(const PhysX3DescTemplate* desc) + { + WRITE_ZONE(); + impl.setPhysX3Template(desc); + } + + virtual bool getPhysX3Template(PhysX3DescTemplate& dest) const + { + READ_ZONE(); + return impl.getPhysX3Template(dest); + } + + PhysX3DescTemplate* createPhysX3DescTemplate() const + { + return impl.createPhysX3DescTemplate(); + } + + // ApexResourceInterface methods + virtual void setListIndex(ResourceList& list, uint32_t index) + { + WRITE_ZONE(); + impl.m_listIndex = index; + impl.m_list = &list; + } + virtual uint32_t getListIndex() const + { + READ_ZONE(); + return impl.m_listIndex; + } + + virtual void getLodRange(float& min, float& max, bool& intOnly) const + { + READ_ZONE(); + impl.getLodRange(min, max, intOnly); + } + + virtual float getActiveLod() const + { + READ_ZONE(); + return impl.getActiveLod(); + } + + virtual void forceLod(float lod) + { + WRITE_ZONE(); + impl.forceLod(lod); + } + + /** + \brief Selectively enables/disables debug visualization of a specific APEX actor. Default value it true. + */ + virtual void setEnableDebugVisualization(bool state) + { + WRITE_ZONE(); + impl.setEnableDebugVisualization(state); + } + + + virtual void setCrumbleEmitterState(bool enable) + { + WRITE_ZONE(); + impl.setCrumbleEmitterEnabled(enable); + } + + virtual void setDustEmitterState(bool enable) + { + WRITE_ZONE(); + impl.setDustEmitterEnabled(enable); + } + + /** + Sets a preferred render volume for a dust or crumble emitter + */ + virtual void setPreferredRenderVolume(RenderVolume* volume, DestructibleEmitterType::Enum type) + { + WRITE_ZONE(); + impl.setPreferredRenderVolume(volume, type); + } + + virtual EmitterActor* getApexEmitter(DestructibleEmitterType::Enum type) + { + READ_ZONE(); + return impl.getApexEmitter(type); + } + + virtual bool recreateApexEmitter(DestructibleEmitterType::Enum type) + { + WRITE_ZONE(); + return impl.recreateApexEmitter(type); + } + + const NvParameterized::Interface* getNvParameterized(DestructibleParameterizedType::Enum type) const + { + READ_ZONE(); + switch (type) + { + case DestructibleParameterizedType::State: + return (const NvParameterized::Interface*)impl.getState(); + case DestructibleParameterizedType::Params: + return (const NvParameterized::Interface*)impl.getParams(); + default: + return NULL; + } + } + + void setNvParameterized(NvParameterized::Interface* params) + { + WRITE_ZONE(); + impl.initialize(params); + } + + const NvParameterized::Interface* getChunks() const + { + return (const NvParameterized::Interface*)impl.getChunks(); + } + + void setChunks(NvParameterized::Interface* chunks) + { + impl.initialize(chunks); + } + + virtual bool setSyncParams(uint32_t userActorID, uint32_t actorSyncFlags, const DestructibleActorSyncState * actorSyncState, const DestructibleChunkSyncState * chunkSyncState) + { + WRITE_ZONE(); + return impl.setSyncParams(userActorID, actorSyncFlags, actorSyncState, chunkSyncState); + } + + virtual bool setHitChunkTrackingParams(bool flushHistory, bool startTracking, uint32_t trackingDepth, bool trackAllChunks) + { + WRITE_ZONE(); + return impl.setHitChunkTrackingParams(flushHistory, startTracking, trackingDepth, trackAllChunks); + } + + virtual bool getHitChunkHistory(const DestructibleHitChunk *& hitChunkContainer, uint32_t & hitChunkCount) const + { + READ_ZONE(); + return impl.getHitChunkHistory(hitChunkContainer, hitChunkCount); + } + + virtual bool forceChunkHits(const DestructibleHitChunk * hitChunkContainer, uint32_t hitChunkCount, bool removeChunks = true, bool deferredEvent = false, PxVec3 damagePosition = PxVec3(0.0f), PxVec3 damageDirection = PxVec3(0.0f)) + { + WRITE_ZONE(); + return impl.forceChunkHits(hitChunkContainer, hitChunkCount, removeChunks, deferredEvent, damagePosition, damageDirection); + } + + virtual bool getDamageColoringHistory(const DamageEventCoreData *& damageEventCoreDataContainer, uint32_t & damageEventCoreDataCount) const + { + READ_ZONE(); + return impl.getDamageColoringHistory(damageEventCoreDataContainer, damageEventCoreDataCount); + } + + virtual bool forceDamageColoring(const DamageEventCoreData * damageEventCoreDataContainer, uint32_t damageEventCoreDataCount) + { + WRITE_ZONE(); + return impl.forceDamageColoring(damageEventCoreDataContainer, damageEventCoreDataCount); + } + + virtual void setDeleteFracturedChunks(bool inDeleteChunkMode) + { + WRITE_ZONE(); + impl.setDeleteFracturedChunks(inDeleteChunkMode); + } + + virtual void takeImpact(const PxVec3& force, const PxVec3& position, uint16_t chunkIndex, PxActor const* damageImpactActor) + { + WRITE_ZONE(); + impl.takeImpact(force, position, chunkIndex, damageImpactActor); + } + + virtual uint32_t getCustomBehaviorGroupCount() const + { + READ_ZONE(); + return impl.getCustomBehaviorGroupCount(); + } + + virtual bool getBehaviorGroup(DestructibleBehaviorGroupDesc& behaviorGroupDesc, int32_t index = -1) const + { + READ_ZONE(); + return impl.getBehaviorGroup(behaviorGroupDesc, index); + } +}; + + +} +} // end namespace nvidia + +#endif // __DESTRUCTIBLEACTOR_PROXY_H__ diff --git a/APEX_1.4/module/destructible/include/DestructibleActorUtils.h b/APEX_1.4/module/destructible/include/DestructibleActorUtils.h new file mode 100644 index 00000000..a8d2cf37 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleActorUtils.h @@ -0,0 +1,401 @@ +/* + * 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 __DESTRUCTIBLEACTORUTILS_H__ +#define __DESTRUCTIBLEACTORUTILS_H__ + +#include "ApexDefs.h" +#include "DestructibleActorImpl.h" +#include "PxPhysics.h" + +namespace nvidia +{ +namespace destructible +{ + +#ifdef _DEBUG +#define VERIFY_PARAM(_A) PX_ASSERT((_A) == NvParameterized::ERROR_NONE) +#else +#define VERIFY_PARAM(_A) (_A) +#endif + + +enum AssignType { + AtoB, + BtoA, + Default = BtoA, + Inverse = AtoB +}; + +static const bool Serialize = true; +static const bool Deserialize = false; + +/////////////////////////////////////////////////////////////////////////// + +static const char* typeName(DestructibleParameterizedType::Enum e) +{ + const char* typeName = ""; + switch (e) + { + case DestructibleParameterizedType::State: + typeName = DestructibleActorState::staticClassName(); + break; + case DestructibleParameterizedType::Params: + typeName = DestructibleActorParam::staticClassName(); + break; + default: + break; + } + return typeName; +} + +PX_INLINE static bool isType(NvParameterized::Interface* i, DestructibleParameterizedType::Enum e) +{ + return nvidia::stricmp(i->className(), typeName(e)) == 0; +} + +/////////////////////////////////////////////////////////////////////////// + +template <typename T, typename FlagType> +PX_INLINE void assignFlag(T& val, FlagType flag, bool setFlag) +{ + val = (T)(setFlag ? (val | (T)flag) : (val & ~(T)flag)); +} + +template <typename T, typename FlagType> +PX_INLINE void assignFlag(bool& flagSet, const T& val, FlagType flag) +{ + flagSet = (val & flag) ? true : false; +} + +template<typename T, typename FlagType> +PX_INLINE void assignFlags(T& a, FlagType flag, bool& b, AssignType assignType) +{ + if (BtoA == assignType) + assignFlag(a, flag, b); + else + assignFlag(b, a, flag); +} + +template<typename T, typename U> +PX_INLINE void assign(T& a, U& b, AssignType assignType) +{ + if(AtoB == assignType) + b = static_cast<U>(a); + else + a = static_cast<T>(b); +} + +template<typename T, typename U, typename T1, typename U1> +PX_INLINE void assignPtr(T1& a, U1& b, AssignType assignType) +{ + if(AtoB == assignType) + b = (U)a; + else + a = (T)b; +} + +/////////////////////////////////////////////////////////////////////////// + +void assign(PhysX3DescTemplateImpl& descA, + DestructibleActorParamNS::P3ActorDescTemplate_Type& descB0, + DestructibleActorParamNS::P3BodyDescTemplate_Type& descB1, + DestructibleActorParamNS::P3ShapeDescTemplate_Type& descB2, + AssignType assignType = Default) +{ + // actor + assign(descA.dominanceGroup , descB0.dominanceGroup, assignType); + assign(descA.ownerClient , descB0.ownerClient, assignType); + assign(descA.clientBehaviorBits, descB0.clientBehaviorBits, assignType); + + assignFlags(descA.actorFlags, physx::PxActorFlag::eVISUALIZATION, descB0.flags.eVISUALIZATION, assignType); + assignFlags(descA.actorFlags, physx::PxActorFlag::eDISABLE_GRAVITY, descB0.flags.eDISABLE_GRAVITY, assignType); + assignFlags(descA.actorFlags, physx::PxActorFlag::eSEND_SLEEP_NOTIFIES, descB0.flags.eSEND_SLEEP_NOTIFIES, assignType); + + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eSOLVE_CONTACT, descB0.contactReportFlags.eSOLVE_CONTACT, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eMODIFY_CONTACTS, descB0.contactReportFlags.eMODIFY_CONTACTS, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eNOTIFY_TOUCH_FOUND, descB0.contactReportFlags.eNOTIFY_TOUCH_FOUND, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eNOTIFY_TOUCH_PERSISTS, descB0.contactReportFlags.eNOTIFY_TOUCH_PERSISTS, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eNOTIFY_TOUCH_LOST, descB0.contactReportFlags.eNOTIFY_TOUCH_LOST, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND, descB0.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_FOUND, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS, descB0.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_PERSISTS, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST, descB0.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_LOST, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eNOTIFY_CONTACT_POINTS, descB0.contactReportFlags.eNOTIFY_CONTACT_POINTS, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eDETECT_CCD_CONTACT, descB0.contactReportFlags.eDETECT_CCD_CONTACT, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eCONTACT_DEFAULT, descB0.contactReportFlags.eCONTACT_DEFAULT, assignType); + assignFlags(descA.contactReportFlags, physx::PxPairFlag::eTRIGGER_DEFAULT, descB0.contactReportFlags.eTRIGGER_DEFAULT, assignType); + assignPtr<void*,size_t>(descA.userData, descB0.userData, assignType); + assignPtr<const char*,size_t>(descA.name, descB0.name, assignType); + + // body + assignFlags(descA.bodyFlags, PxRigidBodyFlag::eKINEMATIC, descB1.flags.eKINEMATIC, assignType); + assignFlags(descA.bodyFlags, PxRigidBodyFlag::eENABLE_CCD, descB1.flags.eENABLE_CCD, assignType); + assign(descA.density , descB1.density, assignType); + assign(descA.sleepThreshold , descB1.sleepThreshold, assignType); + assign(descA.wakeUpCounter , descB1.wakeUpCounter, assignType); + assign(descA.linearDamping , descB1.linearDamping, assignType); + assign(descA.angularDamping , descB1.angularDamping, assignType); + assign(descA.maxAngularVelocity , descB1.maxAngularVelocity, assignType); + assign(descA.solverIterationCount , descB1.solverIterationCount, assignType); + assign(descA.velocityIterationCount , descB1.velocityIterationCount, assignType); + assign(descA.contactReportThreshold , descB1.contactReportThreshold, assignType); + assign(descA.sleepLinearVelocity , descB1.sleepLinearVelocity, assignType); + + // shape + assignFlags(descA.shapeFlags, PxShapeFlag::eSIMULATION_SHAPE, descB2.flags.eSIMULATION_SHAPE, assignType); + assignFlags(descA.shapeFlags, PxShapeFlag::eSCENE_QUERY_SHAPE, descB2.flags.eSCENE_QUERY_SHAPE, assignType); + assignFlags(descA.shapeFlags, PxShapeFlag::eTRIGGER_SHAPE, descB2.flags.eTRIGGER_SHAPE, assignType); + assignFlags(descA.shapeFlags, PxShapeFlag::eVISUALIZATION, descB2.flags.eVISUALIZATION, assignType); + assignFlags(descA.shapeFlags, PxShapeFlag::ePARTICLE_DRAIN, descB2.flags.ePARTICLE_DRAIN, assignType); + + // TODO: Remove this from the NvParameterized destructible actor, shift it to the BODY descriptor? + //assignFlags(descA.shapeFlags, PxShapeFlag::eUSE_SWEPT_BOUNDS, descB2.flags.eUSE_SWEPT_BOUNDS, assignType); + + assign(descA.simulationFilterData.word0 , descB2.simulationFilterData.word0, assignType); + assign(descA.simulationFilterData.word1 , descB2.simulationFilterData.word1, assignType); + assign(descA.simulationFilterData.word2 , descB2.simulationFilterData.word2, assignType); + assign(descA.simulationFilterData.word3 , descB2.simulationFilterData.word3, assignType); + assign(descA.queryFilterData.word0 , descB2.queryFilterData.word0, assignType); + assign(descA.queryFilterData.word1 , descB2.queryFilterData.word1, assignType); + assign(descA.queryFilterData.word2 , descB2.queryFilterData.word2, assignType); + assign(descA.queryFilterData.word3 , descB2.queryFilterData.word3, assignType); + assign(descA.contactOffset , descB2.contactOffset, assignType); + assign(descA.restOffset , descB2.restOffset, assignType); + assignPtr<void*,size_t>(descA.shapeUserData , descB2.userData, assignType); + assignPtr<const char*, size_t>(descA.shapeName, descB2.name, assignType); + + if (BtoA == assignType) + { + PxMaterial* material = NULL; + if (descB2.material) + material = (PxMaterial*)descB2.material; + else + { + // Get the first material as a fallback + if (GetApexSDK()->getPhysXSDK()->getNbMaterials()) + GetApexSDK()->getPhysXSDK()->getMaterials(&material, 1, 0); + } + if (NULL != material) + { + descA.materials.pushBack(material); + } + } + else + descB2.material = descA.materials.size() > 0 ? (size_t)descA.materials[0] : (uint64_t)0; +} + +PX_INLINE void deserialize(PhysX3DescTemplateImpl& descA, + const DestructibleActorParamNS::P3ActorDescTemplate_Type& descB0, + const DestructibleActorParamNS::P3BodyDescTemplate_Type& descB1, + const DestructibleActorParamNS::P3ShapeDescTemplate_Type& descB2) +{ + assign(descA, + const_cast<DestructibleActorParamNS::P3ActorDescTemplate_Type&>(descB0), + const_cast<DestructibleActorParamNS::P3BodyDescTemplate_Type&>(descB1), + const_cast<DestructibleActorParamNS::P3ShapeDescTemplate_Type&>(descB2), BtoA); +} + +PX_INLINE void serialize(const PhysX3DescTemplateImpl& descA, + DestructibleActorParamNS::P3ActorDescTemplate_Type& descB0, + DestructibleActorParamNS::P3BodyDescTemplate_Type& descB1, + DestructibleActorParamNS::P3ShapeDescTemplate_Type& descB2) +{ + assign(const_cast<PhysX3DescTemplateImpl&>(descA), descB0, descB1, descB2, AtoB); +} + +/////////////////////////////////////////////////////////////////////////// + +PX_INLINE void assign(DestructibleDepthParameters& paramA, + DestructibleActorParamNS::DestructibleDepthParameters_Type& paramB, + AssignType assignType = Default) +{ + assignFlags(paramA.flags, DestructibleDepthParametersFlag::OVERRIDE_IMPACT_DAMAGE, paramB.OVERRIDE_IMPACT_DAMAGE, assignType); + assignFlags(paramA.flags, DestructibleDepthParametersFlag::OVERRIDE_IMPACT_DAMAGE_VALUE, paramB.OVERRIDE_IMPACT_DAMAGE_VALUE, assignType); + assignFlags(paramA.flags, DestructibleDepthParametersFlag::IGNORE_POSE_UPDATES, paramB.IGNORE_POSE_UPDATES, assignType); + assignFlags(paramA.flags, DestructibleDepthParametersFlag::IGNORE_RAYCAST_CALLBACKS, paramB.IGNORE_RAYCAST_CALLBACKS, assignType); + assignFlags(paramA.flags, DestructibleDepthParametersFlag::IGNORE_CONTACT_CALLBACKS, paramB.IGNORE_CONTACT_CALLBACKS, assignType); + assignFlags(paramA.flags, DestructibleDepthParametersFlag::USER_FLAG_0, paramB.USER_FLAG_0, assignType); + assignFlags(paramA.flags, DestructibleDepthParametersFlag::USER_FLAG_1, paramB.USER_FLAG_1, assignType); + assignFlags(paramA.flags, DestructibleDepthParametersFlag::USER_FLAG_2, paramB.USER_FLAG_2, assignType); + assignFlags(paramA.flags, DestructibleDepthParametersFlag::USER_FLAG_3, paramB.USER_FLAG_3, assignType); +} + +/////////////////////////////////////////////////////////////////////////// + +PX_INLINE void assign(DestructibleParameters& paramA, + DestructibleActorParamNS::DestructibleParameters_Type& paramB, + AssignType assignType = Default) +{ + assign(paramA.damageCap , paramB.damageCap, assignType); + assign(paramA.debrisDepth , paramB.debrisDepth, assignType); + assign(paramA.debrisLifetimeMax , paramB.debrisLifetimeMax, assignType); + assign(paramA.debrisLifetimeMin , paramB.debrisLifetimeMin, assignType); + assign(paramA.debrisMaxSeparationMax , paramB.debrisMaxSeparationMax, assignType); + assign(paramA.debrisMaxSeparationMin , paramB.debrisMaxSeparationMin, assignType); + assign(paramA.essentialDepth , paramB.essentialDepth, assignType); + assign(paramA.forceToDamage , paramB.forceToDamage, assignType); + assign(paramA.fractureImpulseScale , paramB.fractureImpulseScale, assignType); + assign(paramA.damageDepthLimit , paramB.damageDepthLimit, assignType); + assign(paramA.impactVelocityThreshold , paramB.impactVelocityThreshold, assignType); + assign(paramA.maxChunkSpeed , paramB.maxChunkSpeed, assignType); + assign(paramA.minimumFractureDepth , paramB.minimumFractureDepth, assignType); + assign(paramA.impactDamageDefaultDepth , paramB.impactDamageDefaultDepth, assignType); + assign(paramA.debrisDestructionProbability , paramB.debrisDestructionProbability, assignType); + assign(paramA.validBounds , paramB.validBounds, assignType); + assign(paramA.dynamicChunksDominanceGroup , paramB.dynamicChunkDominanceGroup, assignType); + assign(paramA.useDynamicChunksGroupsMask , paramB.dynamicChunksGroupsMask.useGroupsMask, assignType); + assign(paramA.dynamicChunksFilterData.word0 , paramB.dynamicChunksGroupsMask.bits0, assignType); + assign(paramA.dynamicChunksFilterData.word1 , paramB.dynamicChunksGroupsMask.bits1, assignType); + assign(paramA.dynamicChunksFilterData.word2 , paramB.dynamicChunksGroupsMask.bits2, assignType); + assign(paramA.dynamicChunksFilterData.word3 , paramB.dynamicChunksGroupsMask.bits3, assignType); + assign(paramA.supportStrength , paramB.supportStrength, assignType); + assign(paramA.legacyChunkBoundsTestSetting , paramB.legacyChunkBoundsTestSetting, assignType); + assign(paramA.legacyDamageRadiusSpreadSetting , paramB.legacyDamageRadiusSpreadSetting, assignType); + + assignFlags(paramA.flags, DestructibleParametersFlag::ACCUMULATE_DAMAGE, paramB.flags.ACCUMULATE_DAMAGE, assignType); + assignFlags(paramA.flags, DestructibleParametersFlag::DEBRIS_TIMEOUT, paramB.flags.DEBRIS_TIMEOUT, assignType); + assignFlags(paramA.flags, DestructibleParametersFlag::DEBRIS_MAX_SEPARATION, paramB.flags.DEBRIS_MAX_SEPARATION, assignType); + assignFlags(paramA.flags, DestructibleParametersFlag::CRUMBLE_SMALLEST_CHUNKS, paramB.flags.CRUMBLE_SMALLEST_CHUNKS, assignType); + assignFlags(paramA.flags, DestructibleParametersFlag::ACCURATE_RAYCASTS, paramB.flags.ACCURATE_RAYCASTS, assignType); + assignFlags(paramA.flags, DestructibleParametersFlag::USE_VALID_BOUNDS, paramB.flags.USE_VALID_BOUNDS, assignType); + assignFlags(paramA.flags, DestructibleParametersFlag::CRUMBLE_VIA_RUNTIME_FRACTURE, paramB.flags.CRUMBLE_VIA_RUNTIME_FRACTURE, assignType); + + // RT Fracture assign + assign(paramA.rtFractureParameters.sheetFracture, paramB.runtimeFracture.sheetFracture, assignType); + assign(paramA.rtFractureParameters.depthLimit, paramB.runtimeFracture.depthLimit, assignType); + assign(paramA.rtFractureParameters.destroyIfAtDepthLimit, paramB.runtimeFracture.destroyIfAtDepthLimit, assignType); + assign(paramA.rtFractureParameters.minConvexSize, paramB.runtimeFracture.minConvexSize, assignType); + assign(paramA.rtFractureParameters.impulseScale, paramB.runtimeFracture.impulseScale, assignType); + assign(paramA.rtFractureParameters.glass.numSectors, paramB.runtimeFracture.glass.numSectors, assignType); + assign(paramA.rtFractureParameters.glass.sectorRand, paramB.runtimeFracture.glass.sectorRand, assignType); + assign(paramA.rtFractureParameters.glass.firstSegmentSize, paramB.runtimeFracture.glass.firstSegmentSize, assignType); + assign(paramA.rtFractureParameters.glass.segmentScale, paramB.runtimeFracture.glass.segmentScale, assignType); + assign(paramA.rtFractureParameters.glass.segmentRand, paramB.runtimeFracture.glass.segmentRand, assignType); + assign(paramA.rtFractureParameters.attachment.posX, paramB.runtimeFracture.attachment.posX, assignType); + assign(paramA.rtFractureParameters.attachment.negX, paramB.runtimeFracture.attachment.negX, assignType); + assign(paramA.rtFractureParameters.attachment.posY, paramB.runtimeFracture.attachment.posY, assignType); + assign(paramA.rtFractureParameters.attachment.negY, paramB.runtimeFracture.attachment.negY, assignType); + assign(paramA.rtFractureParameters.attachment.posZ, paramB.runtimeFracture.attachment.posZ, assignType); + assign(paramA.rtFractureParameters.attachment.negZ, paramB.runtimeFracture.attachment.negZ, assignType); +} + +/////////////////////////////////////////////////////////////////////////// + +template<typename A, typename B> +PX_INLINE void deserialize(A& paramA, const B& paramB) +{ + assign(paramA, const_cast<B&>(paramB), BtoA); +} + +template<typename A, typename B> +PX_INLINE void serialize(const A& paramA, B& paramB) +{ + assign(const_cast<A&>(paramA), paramB, AtoB); +} + +/////////////////////////////////////////////////////////////////////////// + +PX_INLINE void serialize(const DestructibleParameters& nxIn, + NvParameterized::Interface& nxOut) +{ + if (isType(&nxOut, DestructibleParameterizedType::Params)) + { + DestructibleActorParam& nxOutParams = static_cast<DestructibleActorParam&>(nxOut); + NvParameterized::Handle handle(nxOutParams); + VERIFY_PARAM(nxOutParams.getParameterHandle("depthParameters", handle)); + nxOutParams.resizeArray(handle, (int32_t)nxIn.depthParametersCount); + + serialize(nxIn, nxOutParams.destructibleParameters); + + PX_ASSERT(nxOutParams.depthParameters.arraySizes[0] == (int32_t)nxIn.depthParametersCount); + for (uint32_t i = 0; i < nxIn.depthParametersCount; ++i) + { + serialize(nxIn.depthParameters[i], nxOutParams.depthParameters.buf[i]); + } + } +} + +PX_INLINE void deserialize(const DestructibleActorParamNS::DestructibleParameters_Type& nxIn, + const DestructibleActorParamNS::DestructibleDepthParameters_DynamicArray1D_Type& nxIn2, + DestructibleParameters& nxOut) +{ + deserialize(nxOut, const_cast<DestructibleActorParamNS::DestructibleParameters_Type&>(nxIn)); + nxOut.depthParametersCount = (uint32_t)nxIn2.arraySizes[0]; + for (uint32_t depth = 0; depth < nxOut.depthParametersCount; ++depth) + { + deserialize(nxOut.depthParameters[depth], nxIn2.buf[depth]); + } +} + +PX_INLINE void serialize(const DestructibleActorImpl& actor, + const DestructibleStructure::Chunk* nxIn, + const uint32_t nxInCount, + DestructibleActorChunks& nxOut) +{ + if (nxInCount <= 0) + return; + + NvParameterized::Handle handle(nxOut); + VERIFY_PARAM(nxOut.getParameterHandle("data", handle)); + nxOut.resizeArray(handle, (int32_t)nxInCount); + PX_ASSERT((int32_t)nxInCount == nxOut.data.arraySizes[0]); + + for (uint32_t i = 0; i < nxInCount; ++i) + { + nxOut.data.buf[i].state = nxIn[i].state; + nxOut.data.buf[i].flags = nxIn[i].flags; + nxOut.data.buf[i].islandID = nxIn[i].islandID; + nxOut.data.buf[i].damage = nxIn[i].damage; + nxOut.data.buf[i].localOffset = nxIn[i].localOffset; + nxOut.data.buf[i].localSphere = PxVec4(nxIn[i].localSphereCenter, nxIn[i].localSphereRadius); + nxOut.data.buf[i].shapesCount = (nxIn[i].isDestroyed() || !(nxIn[i].state & ChunkVisible)) ? 0 : nxIn[i].getShapeCount(); + + if (nxIn[i].visibleAncestorIndex != (int32_t)DestructibleStructure::InvalidChunkIndex) + nxOut.data.buf[i].visibleAncestorIndex = nxIn[i].visibleAncestorIndex - (int32_t)actor.getFirstChunkIndex(); + else + nxOut.data.buf[i].visibleAncestorIndex = (int32_t)DestructibleStructure::InvalidChunkIndex; + + if (!nxIn[i].isDestroyed()) + { + // BRG - shouldn't this state be obtained from nxIn[i].state? In any case, must decouple this now since we have "dormant" kinematic chunks + // which are chunks that have been freed but turned kinematic for "hard" sleeping +// const bool chunkDynamic = !actor.getChunkActor(i)->readBodyFlag(BF_KINEMATIC); +// assignFlag(nxOut.data.buf[i].state, ChunkDynamic, chunkDynamic); + + nxOut.data.buf[i].linearVelocity = actor.getChunkLinearVelocity(i); + nxOut.data.buf[i].angularVelocity = actor.getChunkAngularVelocity(i); + nxOut.data.buf[i].globalPose = actor.getChunkPose(i); + nxOut.data.buf[i].globalPose.q.normalize(); + } + } +} + +PX_INLINE void deserializeChunkData(const DestructibleActorChunksNS::Chunk_Type& nxIn, DestructibleStructure::Chunk& nxOut) +{ + nxOut.state = nxIn.state; + nxOut.flags = nxIn.flags; + nxOut.damage = nxIn.damage; + nxOut.localOffset = nxIn.localOffset; + nxOut.localSphereCenter = nxIn.localSphere.getXYZ(); + nxOut.localSphereRadius = nxIn.localSphere.w; + nxOut.islandID = nxIn.islandID; + nxOut.clearShapes(); + // Poses and velocities are restored later as chunks are actually created +} + +/////////////////////////////////////////////////////////////////////////// + +} +} // end namespace nvidia + + + +#endif diff --git a/APEX_1.4/module/destructible/include/DestructibleAssetImpl.h b/APEX_1.4/module/destructible/include/DestructibleAssetImpl.h new file mode 100644 index 00000000..28267af4 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleAssetImpl.h @@ -0,0 +1,916 @@ +/* + * 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 DESTRUCTIBLE_ASSET_IMPL_H +#define DESTRUCTIBLE_ASSET_IMPL_H + +#include "Apex.h" +#include "PsArray.h" +#include "ApexSDKHelpers.h" +#include "DestructibleAsset.h" +#include "ApexSharedUtils.h" +#include "ApexAssetTracker.h" +#include "DestructibleActorParam.h" +#include "ApexUsingNamespace.h" +#include "DestructibleAssetParameters.h" +#include "MeshCookedCollisionStreamsAtScale.h" +#include "MeshCookedCollisionStream.h" +#include "DestructibleAssetCollisionDataSet.h" +#include "CachedOverlaps.h" + +#include "PxConvexMesh.h" + +#include "authoring/Fracturing.h" + +#include "ApexActor.h" + +namespace nvidia +{ +namespace apex +{ +class DestructiblePreview; +} +namespace destructible +{ +class ModuleDestructibleImpl; + + +/** + Descriptor used to create a Destructible actor. +*/ +class DestructibleActorDesc : public ApexDesc +{ +public: + + /** + \brief Constructor sets to default. + */ + PX_INLINE DestructibleActorDesc() : ApexDesc() + { + setToDefault(); + } + + /** + \brief Resets descriptor to default settings. + */ + PX_INLINE void setToDefault() + { + ApexDesc::setToDefault(); + + physX3Template = NULL; + crumbleEmitterName = NULL; + dustEmitterName = NULL; + globalPose = PxMat44(PxIdentity); + scale = PxVec3(1.0f); + dynamic = false; + supportDepth = 0; + formExtendedStructures = false; + useAssetDefinedSupport = false; + useWorldSupport = false; + overrideSkinnedMaterials = NULL; + overrideSkinnedMaterialCount = 0; + overrideStaticMaterials = NULL; + overrideStaticMaterialCount = 0; + renderStaticChunksSeparately = true; + destructibleParameters.setToDefault(); + } + + /** + Returns true iff an object can be created using this descriptor. + */ + PX_INLINE bool isValid() const + { + const float det = (globalPose.column0.getXYZ().cross(globalPose.column1.getXYZ())).dot(globalPose.column2.getXYZ()); + if (!PxEquals(det, 1.0f, 0.001f)) + { + APEX_DEBUG_WARNING("Mirror transformations are not allowed in the DestructibleActor descriptor."); + return false; + } + + if (scale.x <= 0 || scale.y <= 0 || scale.z <= 0) + { + APEX_DEBUG_WARNING("Negative scales are not allowed in the DestructibleActor descriptor."); + return false; + } + + if (physX3Template && !physX3Template->isValid() ) + { + APEX_DEBUG_WARNING("Invalid physx3 descriptor template in the DestructibleActor descriptor."); + return false; + } + + if (overrideSkinnedMaterialCount > 0 && overrideSkinnedMaterials == NULL) + { + APEX_DEBUG_WARNING("overrideSkinnedMaterials is NULL, but overrideSkinnedMaterialCount > 0."); + return false; + } + + if (overrideStaticMaterialCount > 0 && overrideStaticMaterials == NULL) + { + APEX_DEBUG_WARNING("overrideStaticMaterials is NULL, but overrideStaticMaterialCount > 0."); + return false; + } + + // Note - Not checking shapeDescTemplate, since meshData is not supplied + + return ApexDesc::isValid(); + } + + PhysX3DescTemplateImpl* physX3Template; + + /** + The name of the MeshParticleSystem to use for crumbling. This overrides the crumble system defined + in the DestructibleAsset if specified. + */ + const char* crumbleEmitterName; + + /** + The name of the MeshParticleSystem to use for fracture-line dust. This overrides the dust system defined + in the DestructibleAsset if specified. + */ + const char* dustEmitterName; + + /** + Initial global pose of undamaged destructible + */ + PxMat44 globalPose; + + /** + 3D scale + */ + PxVec3 scale; + + /** + Whether or not the destructible starts life as a dynamic actor + */ + bool dynamic; + + /** + The chunk hierarchy depth at which to create a support graph. Higher depth levels give more detailed support, + but will give a higher computational load. Chunks below the support depth will never be supported. + */ + uint32_t supportDepth; + + /** + If set, and the destructible is initially static, it will become part of an extended support + structure if it is in contact with another static destructible that also has this flag set. + */ + bool formExtendedStructures; + + /** + If set, then chunks which are tagged as "support" chunks (via DestructibleChunkDesc::isSupportChunk) + will have environmental support in static destructibles. + + Note: if both ASSET_DEFINED_SUPPORT and WORLD_SUPPORT are set, then chunks must be tagged as + "support" chunks AND overlap the PxScene's static geometry in order to be environmentally supported. + */ + bool useAssetDefinedSupport; + + /** + If set, then chunks which overlap the PxScene's static geometry will have environmental support in + static destructibles. + + Note: if both ASSET_DEFINED_SUPPORT and WORLD_SUPPORT are set, then chunks must be tagged as + "support" chunks AND overlap the PxScene's static geometry in order to be environmentally supported. + */ + bool useWorldSupport; + + /* + If true, static chunks will be renderered separately from dynamic chunks, as a single mesh (not using skinning). + This parameter is ignored if the 'dynamic' parameter is true. + Default value = false. + */ + bool renderStaticChunksSeparately; + + /** + Per-actor material names for the skinned mesh + */ + const char** overrideSkinnedMaterials; + + /** + Size of overrideSkinnedMaterials array + */ + uint32_t overrideSkinnedMaterialCount; + + /** + Per-actor material names for the static mesh + */ + const char** overrideStaticMaterials; + + /** + Size of overrideStaticMaterials array + */ + uint32_t overrideStaticMaterialCount; + + /** + Initial destructible parameters. These may be changed at runtime. + */ + DestructibleParameters destructibleParameters; +}; + + +/** + Set of sets of convex meshes [scale#][part#] +*/ +class DestructibleConvexMeshContainer +{ +public: + struct ConvexMeshSet : public UserAllocated + { + ConvexMeshSet() : mReferenceCount(0) {} + + physx::Array<PxConvexMesh*> mSet; + uint32_t mReferenceCount; + }; + + ~DestructibleConvexMeshContainer() { reset(); } + + uint32_t size() const + { + return mConvexMeshSets.size(); + } + + physx::Array<PxConvexMesh*>& operator [] (uint32_t i) const + { + return mConvexMeshSets[i]->mSet; + } + + uint32_t getReferenceCount(uint32_t i) const + { + return mConvexMeshSets[i]->mReferenceCount; + } + void incReferenceCount(uint32_t i) + { + ++mConvexMeshSets[i]->mReferenceCount; + } + bool decReferenceCount(uint32_t i) + { + if (mConvexMeshSets[i]->mReferenceCount == 0) + return false; + --mConvexMeshSets[i]->mReferenceCount; + return true; + } + + void resize(uint32_t newSize) + { + const uint32_t oldSize = size(); + mConvexMeshSets.resize(newSize); + for (uint32_t i = oldSize; i < newSize; ++i) + { + mConvexMeshSets[i] = PX_NEW(ConvexMeshSet); + } + } + + void reset(bool force = true) + { + for (uint32_t i = mConvexMeshSets.size(); i--;) + { + ConvexMeshSet* meshSet = mConvexMeshSets[i]; + if (meshSet != NULL) + { + if (force) + { + PX_DELETE(meshSet); + mConvexMeshSets[i] = NULL; + } + else + { + if (meshSet->mReferenceCount == 0) + { + // Release the PhysX convex mesh pointers + for (uint32_t j=0; j<meshSet->mSet.size(); j++) + { + PxConvexMesh* convexMesh = meshSet->mSet[j]; + if (convexMesh == NULL) + { + continue; + } + convexMesh->release(); + } + + meshSet->mSet.resize(0); + PX_DELETE(meshSet); + mConvexMeshSets.replaceWithLast(i); + } + } + } + } + if (force) + { + mConvexMeshSets.reset(); + } + } + +private: + physx::Array<ConvexMeshSet*> mConvexMeshSets; +}; + + +/** + Destructible asset collision data. Caches collision data for a DestructibleAsset at + various scales. +*/ + +#define kDefaultDestructibleAssetCollisionScaleTolerance (0.0001f) + +class DestructibleAssetCollision : public ApexResource +{ +public: + + struct Version + { + enum Enum + { + First = 0, + // New versions must be put here. There is no need to explicitly number them. The + // numbers above were put there to conform to the old DestructionToolStreamVersion enum. + + Count, + Current = Count - 1 + }; + }; + + DestructibleAssetCollision(); + DestructibleAssetCollision(NvParameterized::Interface* params); + ~DestructibleAssetCollision(); + + void setDestructibleAssetToCook(class DestructibleAssetImpl* asset); + + bool addScale(const PxVec3& scale); + + bool cookAll(); + + bool cookScale(const PxVec3& scale); + + void resize(uint32_t hullCount); + + const char* getAssetName() const + { + return mParams->assetName; + } + DestructibleAssetImpl* getAsset() { return mAsset; } + PxConvexMesh* getConvexMesh(uint32_t hullIndex, const PxVec3& scale); + + PxFileBuf& deserialize(PxFileBuf& stream, const char* assetName); + PxFileBuf& serialize(PxFileBuf& stream) const; + + bool platformAndVersionMatch() const; + void setPlatformAndVersion(); + + uint32_t memorySize() const; + + MeshCookedCollisionStreamsAtScale* getCollisionAtScale(const PxVec3& scale); + + physx::Array<PxConvexMesh*>* getConvexMeshesAtScale(const PxVec3& scale); + + void clearUnreferencedSets(); + // Spit out warnings to the error stream for any referenced sets + void reportReferencedSets(); + bool incReferenceCount(int scaleIndex); + bool decReferenceCount(int scaleIndex); + + void merge(DestructibleAssetCollision& collisionSet); + + int32_t getScaleIndex(const PxVec3& scale, float tolerance) const; + +private: + DestructibleAssetCollisionDataSet* mParams; + bool mOwnsParams; + + class DestructibleAssetImpl* mAsset; + DestructibleConvexMeshContainer mConvexMeshContainer; +}; + +#define OFFSET_FN(_classname, _membername) static uint32_t _membername##Offset() { return PX_OFFSET_OF(_classname, _membername); } + +class DestructibleAssetImpl : public ApexResource +{ +public: + + enum + { + InvalidChunkIndex = 0xFFFF + }; + + enum ChunkFlags + { + SupportChunk = (1 << 0), + UnfracturableChunk = (1 << 1), + DescendantUnfractureable = (1 << 2), + UndamageableChunk = (1 << 3), + UncrumbleableChunk = (1 << 4), +#if APEX_RUNTIME_FRACTURE + RuntimeFracturableChunk = (1 << 5), +#endif + + Instanced = (1 << 8), + }; + + struct ChunkInstanceBufferDataElement + { + PxVec3 translation; + PxMat33 scaledRotation; + PxVec2 uvOffset; + PxVec3 localOffset; + + OFFSET_FN(ChunkInstanceBufferDataElement, translation) + OFFSET_FN(ChunkInstanceBufferDataElement, scaledRotation) + OFFSET_FN(ChunkInstanceBufferDataElement, uvOffset) + OFFSET_FN(ChunkInstanceBufferDataElement, localOffset) + }; + + struct ScatterInstanceBufferDataElement + { + PxVec3 translation; + PxMat33 scaledRotation; + float alpha; + + OFFSET_FN(ScatterInstanceBufferDataElement, translation) + OFFSET_FN(ScatterInstanceBufferDataElement, scaledRotation) + OFFSET_FN(ScatterInstanceBufferDataElement, alpha) + }; + + struct ScatterMeshInstanceInfo + { + ScatterMeshInstanceInfo() + : m_actor(NULL) + , m_instanceBuffer(NULL) + , m_IBSize(0) + {} + + ~ScatterMeshInstanceInfo(); + + RenderMeshActor* m_actor; + UserRenderInstanceBuffer* m_instanceBuffer; + uint32_t m_IBSize; + physx::Array<ScatterInstanceBufferDataElement> m_instanceBufferData; + }; + + DestructibleAssetImpl(ModuleDestructibleImpl* module, DestructibleAsset* api, const char* name); + DestructibleAssetImpl(ModuleDestructibleImpl* module, DestructibleAsset* api, NvParameterized::Interface* params, const char* name); + ~DestructibleAssetImpl(); + + const NvParameterized::Interface* getAssetNvParameterized() const + { + return mParams; + } + + DestructibleActor* createDestructibleActorFromDeserializedState(NvParameterized::Interface* params, Scene&); + DestructibleActor* createDestructibleActor(const NvParameterized::Interface& params, Scene&); + void releaseDestructibleActor(DestructibleActor& actor); + + RenderMeshAsset* getRenderMeshAsset() const + { + return renderMeshAsset; + } + bool setRenderMeshAsset(RenderMeshAsset* newRenderMeshAsset); + + bool setScatterMeshAssets(RenderMeshAsset** scatterMeshAssetArray, uint32_t scatterMeshAssetArraySize); + + void createScatterMeshInstanceInfo(); + + UserRenderInstanceBufferDesc getScatterMeshInstanceBufferDesc(); + + uint32_t getScatterMeshAssetCount() const + { + return scatterMeshAssets.size(); + } + + virtual RenderMeshAsset* const * getScatterMeshAssets() const + { + return scatterMeshAssets.size() > 0 ? &scatterMeshAssets[0] : NULL; + } + + RenderMeshAsset* getRuntimeRenderMeshAsset() const + { + return runtimeRenderMeshAsset; + } + + uint32_t getInstancedChunkMeshCount() const + { + return m_instancedChunkMeshCount; + } + + uint32_t getChunkCount() const + { + return (uint32_t)mParams->chunks.arraySizes[0]; + } + uint32_t getDepthCount() const + { + return mParams->depthCount; + } + bool getScatterMeshAlwaysDrawFlag() const + { + return mParams->destructibleParameters.alwaysDrawScatterMesh; + } + uint32_t getChunkChildCount(uint32_t chunkIndex) const + { + if (chunkIndex >= (uint32_t)mParams->chunks.arraySizes[0]) + { + return 0; + } + return (uint32_t)mParams->chunks.buf[chunkIndex].numChildren; + } + uint16_t getChunkDepth(uint32_t chunkIndex) const + { + if (chunkIndex >= (uint32_t)mParams->chunks.arraySizes[0]) + { + return 0; + } + return mParams->chunks.buf[chunkIndex].depth; + } + int32_t getChunkChild(uint32_t chunkIndex, uint32_t childIndex) const + { + if (childIndex >= getChunkChildCount(chunkIndex)) + { + return -1; + } + return int32_t(mParams->chunks.buf[chunkIndex].firstChildIndex + childIndex); + } + PxBounds3 getBounds() const + { + return mParams->bounds; + } + DestructibleParameters getParameters() const; + DestructibleInitParameters getInitParameters() const; + const char* getCrumbleEmitterName() const; + const char* getDustEmitterName() const; + const char* getFracturePatternName() const; + float getFractureImpulseScale() const + { + return mParams->destructibleParameters.fractureImpulseScale; + } + float getImpactVelocityThreshold() const + { + return mParams->destructibleParameters.impactVelocityThreshold; + } + void getStats(DestructibleAssetStats& stats) const; + void cacheChunkOverlapsUpToDepth(int32_t depth = -1); + float getNeighborPadding() const + { + return mParams->neighborPadding; + } + + uint16_t getChunkParentIndex(uint32_t chunkIndex) const + { + PX_ASSERT(chunkIndex < (uint16_t)mParams->chunks.arraySizes[0]); + return mParams->chunks.buf[chunkIndex].parentIndex; + } + + PxVec3 getChunkPositionOffset(uint32_t chunkIndex) const + { + PX_ASSERT(chunkIndex < (uint16_t)mParams->chunks.arraySizes[0]); + DestructibleAssetParametersNS::Chunk_Type& sourceChunk = mParams->chunks.buf[chunkIndex]; + return (sourceChunk.flags & DestructibleAssetImpl::Instanced) == 0 ? PxVec3(0.0f) : mParams->chunkInstanceInfo.buf[sourceChunk.meshPartIndex].chunkPositionOffset; + } + + PxVec2 getChunkUVOffset(uint32_t chunkIndex) const + { + PX_ASSERT(chunkIndex < (uint16_t)mParams->chunks.arraySizes[0]); + DestructibleAssetParametersNS::Chunk_Type& sourceChunk = mParams->chunks.buf[chunkIndex]; + return (sourceChunk.flags & DestructibleAssetImpl::Instanced) == 0 ? PxVec2(0.0f) : mParams->chunkInstanceInfo.buf[sourceChunk.meshPartIndex].chunkUVOffset; + } + + uint32_t getChunkFlags(uint32_t chunkIndex) const + { + PX_ASSERT(chunkIndex < (uint16_t)mParams->chunks.arraySizes[0]); + DestructibleAssetParametersNS::Chunk_Type& sourceChunk = mParams->chunks.buf[chunkIndex]; + uint32_t flags = 0; + if (sourceChunk.flags & DestructibleAssetImpl::SupportChunk) + { + flags |= DestructibleAsset::ChunkEnvironmentallySupported; + } + if (sourceChunk.flags & DestructibleAssetImpl::UnfracturableChunk) + { + flags |= DestructibleAsset::ChunkAndDescendentsDoNotFracture; + } + if (sourceChunk.flags & DestructibleAssetImpl::UndamageableChunk) + { + flags |= DestructibleAsset::ChunkDoesNotFracture; + } + if (sourceChunk.flags & DestructibleAssetImpl::UncrumbleableChunk) + { + flags |= DestructibleAsset::ChunkDoesNotCrumble; + } + if (sourceChunk.flags & DestructibleAssetImpl::Instanced) + { + flags |= DestructibleAsset::ChunkIsInstanced; + } +#if APEX_RUNTIME_FRACTURE + if (sourceChunk.flags & DestructibleAssetImpl::RuntimeFracturableChunk) + { + flags |= DestructibleAsset::ChunkRuntimeFracture; + } +#endif + return flags; + } + + uint32_t getPartIndex(uint32_t chunkIndex) const + { + PX_ASSERT(chunkIndex < (uint16_t)mParams->chunks.arraySizes[0]); + DestructibleAssetParametersNS::Chunk_Type& sourceChunk = mParams->chunks.buf[chunkIndex]; + return (sourceChunk.flags & DestructibleAssetImpl::Instanced) == 0 ? sourceChunk.meshPartIndex : mParams->chunkInstanceInfo.buf[sourceChunk.meshPartIndex].partIndex; + } + + uint32_t getChunkHullIndexStart(uint32_t chunkIndex) const + { + return mParams->chunkConvexHullStartIndices.buf[getPartIndex(chunkIndex)]; + } + + uint32_t getChunkHullIndexStop(uint32_t chunkIndex) const + { + return mParams->chunkConvexHullStartIndices.buf[getPartIndex(chunkIndex)+1]; + } + + uint32_t getChunkHullCount(uint32_t chunkIndex) const + { + const uint32_t partIndex = getPartIndex(chunkIndex); + return mParams->chunkConvexHullStartIndices.buf[partIndex+1] - mParams->chunkConvexHullStartIndices.buf[partIndex]; + } + + uint32_t getPartHullIndexStart(uint32_t partIndex) const + { + return mParams->chunkConvexHullStartIndices.buf[partIndex]; + } + + uint32_t getPartHullIndexStop(uint32_t partIndex) const + { + return mParams->chunkConvexHullStartIndices.buf[partIndex+1]; + } + + NvParameterized::Interface** getConvexHullParameters(uint32_t hullIndex) const + { + return mParams->chunkConvexHulls.buf + hullIndex; + } + + PxBounds3 getChunkActorLocalBounds(uint32_t chunkIndex) const + { + const uint32_t partIndex = getPartIndex(chunkIndex); + PxBounds3 bounds = renderMeshAsset->getBounds(partIndex); + const PxVec3 offset = getChunkPositionOffset(chunkIndex); + bounds.minimum += offset; + bounds.maximum += offset; + return bounds; + } + + const PxBounds3& getChunkShapeLocalBounds(uint32_t chunkIndex) const + { + const uint32_t partIndex = getPartIndex(chunkIndex); + return renderMeshAsset->getBounds(partIndex); + } + + void applyTransformation(const PxMat44& transformation, float scale); + void applyTransformation(const PxMat44& transformation); + bool setPlatformMaxDepth(PlatformTag platform, uint32_t maxDepth); + bool removePlatformMaxDepth(PlatformTag platform); + + CachedOverlapsNS::IntPair_DynamicArray1D_Type* getOverlapsAtDepth(uint32_t depth, bool create = true) const; + + void clearChunkOverlaps(int32_t depth = -1, bool keepCachedFlag = false); + void addChunkOverlaps(IntPair* supportGraphEdges, uint32_t numSupportGraphEdges); + void removeChunkOverlaps(IntPair* supportGraphEdges, uint32_t numSupportGraphEdges, bool keepCachedFlagIfEmpty); + + void traceSurfaceBoundary(physx::Array<PxVec3>& outPoints, uint16_t chunkIndex, const PxTransform& localToWorldRT, const PxVec3& scale, + float spacing, float jitter, float surfaceDistance, uint32_t maxPoints); + + AuthObjTypeID getObjTypeID() const + { + return mAssetTypeID; + } + const char* getObjTypeName() const + { + return getClassName(); + } + const char* getName() const + { + return mName.c_str(); + } + + void prepareForNewInstance(); + + void resetInstanceData(); + + // DestructibleAssetAuthoring methods + virtual bool prepareForPlatform(nvidia::apex::PlatformTag platform) const; + + void setFractureImpulseScale(float scale) + { + mParams->destructibleParameters.fractureImpulseScale = scale; + } + void setImpactVelocityThreshold(float threshold) + { + mParams->destructibleParameters.impactVelocityThreshold = threshold; + } + void setChunkOverlapsCacheDepth(int32_t depth = -1); + void setParameters(const DestructibleParameters&); + void setInitParameters(const DestructibleInitParameters&); + void setCrumbleEmitterName(const char*); + void setDustEmitterName(const char*); + void setFracturePatternName(const char*); + void setNeighborPadding(float neighborPadding) + { + mParams->neighborPadding = neighborPadding; + } + + uint32_t forceLoadAssets(); + void initializeAssetNameTable(); + + void cleanup(); + ModuleDestructibleImpl* getOwner() + { + return module; + } + DestructibleAsset* getAsset() + { + return mNxAssetApi; + } + + static AuthObjTypeID getAssetTypeID() + { + return mAssetTypeID; + } + + virtual NvParameterized::Interface* getDefaultActorDesc(); + virtual NvParameterized::Interface* getDefaultAssetPreviewDesc(); + virtual Actor* createApexActor(const NvParameterized::Interface& params, Scene& apexScene); + + virtual AssetPreview* createApexAssetPreview(const ::NvParameterized::Interface& /*params*/, AssetPreviewScene* /*previewScene*/); + + virtual bool isValidForActorCreation(const ::NvParameterized::Interface& /*parms*/, Scene& /*apexScene*/) const; + + uint32_t getActorTransformCount() const + { + return (uint32_t)mParams->actorTransforms.arraySizes[0]; + } + + const PxMat44* getActorTransforms() const + { + return mParams->actorTransforms.buf; + } + + void appendActorTransforms(const PxMat44* transforms, uint32_t transformCount); + + void clearActorTransforms(); + + bool rebuildCollisionGeometry(uint32_t partIndex, const DestructibleGeometryDesc& geometryDesc); + + + NvParameterized::Interface* acquireNvParameterizedInterface(void) + { + NvParameterized::Interface* ret = mParams; + + // don't set mParams to NULL here, because it's read during the asset release + mOwnsParams = false; + + return ret; + } + +protected: + + void init(); + + void calculateChunkDepthStarts(); + void calculateChunkOverlaps(physx::Array<IntPair>& overlaps, uint32_t depth) const; + + void reduceAccordingToLOD(); + + void updateChunkInstanceRenderResources(bool rewriteBuffers, void* userRenderData); + + static bool chunksInProximity(const DestructibleAssetImpl& asset0, uint16_t chunkIndex0, const PxTransform& tm0, const PxVec3& scale0, + const DestructibleAssetImpl& asset1, uint16_t chunkIndex1, const PxTransform& tm1, const PxVec3& scale1, + float padding); + + bool chunkAndSphereInProximity(uint16_t chunkIndex, const PxTransform& chunkTM, const PxVec3& chunkScale, + const PxVec3& sphereWorldCenter, float sphereRadius, float padding, float* distance); + + static DestructibleParameters getParameters(const DestructibleAssetParametersNS::DestructibleParameters_Type&, + const DestructibleAssetParametersNS::DestructibleDepthParameters_DynamicArray1D_Type*); + static void setParameters(const DestructibleParameters&, DestructibleAssetParametersNS::DestructibleParameters_Type&); + + static AuthObjTypeID mAssetTypeID; + static const char* getClassName() + { + return DESTRUCTIBLE_AUTHORING_TYPE_NAME; + } + ApexSimpleString mName; + + DestructibleAsset* mNxAssetApi; + ModuleDestructibleImpl* module; + + DestructibleAssetParameters* mParams; + bool mOwnsParams; + + // Has a parameterized internal representation + Array<ConvexHullImpl> chunkConvexHulls; + + // Runtime / derived + int32_t chunkOverlapCacheDepth; + Array<ResID> mStaticMaterialIDs; + + ApexAssetTracker mCrumbleAssetTracker; + ApexAssetTracker mDustAssetTracker; + + RenderMeshAsset* renderMeshAsset; + RenderMeshAsset* runtimeRenderMeshAsset; + + physx::Array<PxConvexMesh*>* mCollisionMeshes; + + uint32_t mRuntimeCookedConvexCount; + + Array<RenderMeshAsset*> scatterMeshAssets; + + // Instanced chunks + uint16_t m_instancedChunkMeshCount; + physx::Array<RenderMeshActor*> m_instancedChunkRenderMeshActors; // One per render mesh actor per instanced chunk + physx::Array<uint16_t> m_instancedChunkActorVisiblePart; + physx::Array<uint16_t> m_instancedChunkActorMap; // from instanced chunk instanceInfo index to actor index + physx::Array<UserRenderInstanceBuffer*> m_chunkInstanceBuffers; + physx::Array< physx::Array< ChunkInstanceBufferDataElement > > m_chunkInstanceBufferData; + + // Scatter meshes + physx::Array<ScatterMeshInstanceInfo> m_scatterMeshInstanceInfo; // One per scatter mesh asset + + uint32_t m_currentInstanceBufferActorAllowance; + bool m_needsInstanceBufferDataResize; + bool m_needsInstanceBufferResize; + nvidia::Mutex m_chunkInstanceBufferDataLock; + + bool m_needsScatterMeshInstanceInfoCreation; + + int32_t m_instancingRepresentativeActorIndex; // -1 => means it's not set + + ResourceList m_destructibleList; + ResourceList m_previewList; + + friend class DestructibleStructure; + friend class DestructiblePreviewImpl; + friend class DestructibleActorImpl; + friend class DestructibleActorJointImpl; + friend class DestructibleScene; + friend class ModuleDestructibleImpl; + friend class DestructibleAssetCollision; + friend class DestructibleModuleCachedData; + friend class ApexDamageEventReportDataImpl; + friend class DestructibleRenderableImpl; + + NvParameterized::Interface* mApexDestructibleActorParams; + +private: + struct PlatformKeyValuePair + { + PlatformKeyValuePair(nvidia::apex::PlatformTag k, uint32_t v): key(k), val(v) {} + ~PlatformKeyValuePair() {} + nvidia::apex::PlatformTag key; + uint32_t val; + private: + PlatformKeyValuePair(); + }; + Array<PlatformKeyValuePair> m_platformFractureDepthMap; + bool setDepthCount(uint32_t targetDepthCount) const; +}; + +#ifndef WITHOUT_APEX_AUTHORING + +void gatherPartMesh(physx::Array<PxVec3>& vertices, physx::Array<uint32_t>& indices, const RenderMeshAsset* renderMeshAsset, uint32_t partIndex); + +class DestructibleAssetAuthoringImpl : public DestructibleAssetImpl +{ +public: + + ExplicitHierarchicalMeshImpl hMesh; + ExplicitHierarchicalMeshImpl hMeshCore; + CutoutSetImpl cutoutSet; + IntersectMesh intersectMesh; + + DestructibleAssetAuthoringImpl(ModuleDestructibleImpl* module, DestructibleAsset* api, const char* name) : + DestructibleAssetImpl(module, api, name) {} + + DestructibleAssetAuthoringImpl(ModuleDestructibleImpl* module, DestructibleAsset* api, NvParameterized::Interface* params, const char* name) : + DestructibleAssetImpl(module, api, params, name) {} + + void setToolString(const char* toolString); + + void cookChunks(const DestructibleAssetCookingDesc&, bool cacheOverlaps, uint32_t* chunkIndexMapUser2Apex, uint32_t* chunkIndexMapApex2User, uint32_t chunkIndexMapCount); + + void trimCollisionGeometry(const uint32_t* partIndices, uint32_t partIndexCount, float maxTrimFraction = 0.2f); + + void serializeFractureToolState(PxFileBuf& stream, nvidia::ExplicitHierarchicalMesh::Embedding& embedding) const; + void deserializeFractureToolState(PxFileBuf& stream, nvidia::ExplicitHierarchicalMesh::Embedding& embedding); + +private: + void trimCollisionGeometryInternal(const uint32_t* chunkIndices, uint32_t chunkIndexCount, const physx::Array<IntPair>& parentDepthOverlaps, uint32_t depth, float maxTrimFraction); +}; +#endif + +} +} // end namespace nvidia + +#endif // DESTRUCTIBLE_ASSET_IMPL_H diff --git a/APEX_1.4/module/destructible/include/DestructibleAssetProxy.h b/APEX_1.4/module/destructible/include/DestructibleAssetProxy.h new file mode 100644 index 00000000..d427a849 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleAssetProxy.h @@ -0,0 +1,923 @@ +/* + * 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 DESTRUCTIBLE_ASSET_PROXY_H +#define DESTRUCTIBLE_ASSET_PROXY_H + +#include "ModuleDestructibleImpl.h" +#include "DestructibleAsset.h" +#include "DestructibleAssetImpl.h" +#include "PsUserAllocated.h" +#include "authoring/Fracturing.h" +#include "ApexUsingNamespace.h" +#include "ApexAuthorableObject.h" +#include "ApexAssetAuthoring.h" + +#include "PsArray.h" +#include "nvparameterized/NvParameterized.h" + +#include "ApexRWLockable.h" +#include "ReadCheck.h" +#include "WriteCheck.h" + +#pragma warning(disable: 4355) // 'this' : used in base member initialization list + +namespace nvidia +{ +namespace destructible +{ + +class DestructibleAssetProxy : public DestructibleAsset, public ApexResourceInterface, public UserAllocated, public ApexRWLockable +{ +public: + APEX_RW_LOCKABLE_BOILERPLATE + + DestructibleAssetImpl impl; + + DestructibleAssetProxy(ModuleDestructibleImpl* module, ResourceList& list, const char* name) : + impl(module, this, name) + { + list.add(*this); + } + + DestructibleAssetProxy(ModuleDestructibleImpl* module, ResourceList& list, NvParameterized::Interface* params, const char* name) : + impl(module, this, params, name) + { + list.add(*this); + } + + ~DestructibleAssetProxy() + { + } + + PxBounds3 getChunkActorLocalBounds(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getChunkActorLocalBounds(chunkIndex); + } + + const NvParameterized::Interface* getAssetNvParameterized() const + { + READ_ZONE(); + return impl.getAssetNvParameterized(); + } + + /** + * \brief Releases the ApexAsset but returns the NvParameterized::Interface and *ownership* to the caller. + */ + virtual NvParameterized::Interface* releaseAndReturnNvParameterizedInterface(void) + { + NvParameterized::Interface* ret = impl.acquireNvParameterizedInterface(); + release(); + return ret; + } + + virtual void releaseDestructibleActor(DestructibleActor& actor) + { + WRITE_ZONE(); + impl.releaseDestructibleActor(actor); + } + virtual DestructibleParameters getDestructibleParameters() const + { + return impl.getParameters(); + } + virtual DestructibleInitParameters getDestructibleInitParameters() const + { + return impl.getInitParameters(); + } + virtual uint32_t getChunkCount() const + { + return impl.getChunkCount(); + } + virtual uint32_t getDepthCount() const + { + READ_ZONE(); + return impl.getDepthCount(); + } + virtual RenderMeshAsset* getRenderMeshAsset() const + { + READ_ZONE(); + return impl.getRenderMeshAsset(); + } + virtual bool setRenderMeshAsset(RenderMeshAsset* renderMeshAsset) + { + WRITE_ZONE(); + return impl.setRenderMeshAsset(renderMeshAsset); + } + virtual uint32_t getScatterMeshAssetCount() const + { + READ_ZONE(); + return impl.getScatterMeshAssetCount(); + } + virtual RenderMeshAsset* const * getScatterMeshAssets() const + { + READ_ZONE(); + return impl.getScatterMeshAssets(); + } + virtual uint32_t getInstancedChunkMeshCount() const + { + READ_ZONE(); + return impl.getInstancedChunkMeshCount(); + } + virtual const char* getCrumbleEmitterName() const + { + READ_ZONE(); + return impl.getCrumbleEmitterName(); + } + virtual const char* getDustEmitterName() const + { + READ_ZONE(); + return impl.getDustEmitterName(); + } + virtual const char* getFracturePatternName() const + { + return impl.getFracturePatternName(); + } + virtual void getStats(DestructibleAssetStats& stats) const + { + READ_ZONE(); + impl.getStats(stats); + } + + virtual void cacheChunkOverlapsUpToDepth(int32_t depth = -1) + { + WRITE_ZONE(); + impl.cacheChunkOverlapsUpToDepth(depth); + } + + virtual void clearChunkOverlaps(int32_t depth = -1, bool keepCachedFlag = false) + { + impl.clearChunkOverlaps(depth, keepCachedFlag); + } + + virtual void addChunkOverlaps(IntPair* supportGraphEdges, uint32_t numSupportGraphEdges) + { + impl.addChunkOverlaps(supportGraphEdges, numSupportGraphEdges); + } + + virtual void removeChunkOverlaps(IntPair* supportGraphEdges, uint32_t numSupportGraphEdges, bool keepCachedFlagIfEmpty) + { + impl.removeChunkOverlaps(supportGraphEdges, numSupportGraphEdges, keepCachedFlagIfEmpty); + } + + virtual uint32_t getCachedOverlapCountAtDepth(uint32_t depth) const + { + READ_ZONE(); + CachedOverlapsNS::IntPair_DynamicArray1D_Type* pairArray = impl.getOverlapsAtDepth(depth, false); + return uint32_t(pairArray != NULL ? pairArray->arraySizes[0] : 0); + } + + virtual const IntPair* getCachedOverlapsAtDepth(uint32_t depth) const + { + READ_ZONE(); + CachedOverlapsNS::IntPair_DynamicArray1D_Type* pairArray = impl.getOverlapsAtDepth(depth, false); + PX_ASSERT(sizeof(IntPair) == pairArray->elementSize); + return pairArray != NULL ? (const IntPair*)pairArray->buf : NULL; + } + + NvParameterized::Interface* getDefaultActorDesc() + { + return impl.getDefaultActorDesc(); + } + + NvParameterized::Interface* getDefaultAssetPreviewDesc() + { + return impl.getDefaultAssetPreviewDesc(); + } + + virtual Actor* createApexActor(const NvParameterized::Interface& parms, Scene& apexScene) + { + return impl.createApexActor(parms, apexScene); + } + + virtual DestructibleActor* createDestructibleActorFromDeserializedState(NvParameterized::Interface* parms, Scene& apexScene) + { + WRITE_ZONE(); + return impl.createDestructibleActorFromDeserializedState(parms, apexScene); + } + + virtual AssetPreview* createApexAssetPreview(const NvParameterized::Interface& params, AssetPreviewScene* /*previewScene*/) + { + return impl.createApexAssetPreview(params, NULL); + } + + virtual bool isValidForActorCreation(const ::NvParameterized::Interface& parms, Scene& apexScene) const + { + return impl.isValidForActorCreation(parms, apexScene); + } + + virtual bool isDirty() const + { + return false; + } + + virtual PxVec3 getChunkPositionOffset(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getChunkPositionOffset(chunkIndex); + } + + virtual PxVec2 getChunkUVOffset(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getChunkUVOffset(chunkIndex); + } + + virtual uint32_t getChunkFlags(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getChunkFlags(chunkIndex); + } + + virtual uint16_t getChunkDepth(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getChunkDepth(chunkIndex); + } + + virtual int32_t getChunkParentIndex(uint32_t chunkIndex) const + { + READ_ZONE(); + const uint16_t chunkParentIndex = impl.getChunkParentIndex(chunkIndex); + return chunkParentIndex != DestructibleAssetImpl::InvalidChunkIndex ? (int32_t)chunkParentIndex : -1; + } + + virtual uint32_t getPartIndex(uint32_t chunkIndex) const + { + READ_ZONE(); + return impl.getPartIndex(chunkIndex); + } + + virtual uint32_t getPartConvexHullCount(const uint32_t partIndex) const + { + READ_ZONE(); + return impl.getPartHullIndexStop(partIndex) - impl.getPartHullIndexStart(partIndex); + } + + virtual NvParameterized::Interface** getPartConvexHullArray(const uint32_t partIndex) const + { + READ_ZONE(); + return impl.getConvexHullParameters(impl.getPartHullIndexStart(partIndex)); + } + + uint32_t getActorTransformCount() const + { + READ_ZONE(); + return impl.getActorTransformCount(); + } + const PxMat44* getActorTransforms() const + { + READ_ZONE(); + return impl.getActorTransforms(); + } + + void applyTransformation(const PxMat44& transformation, float scale) + { + WRITE_ZONE(); + impl.applyTransformation(transformation, scale); + } + void applyTransformation(const PxMat44& transformation) + { + WRITE_ZONE(); + impl.applyTransformation(transformation); + } + + virtual bool rebuildCollisionGeometry(uint32_t partIndex, const DestructibleGeometryDesc& geometryDesc) + { + WRITE_ZONE(); + return impl.rebuildCollisionGeometry(partIndex, geometryDesc); + } + + // ApexInterface methods + virtual void release() + { + WRITE_ZONE(); + impl.getOwner()->mSdk->releaseAsset(*this); + } + virtual void destroy() + { + impl.cleanup(); + delete this; + } + + // Asset methods + virtual const char* getName() const + { + READ_ZONE(); + return impl.getName(); + } + static const char* getClassName() + { + return DESTRUCTIBLE_AUTHORING_TYPE_NAME; + } + virtual AuthObjTypeID getObjTypeID() const + { + return impl.getObjTypeID(); + } + virtual const char* getObjTypeName() const + { + return impl.getObjTypeName(); + } + virtual uint32_t forceLoadAssets() + { + return impl.forceLoadAssets(); + } + + // ApexResourceInterface methods + virtual void setListIndex(ResourceList& list, uint32_t index) + { + impl.m_listIndex = index; + impl.m_list = &list; + } + virtual uint32_t getListIndex() const + { + return impl.m_listIndex; + } + + friend class DestructibleActorImpl; +}; + +#ifndef WITHOUT_APEX_AUTHORING +class DestructibleAssetAuthoringProxy : public DestructibleAssetAuthoring, public ApexResourceInterface, public ApexAssetAuthoring, public UserAllocated, public ApexRWLockable +{ +public: + APEX_RW_LOCKABLE_BOILERPLATE + + DestructibleAssetAuthoringImpl impl; + + DestructibleAssetAuthoringProxy(ModuleDestructibleImpl* module, ResourceList& list) : + impl(module, NULL, "DestructibleAuthoring") + { + list.add(*this); + } + + DestructibleAssetAuthoringProxy(ModuleDestructibleImpl* module, ResourceList& list, const char* name) : + impl(module, NULL, name) + { + list.add(*this); + } + + DestructibleAssetAuthoringProxy(ModuleDestructibleImpl* module, ResourceList& list, NvParameterized::Interface* params, const char* name) : + impl(module, NULL, params, name) + { + list.add(*this); + } + + virtual ~DestructibleAssetAuthoringProxy() + { + } + + // DestructibleAssetAuthoring methods + + virtual ExplicitHierarchicalMesh& getExplicitHierarchicalMesh() + { + return impl.hMesh; + } + + virtual ExplicitHierarchicalMesh& getCoreExplicitHierarchicalMesh() + { + return impl.hMeshCore; + } + + virtual CutoutSet& getCutoutSet() + { + return impl.cutoutSet; + } + + virtual uint32_t partitionMeshByIslands + ( + nvidia::ExplicitRenderTriangle* mesh, + uint32_t meshTriangleCount, + uint32_t* meshPartition, + uint32_t meshPartitionMaxCount, + float padding + ) + { + return ::FractureTools::partitionMeshByIslands(mesh, meshTriangleCount, meshPartition, meshPartitionMaxCount, padding); + } + + virtual bool setRootMesh + ( + const ExplicitRenderTriangle* meshTriangles, + uint32_t meshTriangleCount, + const ExplicitSubmeshData* submeshData, + uint32_t submeshCount, + uint32_t* meshPartition = NULL, + uint32_t meshPartitionCount = 0, + int32_t* parentIndices = NULL, + uint32_t parentIndexCount = 0 + ) + { + return ::FractureTools::buildExplicitHierarchicalMesh(impl.hMesh, meshTriangles, meshTriangleCount, submeshData, submeshCount, meshPartition, meshPartitionCount, parentIndices, parentIndexCount); + } + + virtual bool importRenderMeshAssetToRootMesh(const nvidia::RenderMeshAsset& renderMeshAsset, uint32_t maxRootDepth = UINT32_MAX) + { + return ::FractureTools::buildExplicitHierarchicalMeshFromRenderMeshAsset(impl.hMesh, renderMeshAsset, maxRootDepth); + } + + virtual bool importDestructibleAssetToRootMesh(const DestructibleAsset& destructibleAsset, uint32_t maxRootDepth = UINT32_MAX) + { + return ::FractureTools::buildExplicitHierarchicalMeshFromDestructibleAsset(impl.hMesh, destructibleAsset, maxRootDepth); + } + + virtual bool setCoreMesh + ( + const ExplicitRenderTriangle* meshTriangles, + uint32_t meshTriangleCount, + const ExplicitSubmeshData* submeshData, + uint32_t submeshCount, + uint32_t* meshPartition = NULL, + uint32_t meshPartitionCount = 0 + ) + { + return ::FractureTools::buildExplicitHierarchicalMesh(impl.hMeshCore, meshTriangles, meshTriangleCount, submeshData, submeshCount, meshPartition, meshPartitionCount); + } + + virtual bool buildExplicitHierarchicalMesh + ( + ExplicitHierarchicalMesh& hMesh, + const ExplicitRenderTriangle* meshTriangles, + uint32_t meshTriangleCount, + const ExplicitSubmeshData* submeshData, + uint32_t submeshCount, + uint32_t* meshPartition = NULL, + uint32_t meshPartitionCount = 0, + int32_t* parentIndices = NULL, + uint32_t parentIndexCount = 0 + ) + { + return ::FractureTools::buildExplicitHierarchicalMesh(hMesh, meshTriangles, meshTriangleCount, submeshData, submeshCount, meshPartition, meshPartitionCount, parentIndices, parentIndexCount); + } + + virtual bool createHierarchicallySplitMesh + ( + const MeshProcessingParameters& meshProcessingParams, + const FractureSliceDesc& desc, + const CollisionDesc& collisionDesc, + bool exportCoreMesh, + int32_t coreMeshImprintSubmeshIndex, + uint32_t randomSeed, + IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::createHierarchicallySplitMesh(impl.hMesh, impl.hMeshCore, exportCoreMesh, coreMeshImprintSubmeshIndex, + meshProcessingParams, desc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual bool createVoronoiSplitMesh + ( + const ::FractureTools::MeshProcessingParameters& meshProcessingParams, + const ::FractureTools::FractureVoronoiDesc& desc, + const CollisionDesc& collisionDesc, + bool exportCoreMesh, + int32_t coreMeshImprintSubmeshIndex, + uint32_t randomSeed, + IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::createVoronoiSplitMesh(impl.hMesh, impl.hMeshCore, exportCoreMesh, coreMeshImprintSubmeshIndex, + meshProcessingParams, desc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual bool hierarchicallySplitChunk + ( + uint32_t chunkIndex, + const ::FractureTools::MeshProcessingParameters& meshProcessingParams, + const ::FractureTools::FractureSliceDesc& desc, + const CollisionDesc& collisionDesc, + uint32_t* randomSeed, + IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::hierarchicallySplitChunk(impl.hMesh, chunkIndex, meshProcessingParams, desc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual bool voronoiSplitChunk + ( + uint32_t chunkIndex, + const ::FractureTools::MeshProcessingParameters& meshProcessingParams, + const ::FractureTools::FractureVoronoiDesc& desc, + const CollisionDesc& collisionDesc, + uint32_t* randomSeed, + IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::voronoiSplitChunk(impl.hMesh, chunkIndex, meshProcessingParams, desc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual bool createChippedMesh + ( + const MeshProcessingParameters& meshProcessingParams, + const FractureCutoutDesc& desc, + const CutoutSet& iCutoutSet, + const FractureSliceDesc& sliceDesc, + const FractureVoronoiDesc& voronoiDesc, + const CollisionDesc& collisionDesc, + uint32_t randomSeed, + IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::createChippedMesh(impl.hMesh, meshProcessingParams, desc, iCutoutSet, sliceDesc, voronoiDesc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual void buildCutoutSet + ( + const uint8_t* pixelBuffer, + uint32_t bufferWidth, + uint32_t bufferHeight, + float snapThreshold, + bool periodic + ) + { + ::FractureTools::buildCutoutSet(impl.cutoutSet, pixelBuffer, bufferWidth, bufferHeight, snapThreshold, periodic); + } + + virtual bool calculateCutoutUVMapping(PxMat33& mapping, const nvidia::ExplicitRenderTriangle& triangle) + { + return ::FractureTools::calculateCutoutUVMapping(triangle, mapping); + } + + virtual bool calculateCutoutUVMapping(PxMat33& mapping, const PxVec3& targetDirection) + { + return ::FractureTools::calculateCutoutUVMapping(impl.hMesh, targetDirection, mapping); + } + + virtual uint32_t createVoronoiSitesInsideMesh + ( + PxVec3* siteBuffer, + uint32_t* siteChunkIndices, + uint32_t siteCount, + uint32_t* randomSeed, + uint32_t* microgridSize, + BSPOpenMode::Enum meshMode, + IProgressListener& progressListener, + uint32_t chunkIndex = 0xFFFFFFFF + ) + { + return ::FractureTools::createVoronoiSitesInsideMesh(impl.hMesh, siteBuffer, siteChunkIndices, siteCount, randomSeed, microgridSize, meshMode, progressListener, chunkIndex); + } + + uint32_t createScatterMeshSites + ( + uint8_t* meshIndices, + PxMat44* relativeTransforms, + uint32_t* chunkMeshStarts, + uint32_t scatterMeshInstancesBufferSize, + uint32_t targetChunkCount, + const uint16_t* targetChunkIndices, + uint32_t* randomSeed, + uint32_t scatterMeshAssetCount, + nvidia::RenderMeshAsset** scatterMeshAssets, + const uint32_t* minCount, + const uint32_t* maxCount, + const float* minScales, + const float* maxScales, + const float* maxAngles + ) + { + return ::FractureTools::createScatterMeshSites(meshIndices, relativeTransforms, chunkMeshStarts, scatterMeshInstancesBufferSize, impl.hMesh, targetChunkCount, targetChunkIndices, + randomSeed, scatterMeshAssetCount, scatterMeshAssets, minCount, maxCount, minScales, maxScales, maxAngles); + } + + virtual void visualizeVoronoiCells + ( + nvidia::RenderDebugInterface& debugRender, + const PxVec3* sites, + uint32_t siteCount, + const uint32_t* cellColors, + uint32_t cellColorCount, + const PxBounds3& bounds, + uint32_t cellIndex = 0xFFFFFFFF + ) + { + ::FractureTools::visualizeVoronoiCells(debugRender, sites, siteCount, cellColors, cellColorCount, bounds, cellIndex); + } + + virtual void setBSPTolerances + ( + float linearTolerance, + float angularTolerance, + float baseTolerance, + float clipTolerance, + float cleaningTolerance + ) + { + ::FractureTools::setBSPTolerances(linearTolerance, angularTolerance, baseTolerance, clipTolerance, cleaningTolerance); + } + + virtual void setBSPBuildParameters + ( + float logAreaSigmaThreshold, + uint32_t testSetSize, + float splitWeight, + float imbalanceWeight + ) + { + ::FractureTools::setBSPBuildParameters(logAreaSigmaThreshold, testSetSize, splitWeight, imbalanceWeight); + } + + virtual ExplicitHierarchicalMesh::ConvexHull* createExplicitHierarchicalMeshConvexHull() + { + return ::FractureTools::createExplicitHierarchicalMeshConvexHull(); + } + + virtual uint32_t buildSliceMesh(const ExplicitRenderTriangle*& mesh, const ::FractureTools::NoiseParameters& noiseParameters, const PxPlane& slicePlane, uint32_t randomSeed) + { + if( ::FractureTools::buildSliceMesh(impl.intersectMesh, impl.hMesh, slicePlane, noiseParameters, randomSeed) ) + { + mesh = impl.intersectMesh.m_triangles.begin(); + return impl.intersectMesh.m_triangles.size(); + } + + mesh = NULL; + return 0; + } + + virtual void setChunkOverlapsCacheDepth(int32_t depth = -1) + { + impl.setChunkOverlapsCacheDepth(depth); + } + virtual RenderMeshAsset* getRenderMeshAsset() const + { + return impl.getRenderMeshAsset(); + } + virtual bool setRenderMeshAsset(RenderMeshAsset* renderMeshAsset) + { + return impl.setRenderMeshAsset(renderMeshAsset); + } + virtual bool setScatterMeshAssets(RenderMeshAsset** scatterMeshAssetArray, uint32_t scatterMeshAssetArraySize) + { + return impl.setScatterMeshAssets(scatterMeshAssetArray, scatterMeshAssetArraySize); + } + virtual uint32_t getScatterMeshAssetCount() const + { + return impl.getScatterMeshAssetCount(); + } + virtual RenderMeshAsset* const * getScatterMeshAssets() const + { + return impl.getScatterMeshAssets(); + } + virtual uint32_t getInstancedChunkMeshCount() const + { + return impl.getInstancedChunkMeshCount(); + } + virtual void setDestructibleParameters(const DestructibleParameters& parameters) + { + impl.setParameters(parameters); + } + virtual DestructibleParameters getDestructibleParameters() const + { + READ_ZONE(); + return impl.getParameters(); + } + virtual void setDestructibleInitParameters(const DestructibleInitParameters& parameters) + { + impl.setInitParameters(parameters); + } + virtual DestructibleInitParameters getDestructibleInitParameters() const + { + READ_ZONE(); + return impl.getInitParameters(); + } + virtual void setCrumbleEmitterName(const char* name) + { + impl.setCrumbleEmitterName(name); + } + virtual void setDustEmitterName(const char* name) + { + impl.setDustEmitterName(name); + } + virtual void setFracturePatternName(const char* name) + { + impl.setFracturePatternName(name); + } + virtual void cookChunks(const DestructibleAssetCookingDesc& cookingDesc, bool cacheOverlaps, uint32_t* chunkIndexMapUser2Apex, uint32_t* chunkIndexMapApex2User, uint32_t chunkIndexMapCount) + { + impl.cookChunks(cookingDesc, cacheOverlaps, chunkIndexMapApex2User, chunkIndexMapUser2Apex, chunkIndexMapCount); + } + virtual void serializeFractureToolState(PxFileBuf& stream, nvidia::ExplicitHierarchicalMesh::Embedding& embedding) const + { + impl.serializeFractureToolState(stream, embedding); + } + virtual void deserializeFractureToolState(PxFileBuf& stream, nvidia::ExplicitHierarchicalMesh::Embedding& embedding) + { + impl.deserializeFractureToolState(stream, embedding); + } + virtual uint32_t getChunkCount() const + { + READ_ZONE(); + return impl.getChunkCount(); + } + virtual uint32_t getDepthCount() const + { + return impl.getDepthCount(); + } + virtual uint32_t getChunkChildCount(uint32_t chunkIndex) const + { + return impl.getChunkChildCount(chunkIndex); + } + virtual int32_t getChunkChild(uint32_t chunkIndex, uint32_t childIndex) const + { + return impl.getChunkChild(chunkIndex, childIndex); + } + virtual PxVec3 getChunkPositionOffset(uint32_t chunkIndex) const + { + return impl.getChunkPositionOffset(chunkIndex); + } + virtual PxVec2 getChunkUVOffset(uint32_t chunkIndex) const + { + return impl.getChunkUVOffset(chunkIndex); + } + virtual uint32_t getPartIndex(uint32_t chunkIndex) const + { + return impl.getPartIndex(chunkIndex); + } + virtual void trimCollisionGeometry(const uint32_t* partIndices, uint32_t partIndexCount, float maxTrimFraction = 0.2f) + { + impl.trimCollisionGeometry(partIndices, partIndexCount, maxTrimFraction); + } + virtual float getImpactVelocityThreshold() const + { + return impl.getImpactVelocityThreshold(); + } + void setImpactVelocityThreshold(float threshold) + { + impl.setImpactVelocityThreshold(threshold); + } + virtual float getFractureImpulseScale() const + { + return impl.getFractureImpulseScale(); + } + void setFractureImpulseScale(float scale) + { + impl.setFractureImpulseScale(scale); + } + virtual void getStats(DestructibleAssetStats& stats) const + { + impl.getStats(stats); + } + + virtual void cacheChunkOverlapsUpToDepth(int32_t depth = -1) + { + impl.cacheChunkOverlapsUpToDepth(depth); + } + + virtual void clearChunkOverlaps(int32_t depth = -1, bool keepCachedFlag = false) + { + impl.clearChunkOverlaps(depth, keepCachedFlag); + } + + virtual void addChunkOverlaps(IntPair* supportGraphEdges, uint32_t numSupportGraphEdges) + { + impl.addChunkOverlaps(supportGraphEdges, numSupportGraphEdges); + } + + virtual void removeChunkOverlaps(IntPair* supportGraphEdges, uint32_t numSupportGraphEdges, bool keepCachedFlagIfEmpty) + { + impl.removeChunkOverlaps(supportGraphEdges, numSupportGraphEdges, keepCachedFlagIfEmpty); + } + + virtual uint32_t getCachedOverlapCountAtDepth(uint32_t depth) + { + CachedOverlapsNS::IntPair_DynamicArray1D_Type* pairArray = impl.getOverlapsAtDepth(depth, false); + return uint32_t(pairArray != NULL ? pairArray->arraySizes[0] : 0); + } + + virtual const IntPair* getCachedOverlapsAtDepth(uint32_t depth) + { + CachedOverlapsNS::IntPair_DynamicArray1D_Type* pairArray = impl.getOverlapsAtDepth(depth, false); + PX_ASSERT(sizeof(IntPair) == pairArray->elementSize); + return pairArray != NULL ? (const IntPair*)pairArray->buf : NULL; + } + virtual void setNeighborPadding(float neighborPadding) + { + impl.setNeighborPadding(neighborPadding); + } + virtual float getNeighborPadding() const + { + return impl.getNeighborPadding(); + } + void applyTransformation(const PxMat44& transformation, float scale) + { + impl.applyTransformation(transformation, scale); + } + void applyTransformation(const PxMat44& transformation) + { + impl.applyTransformation(transformation); + } + + bool setPlatformMaxDepth(PlatformTag platform, uint32_t maxDepth) + { + return impl.setPlatformMaxDepth(platform, maxDepth); + } + + bool removePlatformMaxDepth(PlatformTag platform) + { + return impl.removePlatformMaxDepth(platform); + } + + // AssetAuthoring methods + + const char* getName(void) const + { + return impl.getName(); + } + + const char* getObjTypeName() const + { + return impl.getObjTypeName(); + } + + virtual bool prepareForPlatform(nvidia::apex::PlatformTag platformTag) + { + return impl.prepareForPlatform(platformTag); + } + + void setToolString(const char* toolName, const char* toolVersion, uint32_t toolChangelist) + { + ApexAssetAuthoring::setToolString(toolName, toolVersion, toolChangelist); + } + + void setToolString(const char* toolString) + { + impl.setToolString(toolString); + } + + uint32_t getActorTransformCount() const + { + return impl.getActorTransformCount(); + } + + const PxMat44* getActorTransforms() const + { + return impl.getActorTransforms(); + } + + void appendActorTransforms(const PxMat44* transforms, uint32_t transformCount) + { + impl.appendActorTransforms(transforms, transformCount); + } + + void clearActorTransforms() + { + impl.clearActorTransforms(); + } + + NvParameterized::Interface* getNvParameterized() const + { + return (NvParameterized::Interface*)impl.getAssetNvParameterized(); + } + + /** + * \brief Releases the ApexAsset but returns the NvParameterized::Interface and *ownership* to the caller. + */ + virtual NvParameterized::Interface* releaseAndReturnNvParameterizedInterface(void) + { + NvParameterized::Interface* ret = impl.acquireNvParameterizedInterface(); + release(); + return ret; + } + + + // ApexResourceInterface methods + virtual void setListIndex(ResourceList& list, uint32_t index) + { + impl.m_listIndex = index; + impl.m_list = &list; + } + virtual uint32_t getListIndex() const + { + return impl.m_listIndex; + } + + // ApexInterface methods + virtual void release() + { + impl.getOwner()->mSdk->releaseAssetAuthoring(*this); + } + virtual void destroy() + { + impl.cleanup(); + delete this; + } +}; +#endif + +} +} // end namespace nvidia + +#endif // DESTRUCTIBLE_ASSET_PROXY_H diff --git a/APEX_1.4/module/destructible/include/DestructibleHelpers.h b/APEX_1.4/module/destructible/include/DestructibleHelpers.h new file mode 100644 index 00000000..e44755fd --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleHelpers.h @@ -0,0 +1,79 @@ +/* + * 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 __DESTRUCTIBLEHELPERS_H__ +#define __DESTRUCTIBLEHELPERS_H__ + +#include "Apex.h" +#include "ApexSDKHelpers.h" +#include "PsUserAllocated.h" +#include "PsMemoryBuffer.h" + +#include "DestructibleAsset.h" +#include "NxPhysicsSDK.h" + +/* + For managing mesh cooking at various scales + */ + +namespace nvidia +{ +namespace destructible +{ + +class ConvexHullAtScale +{ +public: + ConvexHullAtScale() : scale(1), convexMesh(NULL) {} + ConvexHullAtScale(const PxVec3& inScale) : scale(inScale), convexMesh(NULL) {} + + PxVec3 scale; + PxConvexMesh* convexMesh; + physx::Array<uint8_t> cookedHullData; +}; + +class MultiScaledConvexHull : public UserAllocated +{ +public: + ConvexHullAtScale* getConvexHullAtScale(const PxVec3& scale, float tolerance = 0.0001f) + { + // Find mesh at scale. If not found, create one. + for (uint32_t index = 0; index < meshes.size(); ++index) + { + if (PxVec3equals(meshes[index].scale, scale, tolerance)) + { + return &meshes[index]; + } + } + meshes.insert(); + return new(&meshes.back()) ConvexHullAtScale(scale); + } + + void releaseConvexMeshes() + { + for (uint32_t index = 0; index < meshes.size(); ++index) + { + if (meshes[index].convexMesh != NULL) + { + GetApexSDK()->getPhysXSDK()->releaseConvexMesh(*meshes[index].convexMesh); + meshes[index].convexMesh = NULL; + } + } + } + + Array<ConvexHullAtScale> meshes; +}; + + +} +} // end namespace nvidia + +#endif // __DESTRUCTIBLEHELPERS_H__ diff --git a/APEX_1.4/module/destructible/include/DestructiblePreviewImpl.h b/APEX_1.4/module/destructible/include/DestructiblePreviewImpl.h new file mode 100644 index 00000000..359dbb96 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructiblePreviewImpl.h @@ -0,0 +1,104 @@ +/* + * 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 __DESTRUCTIBLE_PREVIEW_IMPL_H__ +#define __DESTRUCTIBLE_PREVIEW_IMPL_H__ + +#include "Apex.h" +#include "ApexPreview.h" +#include "RenderMesh.h" +#include "DestructiblePreview.h" + +namespace nvidia +{ +namespace destructible +{ +class DestructiblePreviewImpl : public ApexResource, public ApexPreview +{ +public: + + DestructibleAssetImpl* m_asset; + DestructiblePreview* m_api; + + uint32_t m_chunkDepth; + float m_explodeAmount; + + RenderMeshActor* m_renderMeshActors[DestructibleActorMeshType::Count]; // Indexed by DestructibleActorMeshType::Enum + + physx::Array<RenderMeshActor*> m_instancedChunkRenderMeshActors; // One per render mesh actor per instanced chunk + physx::Array<uint16_t> m_instancedActorVisiblePart; + + physx::Array<uint16_t> m_instancedChunkActorMap; // from instanced chunk instanceInfo index to actor index + + physx::Array<UserRenderInstanceBuffer*> m_chunkInstanceBuffers; + physx::Array< physx::Array< DestructibleAssetImpl::ChunkInstanceBufferDataElement > > m_chunkInstanceBufferData; + + bool m_drawUnexpandedChunksStatically; + + void* m_userData; + + void setExplodeView(uint32_t depth, float explode); + + void updateRenderResources(bool rewriteBuffers, void* userRenderData); + + RenderMeshActor* getRenderMeshActor() const + { + return m_renderMeshActors[(!m_drawUnexpandedChunksStatically || m_explodeAmount != 0.0f) ? DestructibleActorMeshType::Skinned : DestructibleActorMeshType::Static]; + } + + void updateRenderResources(void* userRenderData); + void dispatchRenderResources(UserRenderer& renderer); + + // ApexPreview methods + void setPose(const PxMat44& pose); + Renderable* getRenderable() + { + return DYNAMIC_CAST(Renderable*)(m_api); + } + void release(); + void destroy(); + + DestructiblePreviewImpl(DestructiblePreview* _api, DestructibleAssetImpl& _asset, const NvParameterized::Interface* params); + virtual ~DestructiblePreviewImpl(); + +protected: + void setChunkVisibility(uint16_t index, bool visibility) + { + PX_ASSERT((int32_t)index < m_asset->mParams->chunks.arraySizes[0]); + if (visibility) + { + mVisibleChunks.use(index); + } + else + { + mVisibleChunks.free(index); + } + DestructibleAssetParametersNS::Chunk_Type& sourceChunk = m_asset->mParams->chunks.buf[index]; + if ((sourceChunk.flags & DestructibleAssetImpl::Instanced) == 0) + { + // Not instanced - need to choose the static or dynamic mesh, and set visibility for the render mesh actor + const DestructibleActorMeshType::Enum typeN = (m_explodeAmount != 0.0f || !m_drawUnexpandedChunksStatically) ? + DestructibleActorMeshType::Skinned : DestructibleActorMeshType::Static; + m_renderMeshActors[typeN]->setVisibility(visibility, sourceChunk.meshPartIndex); + } + } + + + void setInstancedChunkCount(uint32_t count); + + IndexBank<uint16_t> mVisibleChunks; + uint16_t m_instancedChunkCount; +}; + +} +} // end namespace nvidia + +#endif // __DESTRUCTIBLEACTOR_H__ diff --git a/APEX_1.4/module/destructible/include/DestructiblePreviewProxy.h b/APEX_1.4/module/destructible/include/DestructiblePreviewProxy.h new file mode 100644 index 00000000..2a7429fb --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructiblePreviewProxy.h @@ -0,0 +1,123 @@ +/* + * 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 __DESTRUCTIBLEPREVIEW_PROXY_H__ +#define __DESTRUCTIBLEPREVIEW_PROXY_H__ + +#include "Apex.h" +#include "DestructiblePreview.h" +#include "DestructiblePreviewImpl.h" +#include "PsUserAllocated.h" +#include "ApexRWLockable.h" +#include "ReadCheck.h" +#include "WriteCheck.h" + +namespace nvidia +{ +namespace destructible +{ + +class DestructiblePreviewProxy : public DestructiblePreview, public ApexResourceInterface, public UserAllocated, public ApexRWLockable +{ +public: + APEX_RW_LOCKABLE_BOILERPLATE + + DestructiblePreviewImpl impl; + +#pragma warning(disable : 4355) // disable warning about this pointer in argument list + DestructiblePreviewProxy(DestructibleAssetImpl& asset, ResourceList& list, const NvParameterized::Interface* params) + : impl(this, asset, params) + { + list.add(*this); + } + + virtual ~DestructiblePreviewProxy() + { + } + + // AssetPreview methods + virtual void setPose(const PxMat44& pose) + { + WRITE_ZONE(); + impl.setPose(pose); + } + + virtual const PxMat44 getPose() const + { + READ_ZONE(); + return impl.getPose(); + } + + // DestructiblePreview methods + + virtual const RenderMeshActor* getRenderMeshActor() const + { + READ_ZONE(); + return const_cast<const RenderMeshActor*>(impl.getRenderMeshActor()); + } + + virtual void setExplodeView(uint32_t depth, float explode) + { + WRITE_ZONE(); + return impl.setExplodeView(depth, explode); + } + + // ApexInterface methods + virtual void release() + { + WRITE_ZONE(); + impl.release(); + delete this; + } + virtual void destroy() + { + impl.destroy(); + } + + // Renderable methods + virtual void updateRenderResources(bool rewriteBuffers, void* userRenderData) + { + URR_SCOPE; + impl.updateRenderResources(rewriteBuffers, userRenderData); + } + virtual void dispatchRenderResources(UserRenderer& api) + { + impl.dispatchRenderResources(api); + } + virtual PxBounds3 getBounds() const + { + return impl.getBounds(); + } + virtual void lockRenderResources() + { + impl.ApexRenderable::renderDataLock(); + } + virtual void unlockRenderResources() + { + impl.ApexRenderable::renderDataUnLock(); + } + + // ApexResourceInterface methods + virtual void setListIndex(ResourceList& list, uint32_t index) + { + impl.m_listIndex = index; + impl.m_list = &list; + } + virtual uint32_t getListIndex() const + { + return impl.m_listIndex; + } +}; + +} +} // end namespace nvidia + +#endif // __DESTRUCTIBLEPREVIEW_PROXY_H__ diff --git a/APEX_1.4/module/destructible/include/DestructibleRenderableImpl.h b/APEX_1.4/module/destructible/include/DestructibleRenderableImpl.h new file mode 100644 index 00000000..4ca7bf68 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleRenderableImpl.h @@ -0,0 +1,114 @@ +/* + * 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 __DESTRUCTIBLE_RENDERABLE_IMPL_H__ +#define __DESTRUCTIBLE_RENDERABLE_IMPL_H__ + +#include "Apex.h" +#include "DestructibleActor.h" +#include "DestructibleRenderable.h" +#include "ApexRWLockable.h" +#include "ApexActor.h" +#if APEX_RUNTIME_FRACTURE +#include "../fracture/Renderable.h" +#endif + +#include "ReadCheck.h" + +namespace nvidia +{ +namespace apex +{ +class RenderMeshActor; +} + +namespace destructible +{ + +class DestructibleActorImpl; + +class DestructibleRenderableImpl : public DestructibleRenderable, public ApexRenderable, public UserAllocated, public ApexRWLockable +{ +public: + APEX_RW_LOCKABLE_BOILERPLATE + + DestructibleRenderableImpl(RenderMeshActor* renderMeshActors[DestructibleActorMeshType::Count], DestructibleAssetImpl* asset, int32_t listIndex); + ~DestructibleRenderableImpl(); + + // Begin DestructibleRenderable methods + virtual RenderMeshActor* getRenderMeshActor(DestructibleActorMeshType::Enum type = DestructibleActorMeshType::Skinned) const + { + READ_ZONE(); + return (uint32_t)type < DestructibleActorMeshType::Count ? mRenderMeshActors[type] : NULL; + } + + virtual void release(); + // End DestructibleRenderable methods + + // Begin Renderable methods + virtual void updateRenderResources(bool rewriteBuffers, void* userRenderData); + + virtual void dispatchRenderResources(UserRenderer& api); + + virtual PxBounds3 getBounds() const + { + PxBounds3 bounds = ApexRenderable::getBounds(); +#if APEX_RUNTIME_FRACTURE + bounds.include(mRTrenderable.getBounds()); +#endif + return bounds; + } + + virtual void lockRenderResources() + { + ApexRenderable::renderDataLock(); + } + + virtual void unlockRenderResources() + { + ApexRenderable::renderDataUnLock(); + } + // End Renderable methods + + // Begin DestructibleRenderable methods + // Returns this if successful, NULL otherwise + DestructibleRenderableImpl* incrementReferenceCount(); + + int32_t getReferenceCount() + { + return mRefCount; + } + + void setBounds(const PxBounds3& bounds) + { + mRenderBounds = bounds; + } + // End DestructibleRenderable methods + +#if APEX_RUNTIME_FRACTURE + ::nvidia::fracture::Renderable& getRTrenderable() { return mRTrenderable; } +#endif + +private: + + RenderMeshActor* mRenderMeshActors[DestructibleActorMeshType::Count]; // Indexed by DestructibleActorMeshType::Enum + DestructibleAssetImpl* mAsset; + int32_t mListIndex; + volatile int32_t mRefCount; +#if APEX_RUNTIME_FRACTURE + ::nvidia::fracture::Renderable mRTrenderable; +#endif +}; + +} +} // end namespace nvidia + +#endif // __DESTRUCTIBLE_RENDERABLE_IMPL_H__ diff --git a/APEX_1.4/module/destructible/include/DestructibleScene.h b/APEX_1.4/module/destructible/include/DestructibleScene.h new file mode 100644 index 00000000..69eb83d2 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleScene.h @@ -0,0 +1,1249 @@ +/* + * 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 __DESTRUCTIBLE_SCENE_H__ +#define __DESTRUCTIBLE_SCENE_H__ + +#include "Apex.h" +#include "SceneIntl.h" +#include "ModuleIntl.h" +#include "DestructibleActorImpl.h" +#include "DestructibleAssetImpl.h" +#include "DestructibleStructure.h" +#include "ModuleDestructibleImpl.h" +#include "PsHashMap.h" +#include "PsHashSet.h" + +#include <PxSimulationEventCallback.h> +#include <PxContactModifyCallback.h> + +#include "DestructibleActorJoint.h" + +#include "RenderDebugInterface.h" + +#include "DebugRenderParams.h" +#include "DestructibleDebugRenderParams.h" + +#include "PsTime.h" +#include "PsMutex.h" +#include "ApexContext.h" + +#include "PxTaskManager.h" +#include "PxTask.h" + +#if APEX_RUNTIME_FRACTURE +#include "SimScene.h" +#endif + +#include "ModulePerfScope.h" + +// We currently have to copy into the contact buffer because the native contact +// stream is compressed within PhysX. If we need to optimize we could use a +// contact iterator like what's found in PxContactPair::extractContacts() +#define USE_EXTRACT_CONTACTS 1 +#define PAIR_POINT_ALLOCS 0 + +#ifndef PX_VERIFY +#ifndef NDEBUG +#define PX_VERIFY(f) PX_ASSERT(f) +#else // NDEBUG +#define PX_VERIFY(f) ((void)(f)) +#endif +#endif + +namespace nvidia +{ +namespace destructible +{ + +static const int32_t MAX_SHAPE_COUNT = 256; + +class ModuleDestructibleImpl; +class DestructibleScene; +class DestructibleActorProxy; +class DestructibleBeforeTick; + +struct IndexedReal +{ + float value; + uint32_t index; + + PX_INLINE bool operator > (IndexedReal& i) + { + return value > i.value; + } +}; + + +class DestructibleContactModify : public PxContactModifyCallback +{ +public: + DestructibleContactModify() : destructibleScene(NULL) {} + + void onContactModify(physx::PxContactModifyPair* const pairs, uint32_t count); + + DestructibleScene* destructibleScene; +}; + +class DestructibleUserNotify : public PxSimulationEventCallback +{ +public: + DestructibleUserNotify(ModuleDestructibleImpl& module, DestructibleScene* destructibleScene); + +private: + virtual void onConstraintBreak(physx::PxConstraintInfo* constraints, uint32_t count); + virtual void onWake(PxActor** actors, uint32_t count); + virtual void onSleep(PxActor** actors, uint32_t count); + virtual void onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, uint32_t nbPairs); + virtual void onTrigger(physx::PxTriggerPair* pairs, uint32_t count); + virtual void onAdvance(const PxRigidBody*const* bodyBuffer, const PxTransform* poseBuffer, const PxU32 count); + + void operator=(const DestructibleUserNotify&) {} + +private: + ModuleDestructibleImpl& mModule; + DestructibleScene* mDestructibleScene; +#if USE_EXTRACT_CONTACTS + physx::Array<uint8_t> mPairPointBuffer; +#endif +}; + + +class ApexDamageEventReportDataImpl : public DamageEventReportData +{ +public: + ApexDamageEventReportDataImpl() + { + clear(); + } + + ApexDamageEventReportDataImpl(const ApexDamageEventReportDataImpl& other) + { + *this = other; + } + + ApexDamageEventReportDataImpl& operator = (const ApexDamageEventReportDataImpl& other) + { + m_destructible = other.m_destructible; + m_fractureEvents = other.m_fractureEvents; + m_chunkReportBitMask = other.m_chunkReportBitMask; + m_chunkReportMaxFractureEventDepth = other.m_chunkReportMaxFractureEventDepth; + destructible = other.destructible; + hitDirection = other.hitDirection; + worldBounds = other.worldBounds; + totalNumberOfFractureEvents = other.totalNumberOfFractureEvents; + minDepth = other.minDepth; + maxDepth = other.maxDepth; + fractureEventList = m_fractureEvents.size() > 0 ? &m_fractureEvents[0] : NULL; + fractureEventListSize = m_fractureEvents.size(); + impactDamageActor = other.impactDamageActor; + appliedDamageUserData = other.appliedDamageUserData; + hitPosition = other.hitPosition; + return *this; + } + + void setDestructible(DestructibleActorImpl* inDestructible); + + uint32_t addFractureEvent(const DestructibleStructure::Chunk& chunk, uint32_t flags); + + ChunkData& getFractureEvent(uint32_t index) + { + return m_fractureEvents[index]; + } + + void clearChunkReports(); + +private: + void clear() + { + m_destructible = NULL; + m_fractureEvents.reset(); + m_chunkReportBitMask = 0xffffffff; + m_chunkReportMaxFractureEventDepth = 0xffffffff; + destructible = NULL; + hitDirection = PxVec3(0.0f); + worldBounds.setEmpty(); + totalNumberOfFractureEvents = 0; + minDepth = 0xffff; + maxDepth = 0; + fractureEventList = NULL; + fractureEventListSize = 0; + impactDamageActor = NULL; + appliedDamageUserData = NULL; + hitPosition = PxVec3(0.0f); + } + + DestructibleActorImpl* m_destructible; + physx::Array<ChunkData> m_fractureEvents; + uint32_t m_chunkReportBitMask; + uint32_t m_chunkReportMaxFractureEventDepth; +}; + +struct ActorFIFOEntry +{ + enum Flag + { + IsDebris = 1 << 0, + ForceLODRemove = 1 << 1, + + MassUpdateNeeded = 1 << 8, + }; + + ActorFIFOEntry() : actor(NULL), origin(0.0f), age(0.0f), benefitCache(PX_MAX_F32), maxSpeed(0.0f), averagedLinearVelocity(0.0f), averagedAngularVelocity(0.0f), unscaledMass(0.0f), flags(0) {} + ActorFIFOEntry(PxRigidDynamic* inActor, float inUnscaledMass, uint32_t inFlags) : actor(inActor), age(0.0f), benefitCache(PX_MAX_F32), maxSpeed(0.0f), + averagedLinearVelocity(0.0f), averagedAngularVelocity(0.0f), unscaledMass(inUnscaledMass), flags(inFlags) + { + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + origin = (actor->getGlobalPose() * actor->getCMassLocalPose()).p; + } + + PxRigidDynamic* actor; + PxVec3 origin; + float age; + float benefitCache; //for LOD + float maxSpeed; + PxVec3 averagedLinearVelocity; + PxVec3 averagedAngularVelocity; + float unscaledMass; + uint32_t flags; +}; + +struct DormantActorEntry +{ + DormantActorEntry() : actor(NULL), unscaledMass(0.0f), flags(0) {} + DormantActorEntry(PxRigidDynamic* inActor, float inUnscaledMass, uint32_t inFlags) : actor(inActor), unscaledMass(inUnscaledMass), flags(inFlags) {} + + PxRigidDynamic* actor; + float unscaledMass; + uint32_t flags; +}; + +struct ChunkBenefitCoefs +{ + ChunkBenefitCoefs() : perChunkInitialBenefit(1.0f), benefitDecayTimeConstant(1.0f), benefitPerPercentScreenArea(1.0f) {} + + float perChunkInitialBenefit; + float benefitDecayTimeConstant; + float benefitPerPercentScreenArea; +}; + +struct ChunkCostCoefs +{ + ChunkCostCoefs() : perChunkCost(1.0f) {} + + float perChunkCost; +}; + + +/* Class which manages DestructibleActors and DestructibleStructures + * associate with a single Scene + */ + +class DestructibleScene : public ModuleSceneIntl, public ApexContext, public ApexResourceInterface, public ApexResource +{ +public: + DestructibleScene(ModuleDestructibleImpl& module, SceneIntl& scene, RenderDebugInterface* debugRender, ResourceList& list); + ~DestructibleScene(); + + /* ModuleSceneIntl */ + virtual void submitTasks(float elapsedTime, float substepSize, uint32_t numSubSteps); + virtual void setTaskDependencies(); + virtual void tasked_beforeTick(float elapsedTime); + virtual void fetchResults(); + + virtual void setModulePhysXScene(PxScene* s); + virtual PxScene* getModulePhysXScene() const + { + return mPhysXScene; + } + virtual void release() + { + mModule->releaseModuleSceneIntl(*this); + } + virtual void visualize(); + + virtual Module* getModule() + { + return mModule; + } + + ModuleDestructibleImpl* getModuleDestructible() const + { + return mModule; + } + + SceneIntl* getApexScene() + { + return mApexScene; + } + + void initModuleSettings(); + +#if APEX_RUNTIME_FRACTURE + ::nvidia::fracture::SimScene* getDestructibleRTScene(bool create = true); +#endif + + enum StatsDataEnum + { + VisibleDestructibleChunkCount, + DynamicDestructibleChunkIslandCount, + NumberOfShapes, + NumberOfAwakeShapes, + RbThroughput, + + // insert new items before this line + NumberOfStats // The number of stats + }; + + virtual SceneStats* getStats(); + + /* ApexResourceInterface */ + uint32_t getListIndex() const + { + return m_listIndex; + } + void setListIndex(ResourceList& list, uint32_t index) + { + m_listIndex = index; + m_list = &list; + } + + /* DestructibleScene methods */ + + void applyRadiusDamage(float damage, float momentum, const PxVec3& position, float radius, bool falloff); + + bool isActorCreationRateExceeded(); + bool isFractureBufferProcessRateExceeded(); + + void addToAwakeList(DestructibleActorImpl& actor); + void removeFromAwakeList(DestructibleActorImpl& actor); + + enum + { + InvalidReportID = 0xFFFFFFFF + }; + +private: + + void addActorsToScene(); + physx::Array<physx::PxActor*> mActorsToAdd; + HashMap<physx::PxActor*, uint32_t> mActorsToAddIndexMap; + + void addForceToAddActorsMap(physx::PxActor* actor, const ActorForceAtPosition& force); + HashMap<physx::PxActor*, ActorForceAtPosition> mForcesToAddToActorsMap; + + ModuleDestructibleImpl* mModule; + SceneIntl* mApexScene; + PxScene* mPhysXScene; + DestructibleContactModify mContactModify; + + ResourceList mDestructibleActorJointList; + DestructibleBeforeTick* mBeforeTickTask; + + DestructibleUserNotify mUserNotify; + SceneStats mModuleSceneStats; + float mElapsedTime; + + physx::Array<DestructibleActorImpl*> mInstancedActors; + +#if APEX_RUNTIME_FRACTURE + ::nvidia::fracture::SimScene* mRTScene; +#endif + + // These values are set per-scene by the destruction module + float mMassScale; + float mMassScaleInv; + float mScaledMassExponent; + float mScaledMassExponentInv; + + int mPreviousVisibleDestructibleChunkCount; // Must keep previous value because of our goofy cumulative-only stats system + int mPreviousDynamicDestructibleChunkIslandCount; // Must keep previous value because of our goofy cumulative-only stats system + +public: + void destroy(); + void reset(); + DestructibleActorJoint* createDestructibleActorJoint(const DestructibleActorJointDesc& destructibleActorJointDesc); + DestructibleActor* getDestructibleAndChunk(const PxShape* shape, int32_t* chunkIndex) const; + + bool insertDestructibleActor(DestructibleActor* destructible); + + bool removeStructure(DestructibleStructure* structure, bool immediate = true); + void addActor(PhysXObjectDescIntl& desc, PxRigidDynamic& actor, float unscaledMass, bool isDebris); + bool destroyActorChunks(PxRigidDynamic& actor, uint32_t chunkFlag); + void capDynamicActorCount(); + void removeReferencesToActor(DestructibleActorImpl& actor); + + void addInstancedActor(DestructibleActorImpl* actor) + { + mInstancedActors.pushBack(actor); + } + + void releasePhysXActor(PxRigidDynamic& actor); + + void resetEmitterActors(); + + PxRigidDynamic* createRoot(DestructibleStructure::Chunk& chunk, const PxTransform& pose, bool dynamic, PxTransform* relTM = NULL, bool fromInitialData = false); + bool appendShapes(DestructibleStructure::Chunk& chunk, bool dynamic, PxTransform* relTM = NULL, PxRigidDynamic* actor = NULL); + + void setWorldSupportPhysXScene(PxScene* physxScene) + { + m_worldSupportPhysXScene = physxScene; + } + + bool testWorldOverlap(const ConvexHullImpl& convexHull, const PxTransform& tm, const PxVec3& scale, float padding, const physx::PxFilterData* groupsMask = NULL); + + DestructibleStructure* getChunkStructure(DestructibleStructure::Chunk& chunk) const + { + return mDestructibles.direct(chunk.destructibleID)->getStructure(); + } + + DestructibleStructure::Chunk* getChunk(const PxShape* shape) const + { + // TODO: this fires all the time with PhysX3 + //PX_ASSERT(mModule->owns((PxActor*)&shape->getActor())); + const PxRigidActor* actor = shape->getActor(); + + if (!mModule->owns(actor)) + { + return NULL; + } + + const PhysXObjectDesc* shapeDesc = mModule->mSdk->getPhysXObjectInfo(shape); + if (shapeDesc == NULL) + { + return NULL; + } + + return (DestructibleStructure::Chunk*)shapeDesc->userData; + } + + const DestructibleActorImpl* getChunkActor(const DestructibleStructure::Chunk& chunk) const + { + return mDestructibles.direct(chunk.destructibleID); + } + + PX_INLINE void createChunkReportDataForFractureEvent(const FractureEvent& fractureEvent, DestructibleActorImpl* destructible, DestructibleStructure::Chunk& chunk) + { + PX_UNUSED(fractureEvent); // Keeping this parameter assuming we'll merge in a later change which requires fractureEvent + PX_ASSERT(destructible != NULL && destructible->mDamageEventReportIndex < mDamageEventReportData.size()); + if (destructible != NULL && destructible->mDamageEventReportIndex < mDamageEventReportData.size()) + { + ApexDamageEventReportDataImpl& damageReportData = mDamageEventReportData[destructible->mDamageEventReportIndex]; + const uint32_t fractureEventIndex = damageReportData.addFractureEvent(chunk, ApexChunkFlag::FRACTURED); + mFractureEventCount++; + chunk.reportID = mChunkReportHandles.size(); + IntPair& handle = mChunkReportHandles.insert(); + handle.set((int32_t)destructible->mDamageEventReportIndex, (int32_t)fractureEventIndex); + } + } + + PX_INLINE ChunkData* getChunkReportData(DestructibleStructure::Chunk& chunk, uint32_t flags); + + PX_INLINE PxRigidDynamic* chunkIntact(DestructibleStructure::Chunk& chunk); + + bool scheduleChunkShapesForDelete(DestructibleStructure::Chunk& chunk); + bool schedulePxActorForDelete(PhysXObjectDescIntl& actorDesc); + + PX_INLINE void calculatePotentialCostAndBenefit(float& cost, float& benefit, physx::Array<uint8_t*>& trail, physx::Array<uint8_t>& undo, const FractureEvent& fractureEvent) const; + + template <class ChunkOpClass> + void forSubtree(DestructibleStructure::Chunk& chunk, ChunkOpClass chunkOp, bool skipRoot = false); + + bool setMassScaling(float massScale, float scaledMassExponent); + + void invalidateBounds(const PxBounds3* bounds, uint32_t boundsCount); + + void setDamageApplicationRaycastFlags(nvidia::DestructibleActorRaycastFlags::Enum flags); + + nvidia::DestructibleActorRaycastFlags::Enum getDamageApplicationRaycastFlags() const { return (nvidia::DestructibleActorRaycastFlags::Enum)m_damageApplicationRaycastFlags; } + + PX_INLINE float scaleMass(float mass) + { + if (PxAbs(mScaledMassExponent - 0.5f) < 1e-7) + { + return mMassScale * PxSqrt(mass * mMassScaleInv); + } + return mMassScale * PxPow(mass * mMassScaleInv, mScaledMassExponent); + } + + PX_INLINE float unscaleMass(float scaledMass) + { + if (PxAbs(mScaledMassExponentInv - 2.f) < 1e-7) + { + float tmp = scaledMass * mMassScaleInv; + return mMassScale * tmp * tmp; + } + return mMassScale * PxPow(scaledMass * mMassScaleInv, mScaledMassExponentInv); + } + + void updateActorPose(DestructibleActorImpl* actor, UserChunkMotionHandler* callback) + { + const bool processChunkPoseForSyncing = ((NULL != callback) && ( actor->getSyncParams().isSyncFlagSet(DestructibleActorSyncFlags::CopyChunkTransform) || + actor->getSyncParams().isSyncFlagSet(DestructibleActorSyncFlags::ReadChunkTransform))); + actor->setRenderTMs(processChunkPoseForSyncing); + } + + bool setRenderLockMode(RenderLockMode::Enum renderLockMode) + { + if ((int)renderLockMode < 0 || (int)renderLockMode > RenderLockMode::PER_MODULE_SCENE_RENDER_LOCK) + { + return false; + } + + mRenderLockMode = renderLockMode; + + return true; + } + + RenderLockMode::Enum getRenderLockMode() const + { + return mRenderLockMode; + } + + bool lockModuleSceneRenderLock() + { + return mRenderDataLock.lock(); + } + + bool unlockModuleSceneRenderLock() + { + return mRenderDataLock.unlock(); + } + + bool lockRenderResources() + { + switch (getRenderLockMode()) + { + case RenderLockMode::PER_ACTOR_RENDER_LOCK: + renderLockAllActors(); + return true; + case RenderLockMode::PER_MODULE_SCENE_RENDER_LOCK: + return lockModuleSceneRenderLock(); + case RenderLockMode::NO_RENDER_LOCK: + break; + } + return true; + } + + bool unlockRenderResources() + { + switch (getRenderLockMode()) + { + case RenderLockMode::PER_ACTOR_RENDER_LOCK: + renderUnLockAllActors(); + return true; + case RenderLockMode::PER_MODULE_SCENE_RENDER_LOCK: + return unlockModuleSceneRenderLock(); + case RenderLockMode::NO_RENDER_LOCK: + break; + } + return true; + } + + physx::Array<ApexDamageEventReportDataImpl> mDamageEventReportData; + physx::Array<IntPair> mChunkReportHandles; // i0 = m_damageEventReportData index, i1 = ApexDamageEventReportDataImpl::m_fractureEvents + + physx::Array<ImpactDamageEventData> mImpactDamageEventData; // Impact damage notify + + physx::Array<DestructibleActorImpl*> mActorsWithChunkStateEvents; // Filled when module->m_chunkStateEventCallbackSchedule is not DestructibleCallbackSchedule::Disabled + + void setStructureSupportRebuild(DestructibleStructure* structure, bool rebuild); + void setStructureUpdate(DestructibleStructure* structure, bool update); + void setStressSolverTick(DestructibleStructure* structure, bool update); + + // FIFO + physx::Array<ActorFIFOEntry> mActorFIFO; + physx::Array<IndexedReal> mActorBenefitSortArray; + uint32_t mDynamicActorFIFONum; // Tracks the valid entries in actorFIFO; + uint32_t mTotalChunkCount; // Tracks the chunks; + + uint32_t mNumFracturesProcessedThisFrame; + uint32_t mNumActorsCreatedThisFrame; + + uint32_t mFractureEventCount; + + // DestructibleActors with scene-global IDs + Bank<DestructibleActorImpl*, uint32_t> mDestructibles; + + // Structure container + Bank<DestructibleStructure*, uint32_t> mStructures; + physx::Array<DestructibleStructure*> mStructureKillList; + Bank<DestructibleStructure*, uint32_t> mStructureUpdateList; + Bank<DestructibleStructure*, uint32_t> mStructureSupportRebuildList; + Bank<DestructibleStructure*, uint32_t> mStressSolverTickList; + + // For delayed release of PxRigidDynamics + physx::Array<PxRigidDynamic*> mActorKillList; + ResourceList mApexActorKillList; + + // Damage queue + RingBuffer<DamageEvent> mDamageBuffer[2]; // Double-buffering + uint32_t mDamageBufferWriteIndex; + + // Fracture queue + RingBuffer<FractureEvent> mFractureBuffer; + + // Destroy queue + physx::Array<IntPair> mChunkKillList; + + // Destructibles on death row + physx::Array<DestructibleActor*> destructibleActorKillList; + + // Bank of dormant (kinematic dynamic) actors + Bank<DormantActorEntry, uint32_t> mDormantActors; + + // list of awake destructible actor IDs (mDestructibles bank) + IndexBank<uint32_t> mAwakeActors; + bool mUsingActiveTransforms; + + // Wake/sleep event actors + physx::Array<DestructibleActor*> mOnWakeActors; + physx::Array<DestructibleActor*> mOnSleepActors; + + physx::Array<physx::PxClientID> mSceneClientIDs; + + // Scene to use for world support calculations if NULL, mPhysXScene is used + physx::PxScene* m_worldSupportPhysXScene; + + physx::Array<PxBounds3> m_invalidBounds; + + uint32_t m_damageApplicationRaycastFlags; + + RenderDebugInterface* mDebugRender; //debug renderer created and owned by the owning ApexScene and passed down. Not owned. + + DebugRenderParams* mDebugRenderParams; + DestructibleDebugRenderParams* mDestructibleDebugRenderParams; + + physx::Array<physx::PxOverlapHit> mOverlapHits; + + RenderLockMode::Enum mRenderLockMode; + + AtomicLock mRenderDataLock; + + // Access to the double-buffered damage events + RingBuffer<DamageEvent>& getDamageWriteBuffer() + { + return mDamageBuffer[mDamageBufferWriteIndex]; + } + RingBuffer<DamageEvent>& getDamageReadBuffer() + { + return mDamageBuffer[mDamageBufferWriteIndex^1]; + } + void swapDamageBuffers() + { + mDamageBufferWriteIndex ^= 1; + } + + class CollectVisibleChunks + { + physx::Array<DestructibleStructure::Chunk*>& chunkArray; + + public: + + CollectVisibleChunks(physx::Array<DestructibleStructure::Chunk*>& inChunkArray) : + chunkArray(inChunkArray) {} + + bool execute(DestructibleStructure* structure, DestructibleStructure::Chunk& chunk) + { + PX_UNUSED(structure); + if ((chunk.state & ChunkVisible) != 0) + { + chunkArray.pushBack(&chunk); + return false; + } + return true; + } + private: + CollectVisibleChunks& operator=(const CollectVisibleChunks&); + }; + + class VisibleChunkSetDescendents + { + uint32_t visibleChunkIndex; + uint8_t raiseStateFlags; + + public: + VisibleChunkSetDescendents(uint32_t chunkIndex, bool makeDynamic) + : visibleChunkIndex(chunkIndex) + , raiseStateFlags(makeDynamic ? (uint8_t)ChunkDynamic : (uint8_t)0) + { + } + bool execute(DestructibleStructure* structure, DestructibleStructure::Chunk& chunk) + { + PX_UNUSED(structure); + chunk.clearShapes(); + chunk.state |= raiseStateFlags; // setting dynamic flag, but these chunks are descendents of a visible chunk and therefore invisible. No need to update visible dynamic chunk shape counts + chunk.visibleAncestorIndex = (int32_t)visibleChunkIndex; + return true; + } + }; + + class ChunkClearDescendents + { + int32_t rootChunkIndex; + + public: + ChunkClearDescendents(int32_t chunkIndex) : rootChunkIndex(chunkIndex) {} + + bool execute(DestructibleStructure* structure, DestructibleStructure::Chunk& chunk) + { + PX_UNUSED(structure); + if (chunk.visibleAncestorIndex == rootChunkIndex) + { + chunk.clearShapes(); + chunk.visibleAncestorIndex = DestructibleStructure::InvalidChunkIndex; + } + return true; + } + }; + + class ChunkLoadState + { + public: + ChunkLoadState(DestructibleScene& scene) : mScene(scene) { } + bool execute(DestructibleStructure* structure, DestructibleStructure::Chunk& chunk); + private: + ChunkLoadState& operator=(const ChunkLoadState&); + DestructibleScene& mScene; + }; + +private: + void createModuleStats(); + void destroyModuleStats(); + void setStatValue(int32_t index, StatValue dataVal); + static PX_INLINE float ticksToMilliseconds(uint64_t t0, uint64_t t1) + { + // this is a copy of ApexScene::tickToMilliseconds. Unfortunately can't easily use the other + static const CounterFrequencyToTensOfNanos freq = nvidia::Time::getBootCounterFrequency(); + static const double freqMultiplier = (double)freq.mNumerator/(double)freq.mDenominator * 0.00001; // convert from 10nanoseconds to milliseconds + + float ret = (float)((double)(t1 - t0) * freqMultiplier); + return ret; + } + + friend class DestructibleActorImpl; + friend class DestructibleActorProxy; + friend class DestructibleActorJointImpl; + friend class DestructibleStructure; + friend class DestructibleContactReport; + friend class DestructibleContactModify; + friend class OverlapSphereShapesReport; + friend class ModuleDestructibleImpl; + friend class ApexDamageEventReportDataImpl; + friend class DestructibleUserNotify; + + /* + <--- Destructible Sync-ables Memory Layout ---> + + all actor data => buffer (consists of) + per actor data => segment (consists of) + 1) header + 1.1) userActorID + 1.2) _X_unit count, pointer to _X_buffer start + 1.3) _Y_unit count, pointer to _Y_buffer start + 1.4) pointer to next header. NULL if last + 2) _X_buffer + 2.1) made up of '_X_count' of '_X_unit' + 3) _Y_buffer (if used) + 3.1) made up of '_Y_count' of '_Y_unit' + + |-------------|----------|---------------|----------|---------------|------|-----------|-----------|----------------- + | userActorID | _X_count | _X_buffer_ptr | _Y_count | _Y_buffer_ptr | next | _X_buffer | _Y_buffer | userActorID ... + |-------------|----------|---------------|----------|---------------|------|-----------|-----------|----------------- + + <------------------------------------------------------ buffer ------------------------------------------------------... + <-------------------------------------------- segment --------------------------------------------> + <--------------------------------- header ---------------------------------> + <-----------> uniform buffer + <-----------> uniform buffer + + + <--- Destructible Sync-ables Function Call Flow ---> + + 1) write + onProcessWriteData() + loadDataForWrite() + interceptLoad() + processWriteBuffer() + getBufferSizeRequired() + getSegmentSizeRequired() + callback.onWriteBegin() + writeUserBuffer() + writeUserSegment() + writeUserUniformBuffer() + interpret() + interceptEdit() + callback.onWriteDone() + unloadDataForWrite() + + ___buffer full___ + a) after generateFractureProfilesInDamageBuffer() + before fillFractureBufferFromDamage() + b) before processFractureBuffer() + c) after fetchResults() + actor->setRenderTMs() + + 2) read + onPreProcessReadData() + processReadBuffer() + callback.onPreProcessReadBegin() + writeUserBufferPointers() + callback.onPreProcessReadDone() + callback.onReadBegin() + loadDataForRead() + + ___begin read___ + a) generateFractureProfilesInDamageBuffer() + interpret() + interceptEdit() + fillFractureBufferFromDamage() + b) processFractureBuffer() + interpret() + interceptEdit() + c) fetchResults() + actor->setRenderTMs() + ___end read___ + + onPostProcessReadData() + unloadDataForRead() + callback.onReadDone() + */ + + /*** DestructibleScene::SyncParams ***/ +public: + class SyncParams + { + public: + struct UserDamageEvent; + struct UserFractureEvent; + explicit SyncParams(const ModuleDestructibleImpl::SyncParams & moduleParams); + ~SyncParams(); + public: + bool setSyncActor(uint32_t entryIndex, DestructibleActorImpl * entry, DestructibleActorImpl *& erasedEntry); + private: + DestructibleActorImpl * getSyncActor(uint32_t entryIndex) const; + uint32_t getUserActorID(uint32_t destructibleID) const; + + public: //read and write - public APIs + void onPreProcessReadData(UserDamageEventHandler & callback, const physx::Array<UserDamageEvent> *& userSource); + void onPreProcessReadData(UserFractureEventHandler & callback, const physx::Array<UserFractureEvent> *& userSource); + void onPreProcessReadData(UserChunkMotionHandler & callback); + + DamageEvent & interpret(const UserDamageEvent & userDamageEvent); + FractureEvent & interpret(const UserFractureEvent & userFractureEvent); + void interceptEdit(DamageEvent & damageEvent, const DestructibleActorImpl::SyncParams & actorParams) const; + void interceptEdit(FractureEvent & fractureEvent, const DestructibleActorImpl::SyncParams & actorParams) const; + + void onPostProcessReadData(UserDamageEventHandler & callback); + void onPostProcessReadData(UserFractureEventHandler & callback); + void onPostProcessReadData(UserChunkMotionHandler & callback); + + void onProcessWriteData(UserDamageEventHandler & callback, const RingBuffer<DamageEvent> & localSource); + void onProcessWriteData(UserFractureEventHandler & callback, const RingBuffer<FractureEvent> & localSource); + void onProcessWriteData(UserChunkMotionHandler & callback); + + private: //read - helper functions + void loadDataForRead(const DamageEventHeader * bufferStart, const physx::Array<UserDamageEvent> *& userSource); + void loadDataForRead(const FractureEventHeader * bufferStart, const physx::Array<UserFractureEvent> *& userSource); + void loadDataForRead(const ChunkTransformHeader * bufferStart); + + bool unloadDataForRead(const UserDamageEventHandler & dummy); + bool unloadDataForRead(const UserFractureEventHandler & dummy); + bool unloadDataForRead(const UserChunkMotionHandler & dummy); + + template<typename Callback, typename Header, typename Unit> const Header * processReadBuffer(Callback & callback) const; + template<typename Header, typename Unit> int32_t writeUserBufferPointers(Header * bufferStart, uint32_t bufferSize) const; + template<typename Callback> void postProcessReadData(Callback & callback); + + private: //write - helper functions + uint32_t loadDataForWrite(const RingBuffer<DamageEvent> & localSource); + uint32_t loadDataForWrite(const RingBuffer<FractureEvent> & localSource); + uint32_t loadDataForWrite(const UserChunkMotionHandler & dummy); + + void unloadDataForWrite(const UserDamageEventHandler & dummy); + void unloadDataForWrite(const UserFractureEventHandler & dummy); + void unloadDataForWrite(const UserChunkMotionHandler & dummy); + + template<typename Callback, typename Header, typename Unit> uint32_t processWriteBuffer(Callback & callback); + template<typename Header, typename Unit> uint32_t getBufferSizeRequired() const; + template<typename Header, typename Unit> uint32_t getSegmentSizeRequired(const DestructibleActorImpl::SyncParams & actorParams) const; + template<typename Header, typename Unit> uint32_t writeUserBuffer(Header * bufferStart, uint32_t & headerCount); + template<typename Header, typename Unit> uint32_t writeUserSegment(Header * header, bool isLast, const DestructibleActorImpl::SyncParams & actorParams); + template<typename Unit> uint32_t writeUserUniformBuffer(Unit * bufferStart, const DestructibleActorImpl::SyncParams & actorParams); + + bool interceptLoad(const DamageEvent & damageEvent, const DestructibleActorImpl & syncActor) const; + bool interceptLoad(const FractureEvent & fractureEvent, const DestructibleActorImpl & syncActor) const; + DamageEventUnit * interpret(const DamageEvent & damageEvent); + FractureEventUnit * interpret(const FractureEvent & fractureEvent); + void interceptEdit(DamageEventUnit & nxApexDamageEventUnit, const DestructibleActorImpl::SyncParams & actorParams) const; + void interceptEdit(FractureEventUnit & nxApexFractureEventUnit, const DestructibleActorImpl::SyncParams & actorParams) const; + + private: //read and write - template helper functions + template<typename Item> uint32_t getUniformBufferCount(const DamageEventHeader & header) const; + template<typename Item> uint32_t getUniformBufferCount(const FractureEventHeader & header) const; + template<typename Item> uint32_t getUniformBufferCount(const ChunkTransformHeader & header) const; + + template<typename Item> uint32_t & getUniformBufferCountMutable(DamageEventHeader & header) const; + template<typename Item> uint32_t & getUniformBufferCountMutable(FractureEventHeader & header) const; + template<typename Item> uint32_t & getUniformBufferCountMutable(ChunkTransformHeader & header) const; + + template<typename Item> Item * getUniformBufferStart(const DamageEventHeader & header) const; + template<typename Item> Item * getUniformBufferStart(const FractureEventHeader & header) const; + template<typename Item> Item * getUniformBufferStart(const ChunkTransformHeader & header) const; + + template<typename Item> Item *& getUniformBufferStartMutable(DamageEventHeader & header) const; + template<typename Item> Item *& getUniformBufferStartMutable(FractureEventHeader & header) const; + template<typename Item> Item *& getUniformBufferStartMutable(ChunkTransformHeader & header) const; + +#if 1 + public: + bool ditchStaleBuffers; + bool lockSyncParams; +#endif // lionel: TODO...if necessary + + private: + SyncParams(); + DECLARE_DISABLE_COPY_AND_ASSIGN(SyncParams); + const ModuleDestructibleImpl::SyncParams & moduleParams; + mutable physx::Array<uint32_t> segmentSizeChecker; + const RingBuffer<DamageEvent> * damageEventWriteSource; + DamageEventUnit damageEventUserInstance; + physx::Array<UserDamageEvent> damageEventReadSource; + DamageEvent damageEventImplInstance; + const RingBuffer<FractureEvent> * fractureEventWriteSource; + FractureEventUnit fractureEventUserInstance; + physx::Array<UserFractureEvent> fractureEventReadSource; + FractureEvent fractureEventImplInstance; + physx::Array<DestructibleStructure::Chunk*> chunksWithUserControlledChunk; + + class SyncActorRecord + { + friend bool DestructibleScene::SyncParams::setSyncActor(uint32_t, DestructibleActorImpl *, DestructibleActorImpl *&); + public: + SyncActorRecord(); + ~SyncActorRecord(); + const physx::Array<uint32_t> & getIndexContainer() const; + const physx::Array<DestructibleActorImpl*> & getActorContainer() const; + private: + DECLARE_DISABLE_COPY_AND_ASSIGN(SyncActorRecord); + void onRebuild(const uint32_t & newCount); + physx::Array<uint32_t> indexContainer; + physx::Array<DestructibleActorImpl*> actorContainer; + private: + bool assertActorContainerOk() const; + } syncActorRecord; + + struct ActorEventPair + { + public: + const DestructibleActorImpl * actorAlias; + protected: + union + { + public: + const DamageEventUnit * userDamageEvent; + const FractureEventUnit * userFractureEvent; + }; + ActorEventPair(const DestructibleActorImpl * actorAlias, const DamageEventUnit * userDamageEvent); + ActorEventPair(const DestructibleActorImpl * actorAlias, const FractureEventUnit * userFractureEvent); + ~ActorEventPair(); + private: + ActorEventPair(); + }; + + public: + struct UserDamageEvent : public ActorEventPair + { + public: + UserDamageEvent(const DestructibleActorImpl * actorAlias, const DamageEventUnit * userDamageEvent); + ~UserDamageEvent(); + const DamageEventUnit * get() const; + private: + UserDamageEvent(); + }; + + struct UserFractureEvent : public ActorEventPair + { + public: + UserFractureEvent(const DestructibleActorImpl * actorAlias, const FractureEventUnit * userFractureEvent); + ~UserFractureEvent(); + const FractureEventUnit * get() const; + private: + UserFractureEvent(); + }; + + public: + bool assertUserDamageEventOk(const DamageEvent & damageEvent, const DestructibleScene & scene) const; + bool assertUserFractureEventOk(const FractureEvent & fractureEvent, const DestructibleScene & scene) const; + private: + bool assertCachedChunkContainerOk(const DestructibleActorImpl::SyncParams & actorParams) const; + bool assertControlledChunkContainerOk() const; + private: + static const char * errorMissingUserActorID; + static const char * errorMissingFlagReadDamageEvents; + static const char * errorMissingFlagReadFractureEvents; + static const char * errorMissingFlagReadChunkMotion; + static const char * errorOutOfBoundsActorChunkIndex; + static const char * errorOutOfBoundsStructureChunkIndex; + static const char * errorOverrunBuffer; + }; + + const DestructibleScene::SyncParams & getSyncParams() const; + DestructibleScene::SyncParams & getSyncParamsMutable(); +private: + SyncParams mSyncParams; + + //these methods participate in the sync process +private: + void processEventBuffers(); + void generateFractureProfilesInDamageBuffer(nvidia::RingBuffer<DamageEvent> & userDamageBuffer, const physx::Array<SyncParams::UserDamageEvent> * userSource = NULL); + void calculateDamageBufferCostProfiles(nvidia::RingBuffer<DamageEvent> & subjectDamageBuffer); + void fillFractureBufferFromDamage(nvidia::RingBuffer<DamageEvent> * userDamageBuffer = NULL); + void processFractureBuffer(); + void processFractureBuffer(const physx::Array<SyncParams::UserFractureEvent> * userSource); + void processDamageColoringBuffer(); + +private: + RingBuffer<FractureEvent> mDeprioritisedFractureBuffer; + RingBuffer<FractureEvent> mDeferredFractureBuffer; + RingBuffer<SyncDamageEventCoreDataParams> mSyncDamageEventCoreDataBuffer; +}; + +template <class ChunkOpClass> +PX_INLINE void DestructibleScene::forSubtree(DestructibleStructure::Chunk& chunk, ChunkOpClass chunkOp, bool skipRoot) +{ + uint16_t indexInAsset = chunk.indexInAsset; + DestructibleStructure::Chunk* pProcessChunk = &chunk; + physx::Array<uint16_t> stack; + + DestructibleActorImpl* destructible = mDestructibles.direct(chunk.destructibleID); + const DestructibleAssetParametersNS::Chunk_Type* sourceChunks = destructible->getDestructibleAsset()->mParams->chunks.buf; + const uint32_t firstChunkIndex = destructible->getFirstChunkIndex(); + + for (;;) + { + bool recurse = skipRoot ? true : chunkOp.execute(destructible->getStructure(), *pProcessChunk); + skipRoot = false; + const DestructibleAssetParametersNS::Chunk_Type& source = sourceChunks[indexInAsset]; + if (recurse && source.numChildren) + { + for (indexInAsset = uint16_t(source.firstChildIndex + source.numChildren); --indexInAsset > source.firstChildIndex;) + { + stack.pushBack(indexInAsset); + } + } + else + { + if (stack.size() == 0) + { + return; + } + indexInAsset = stack.back(); + stack.popBack(); + } + pProcessChunk = destructible->getStructure()->chunks.begin() + (firstChunkIndex + indexInAsset); + } +} + +PX_INLINE ChunkData* DestructibleScene::getChunkReportData(DestructibleStructure::Chunk& chunk, uint32_t flags) +{ + if (!mModule->m_chunkReport) + { + return NULL; // don't give out data if we won't be reporting it + } + + if (chunk.reportID == InvalidReportID) + { + // No chunk report data. Create. + const uint32_t damageEventIndex = mDamageEventReportData.size(); + ApexDamageEventReportDataImpl& damageReportData = mDamageEventReportData.insert(); + damageReportData.setDestructible(mDestructibles.direct(chunk.destructibleID)); + const uint32_t fractureEventIndex = damageReportData.addFractureEvent(chunk, flags); + chunk.reportID = mChunkReportHandles.size(); + IntPair& handle = mChunkReportHandles.insert(); + handle.set((int32_t)damageEventIndex, (int32_t)fractureEventIndex); + } + + PX_ASSERT(chunk.reportID < mChunkReportHandles.size()); + if (chunk.reportID < mChunkReportHandles.size()) + { + IntPair& handle = mChunkReportHandles[chunk.reportID]; + PX_ASSERT((uint32_t)handle.i0 < mDamageEventReportData.size()); + if ((uint32_t)handle.i0 < mDamageEventReportData.size() && (uint32_t)handle.i1 != 0xFFFFFFFF) + { + return &mDamageEventReportData[(uint32_t)handle.i0].getFractureEvent((uint32_t)handle.i1); + } + } + + return NULL; +} + +PX_INLINE PxRigidDynamic* DestructibleScene::chunkIntact(DestructibleStructure::Chunk& chunk) +{ + DestructibleStructure::Chunk* child = &chunk; + DestructibleActorImpl* destructible = mDestructibles.direct(chunk.destructibleID); + + if (!chunk.isDestroyed()) + { + return destructible->getStructure()->getChunkActor(chunk); + } + + if ((chunk.flags & ChunkMissingChild) != 0) + { + return NULL; + } + + DestructibleAssetImpl* asset = destructible->getDestructibleAsset(); + do + { + DestructibleAssetParametersNS::Chunk_Type& source = asset->mParams->chunks.buf[child->indexInAsset]; + PX_ASSERT(source.numChildren > 0); + child = &destructible->getStructure()->chunks[destructible->getFirstChunkIndex() + source.firstChildIndex]; + + if (!child->isDestroyed()) + { + return destructible->getStructure()->getChunkActor(chunk); + } + } + while ((child->flags & ChunkMissingChild) == 0); + + return NULL; +} + +PX_INLINE void cacheChunkTempState(DestructibleStructure::Chunk& chunk, physx::Array<uint8_t*>& trail, physx::Array<uint8_t>& undo) +{ + // ChunkTemp0 = chunk state has been cached + // ChunkTemp1 = chunk exists + // ChunkTemp2 = chunk is visible + // ChunkTemp3 = chunk is dynamic + + undo.pushBack((uint8_t)(chunk.state & (uint8_t)ChunkTempMask)); + + if ((chunk.state & ChunkTemp0) == 0) + { + chunk.state |= ChunkTemp0; + if (!chunk.isDestroyed()) + { + chunk.state |= ChunkTemp1; + if (chunk.state & ChunkVisible) + { + chunk.state |= ChunkTemp2; + } + if (chunk.state & ChunkDynamic) + { + chunk.state |= ChunkTemp3; + } + } + trail.pushBack(&chunk.state); + } +} + +PX_INLINE void DestructibleScene::calculatePotentialCostAndBenefit(float& cost, float& benefit, physx::Array<uint8_t*>& trail, physx::Array<uint8_t>& undo, const FractureEvent& fractureEvent) const +{ + cost = 0.0f; + benefit = 0.0f; + + DestructibleActorImpl* destructible = mDestructibles.direct(fractureEvent.destructibleID); + if (destructible == NULL) + { + return; + } + + DestructibleStructure* structure = destructible->getStructure(); + if (structure == NULL) + { + return; + } + + DestructibleStructure::Chunk* chunk = structure->chunks.begin() + fractureEvent.chunkIndexInAsset + destructible->getFirstChunkIndex(); + + // ChunkTemp0 = chunk state has been cached + // ChunkTemp1 = chunk exists + // ChunkTemp2 = chunk is visible + // ChunkTemp3 = chunk is dynamic + + cacheChunkTempState(*chunk, trail, undo); + + if ((chunk->state & ChunkTemp1) == 0) + { + return; + } + + if ((chunk->state & ChunkTemp3) != 0) // If the chunk is dynamic, we're done... no extra cost or benefit, and it's disconnected from its parent + { + return; + } + + const uint32_t chunkIndexInAsset = fractureEvent.chunkIndexInAsset; + const uint32_t chunkShapeCount = destructible->getDestructibleAsset()->getChunkHullCount(chunkIndexInAsset); + + cost += chunkShapeCount; + benefit += destructible->getBenefit()*(float)chunkShapeCount/(float)PxMax<uint32_t>(destructible->getVisibleDynamicChunkShapeCount(), 1); + + chunk->state |= ChunkTemp3; // Mark it as dynamic + + if ((chunk->state & ChunkTemp2) != 0) + { + return; // It was visible already, so we just made it dynamic. It will have no parent and iits siblings will already be accounted for, if they exist. + } + + chunk->state |= ChunkTemp2; // Mark it as visible + + for (;;) + { + // Climb the hierarchy + DestructibleAssetParametersNS::Chunk_Type& source = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk->indexInAsset]; + if (source.parentIndex == DestructibleAssetImpl::InvalidChunkIndex) + { + break; + } + chunk = structure->chunks.begin() + (source.parentIndex + destructible->getFirstChunkIndex()); + cacheChunkTempState(*chunk, trail, undo); + if ((chunk->state & ChunkTemp1) == 0) + { + break; // Parent doesn't exist + } + + // Make children visible + DestructibleAssetParametersNS::Chunk_Type& parentSource = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk->indexInAsset]; + const uint32_t firstChildIndex = parentSource.firstChildIndex + destructible->getFirstChunkIndex(); + const uint32_t endChildIndex = firstChildIndex + parentSource.numChildren; + for (uint32_t childIndex = firstChildIndex; childIndex < endChildIndex; ++childIndex) + { + DestructibleStructure::Chunk& child = structure->chunks[childIndex]; + cacheChunkTempState(child, trail, undo); + if ((child.state & ChunkTemp1) == 0) + { + continue; // Child doesn't exist, skip + } + child.state |= ChunkTemp2; // Make it visible + if ((chunk->state & ChunkTemp3) != 0 || (child.flags & ChunkBelowSupportDepth) != 0) + { + // Add cost and benefit for children + const uint32_t childndexInAsset = childIndex - destructible->getFirstChunkIndex(); + const uint32_t childShapeCount = destructible->getDestructibleAsset()->getChunkHullCount(childndexInAsset); + + cost += childShapeCount; + benefit += destructible->getBenefit()*(float)childShapeCount/(float)PxMax<uint32_t>(destructible->getVisibleDynamicChunkShapeCount(), 1); + + // Parent is dynamic (so its children will be too), or the child is below the support depth, so make it dynamic + child.state |= ChunkTemp3; + } + } + + chunk->state &= ~(uint8_t)(ChunkTemp1 | ChunkTemp2 | ChunkTemp3); // The parent will cease to exist + } +} + +} +} // end namespace nvidia + +#endif // __DESTRUCTIBLE_SCENE_H__ diff --git a/APEX_1.4/module/destructible/include/DestructibleStructure.h b/APEX_1.4/module/destructible/include/DestructibleStructure.h new file mode 100644 index 00000000..493d7e91 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleStructure.h @@ -0,0 +1,479 @@ +/* + * 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 __DESTRUCTIBLESTRUCTURE_H__ +#define __DESTRUCTIBLESTRUCTURE_H__ + +#include "Apex.h" +#include "DestructibleAssetProxy.h" + +#include "ScopedPhysXLock.h" + +#include "PsMutex.h" +#include "PxShape.h" +#include "PxRigidActor.h" +#include <PxRigidDynamic.h> +#include <PxRigidBodyExt.h> +#include <PxShapeExt.h> + +#ifndef USE_CHUNK_RWLOCK +#define USE_CHUNK_RWLOCK 0 +#endif + +namespace nvidia +{ +namespace destructible +{ + +class ModuleDestructibleImpl; +class DestructibleScene; +typedef class DestructibleStructureStressSolver StressSolver; + +#define ENFORCE(condition) extern char unusableName[(condition)?1:-1] +#define GET_OFFSET(Class, Member) uint64_t(&(static_cast<Class*>(0)->Member)) +struct CachedChunk : public ChunkTransformUnit +{ + CachedChunk(uint32_t chunkIndex_, PxMat44 chunkPose_) + { + chunkIndex = chunkIndex_; + chunkPosition = chunkPose_.getPosition(); + chunkOrientation = PxQuat(PxMat33(chunkPose_.column0.getXYZ(), chunkPose_.column1.getXYZ(), chunkPose_.column2.getXYZ())); +#if defined WIN32 + ENFORCE(GET_OFFSET(CachedChunk, chunkIndex) == GET_OFFSET(ChunkTransformUnit, chunkIndex)); + ENFORCE(GET_OFFSET(CachedChunk, chunkPosition) == GET_OFFSET(ChunkTransformUnit, chunkPosition)); + ENFORCE(GET_OFFSET(CachedChunk, chunkOrientation) == GET_OFFSET(ChunkTransformUnit, chunkOrientation)); + ENFORCE(static_cast<uint64_t>(sizeof(*this)) == static_cast<uint64_t>(sizeof(ChunkTransformUnit))); +#endif // WIN32 + } + ~CachedChunk() {} +private: + CachedChunk(); +}; +typedef CachedChunk ControlledChunk; +#undef GET_OFFSET +#undef ENFORCE + +struct SyncDamageEventCoreDataParams : public DamageEventCoreData +{ + SyncDamageEventCoreDataParams() + : + destructibleID(0xFFFFFFFF) + { + DamageEventCoreData::chunkIndexInAsset = 0; + DamageEventCoreData::damage = 0.0f; + DamageEventCoreData::radius = 0.0f; + DamageEventCoreData::position = PxVec3(0.0f); + } + + uint32_t destructibleID; // The ID of the destructible actor that is being damaged. +}; + +struct FractureEvent +{ + FractureEvent() : chunkIndexInAsset(0xFFFFFFFF), destructibleID(0xFFFFFFFF), flags(0), impactDamageActor(NULL), appliedDamageUserData(NULL), deletionWeight(0.0f), damageFraction(1.0f) {} + + enum Flag + { + DamageFromImpact = (1U << 0), + CrumbleChunk = (1U << 1), + DeleteChunk = (1U << 2), + + SyncDirect = (1U << 24), // fracture event is directly sync-ed + SyncDerived = (1U << 25), // fracture event is a derivative of a sync-ed damage event + Manual = (1U << 26), // fracture event is manually invoked by the user + Snap = (1U << 27), // fracture event is generated from the destructible stress solver + Forced = (1U << 28), + Silent = (1U << 29), + Virtual = (1U << 30), + + Invalid = (1U << 31) + }; + + PxVec3 position; // The position of a single fracture event. + uint32_t chunkIndexInAsset; // The chunk index which is being fractured. + PxVec3 impulse; // The impulse vector to apply for this fracture event. + uint32_t destructibleID; // The ID of the destructible actor that is being damaged. + uint32_t flags; // Bit flags describing behavior of this fracture event. + PxVec3 hitDirection; // The direction vector this damage being applied to this fracture event. + physx::PxActor const* impactDamageActor; // Other PhysX actor that caused damage to ApexDamageEventReportData. + + void* appliedDamageUserData; // User data from applyDamage or applyRadiusDamage. + float deletionWeight; // A weighting factor for probabilistic deletion + float damageFraction; // Calculated from damage spread functions, it's good to store this for later use (e.g. impulse scaling) +}; + +enum ChunkState +{ + ChunkVisible = 0x01, + ChunkDynamic = 0x02, + //ChunkControlled = 0x04, // chunk behavior is not locally-determined //unused + + ChunkTemp0 = 0x10, // chunk state has been cached + ChunkTemp1 = 0x20, // chunk exists + ChunkTemp2 = 0x40, // chunk is visible + ChunkTemp3 = 0x80, // chunk is dynamic + ChunkTempMask = 0xF0, +}; + +enum ChunkFlag +{ + ChunkCrumbled = 0x01, + ChunkBelowSupportDepth = 0x02, + ChunkExternallySupported = 0x04, + ChunkWorldSupported = 0x08, + ChunkMissingChild = 0x20, + ChunkRuntime = 0x80, + //ChunkGraphical = 0x80, // chunk has no attached PxShape //unused +}; + +/* A struct for adding forces to actors after they are added to the scene */ +struct ActorForceAtPosition +{ + ActorForceAtPosition() : force(0.0f), pos(0.0f), mode(physx::PxForceMode::eFORCE), wakeup(true), usePosition(true) {} + + ActorForceAtPosition(const PxVec3& _force, const PxVec3& _pos, physx::PxForceMode::Enum _mode, bool _wakeup, bool _usePosition) + : force(_force) + , pos(_pos) + , mode(_mode) + , wakeup(_wakeup) + , usePosition(_usePosition) + {} + + PxVec3 force; + PxVec3 pos; + physx::PxForceMode::Enum mode; + bool wakeup; + bool usePosition; +}; + + +class DestructibleStructure : public UserAllocated +{ +public: + + enum + { + InvalidID = 0xFFFFFFFF, + InvalidChunkIndex = 0xFFFFFFFF + }; + + struct Chunk + { + uint32_t destructibleID; // The GUID of the destructible actor this chunk is associated with. + uint32_t reportID; // A GUID to report state about this chunk + uint16_t indexInAsset; // The index into the master asset for this destructible + uint8_t state; // bit flags controlling the current 'state' of this chunk. + uint8_t flags; // Overall Chunk flags + float damage; // How damaged this chunk is. + PxVec3 localSphereCenter; // A local bounding sphere for this chunk (center). + float localSphereRadius; // A local bounding sphere for this chunk (radius). + const ControlledChunk * controlledChunk; // Chunk data given by user +#if USE_CHUNK_RWLOCK + shdfnd::ReadWriteLock* lock; +#endif + + PxVec3 localOffset; // If this chunk is instanced, this may be non-zero. It needs to be stored somewhere in case we use + // the transform of a parent chunk which has a different offset. Actually, this can all be looked up + // through a chain of indirection, but I'm storing it here for efficiency. + int32_t visibleAncestorIndex; // Index (in structure) of this chunks' visible ancestor, if any. If none exists, it's InvalidChunkIndex. + + uint32_t islandID; // The GUID of the actor associated with the chunk. Used for island reconstruction. + + private: + physx::Array<PxShape*> shapes; // The rigid body shapes for this chunk. + + public: + + Chunk() {} + Chunk(const Chunk& other) + { + *this = other; + } + + Chunk& operator = (const Chunk& other) + { + destructibleID = other.destructibleID; + reportID = other.reportID; + indexInAsset = other.indexInAsset; + state = other.state; + flags = other.flags; + damage = other.damage; + localSphereCenter = other.localSphereCenter; + localSphereRadius = other.localSphereRadius; + controlledChunk = other.controlledChunk; +#if USE_CHUNK_RWLOCK +#error USE_CONTROL_RWLOCK non-zero, but lock is not supported in assignment operator and copy constructor +#endif + localOffset = other.localOffset; + visibleAncestorIndex = other.visibleAncestorIndex; + islandID = other.islandID; + shapes = physx::Array<PxShape*>(other.shapes); + return *this; + } + + uint32_t getShapeCount() const + { + return shapes.size(); + } + + const PxShape* getShape(uint32_t shapeIndex) const + { + return shapeIndex < shapes.size() ? shapes[shapeIndex] : NULL; + } + + PxShape* getShape(uint32_t shapeIndex) + { + return shapeIndex < shapes.size() ? shapes[shapeIndex] : NULL; + } + + bool isFirstShape(const PxShape* shape) const + { + return shapes.size() ? shapes[0] == shape : false; + } + + void setShapes(PxShape* const* newShapes, uint32_t shapeCount) + { + shapes.resize(shapeCount); + for (uint32_t i = 0; i < shapeCount; ++i) + { + shapes[i] = newShapes[i]; + } + visibleAncestorIndex = InvalidChunkIndex; + } + + void clearShapes() + { + shapes.reset(); + visibleAncestorIndex = InvalidChunkIndex; + } + + bool isDestroyed() const + { + return shapes.empty() && visibleAncestorIndex == (int32_t)InvalidChunkIndex; + } + + friend class DestructibleStructure; + }; + +#if USE_CHUNK_RWLOCK + class ChunkScopedReadLock : public physx::ScopedReadLock + { + public: + ChunkScopedReadLock(Chunk& chunk) : physx::ScopedReadLock(*chunk.lock) {} + }; + + class ChunkScopedWriteLock : public physx::ScopedWriteLock + { + public: + ChunkScopedWriteLock(Chunk& chunk) : physx::ScopedWriteLock(*chunk.lock) {} + }; +#endif + + DestructibleScene* dscene; // The scene that this destructible structure belongs to + Array<DestructibleActorImpl*> destructibles; // The array of destructible actors associated with this destructible structure + Array<Chunk> chunks; // The array of chunks associated with this structure. + Array<uint32_t> supportDepthChunks; // + Array<uint32_t> overlaps; + Array<uint32_t> firstOverlapIndices; // Size = chunks.size()+1, firstOverlapsIndices[chunks.size()] = overlaps.size() + uint32_t ID; // The unique GUID associated with this destructible structure + uint32_t supportDepthChunksNotExternallySupportedCount; + bool supportInvalid; + PxRigidDynamic* actorForStaticChunks; + StressSolver * stressSolver; + + typedef HashMap<PxRigidDynamic*, uint32_t> ActorToIslandMap; + typedef HashMap<uint32_t, PxRigidDynamic*> IslandToActorMap; + // As internal, cache-type containers, these structures do not affect external state + mutable ActorToIslandMap actorToIsland; + mutable IslandToActorMap islandToActor; + + DestructibleStructure(DestructibleScene* inScene, uint32_t inID); + ~DestructibleStructure(); + + bool addActors(const physx::Array<class DestructibleActorImpl*>& destructiblesToAdd); + bool removeActor(DestructibleActorImpl* destructibleToRemove); + void setSupportInvalid(bool supportIsInvalid); + + void updateIslands(); + void tickStressSolver(float deltaTime); + void visualizeSupport(RenderDebugInterface* debugRender); + + uint32_t damageChunk(Chunk& chunk, const PxVec3& position, const PxVec3& direction, bool fromImpact, float damage, float damageRadius, + physx::Array<FractureEvent> outputs[], uint32_t& possibleDeleteChunks, float& totalDeleteChunkRelativeDamage, + uint32_t& maxDepth, uint32_t depth, uint16_t stopDepth, float padding); + void fractureChunk(const FractureEvent& fractureEvent); +#if APEX_RUNTIME_FRACTURE + void runtimeFractureChunk(const FractureEvent& fractureEvent, Chunk& chunk); +#endif + void crumbleChunk(const FractureEvent& fractureEvent, Chunk& chunk, const PxVec3* impulse = NULL); // Add an impulse - used when actor is static + void addDust(Chunk& chunk); + void removeChunk(Chunk& chunk); + void separateUnsupportedIslands(); + void createDynamicIsland(const physx::Array<uint32_t>& indices); + void calculateExternalSupportChunks(); + void buildSupportGraph(); + void invalidateBounds(const PxBounds3* bounds, uint32_t boundsCount); + void postBuildSupportGraph(); + void evaluateForHitChunkList(const physx::Array<uint32_t> & chunkIndices) const; + + PxMat44 getActorForStaticChunksPose() + { + if (NULL != actorForStaticChunks) + { + SCOPED_PHYSX_LOCK_READ(actorForStaticChunks->getScene()); + return PxMat44(actorForStaticChunks->getGlobalPose()); + } + else + { + return PxMat44(PxIdentity); + } + } + + physx::Array<PxShape*>& getChunkShapes(Chunk& chunk) + { + return (chunk.visibleAncestorIndex == (int32_t)InvalidChunkIndex) ? chunk.shapes : chunks[(uint32_t)chunk.visibleAncestorIndex].shapes; + } + + const physx::Array<PxShape*>& getChunkShapes(const Chunk& chunk) const + { + return (chunk.visibleAncestorIndex == (int32_t)InvalidChunkIndex) ? chunk.shapes : chunks[(uint32_t)chunk.visibleAncestorIndex].shapes; + } + + PxRigidDynamic* getChunkActor(Chunk& chunk); + + const PxRigidDynamic* getChunkActor(const Chunk& chunk) const; + + bool chunkIsSolitary(Chunk& chunk) + { + PxRigidDynamic* actor = getChunkActor(chunk); + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + return (actor == NULL) ? false : (getChunkShapes(chunk).size() == actor->getNbShapes()); + } + + Chunk* getRootChunk(Chunk& chunk) + { + if (chunk.isDestroyed()) + { + return NULL; + } + return chunk.visibleAncestorIndex == (int32_t)InvalidChunkIndex ? &chunk : &chunks[(uint32_t)chunk.visibleAncestorIndex]; + } + + PxTransform getChunkLocalPose(const Chunk& chunk) const; + + void setChunkGlobalPose(Chunk& chunk, PxTransform pose) + { + physx::Array<PxShape*>& shapes = getChunkShapes(chunk); + PX_ASSERT(!shapes.empty()); + + for (uint32_t i = 0; i < shapes.size(); ++i) + { + const PxTransform shapeLocalPose = shapes[i]->getLocalPose(); + const PxTransform inverseShapeLocalPose = shapeLocalPose.getInverse(); + PxTransform newGlobalPose = pose * inverseShapeLocalPose; + + shapes[i]->getActor()->setGlobalPose(newGlobalPose); + } + } + + PxTransform getChunkActorPose(const Chunk& chunk) const; + + PxTransform getChunkGlobalPose(const Chunk& chunk) const + { + return getChunkActorPose(chunk) * getChunkLocalPose(chunk); + } + + PxTransform getChunkLocalTransform(const Chunk& chunk) const + { + const physx::Array<PxShape*>* shapes; + PxVec3 offset; + if (chunk.visibleAncestorIndex == (int32_t)InvalidChunkIndex) + { + shapes = &chunk.shapes; + offset = PxVec3(0.0f); + } + else + { + shapes = &chunks[(uint32_t)chunk.visibleAncestorIndex].shapes; + offset = chunk.localOffset - chunks[(uint32_t)chunk.visibleAncestorIndex].localOffset; + } + + PX_ASSERT(!shapes->empty()); + PxTransform transform; + if (!shapes->empty() && NULL != (*shapes)[0]) + { + transform = (*shapes)[0]->getLocalPose(); + } + else + { + transform = PxTransform(PxVec3(0, 0, 0), PxQuat(0, 0, 0, 1)); + } + transform.p += offset; + return transform; + } + + PxTransform getChunkActorTransform(const Chunk& chunk) const + { + const physx::Array<PxShape*>& shapes = getChunkShapes(chunk); + PX_ASSERT(!shapes.empty()); + if (!shapes.empty() && NULL != shapes[0]) + { + // All shapes should have the same actor + SCOPED_PHYSX_LOCK_READ(shapes[0]->getActor()->getScene()); + return shapes[0]->getActor()->getGlobalPose(); + } + else + { + return PxTransform(PxVec3(0, 0, 0), PxQuat(0, 0, 0, 1)); + } + } + + PxTransform getChunkGlobalTransform(const Chunk& chunk) const + { + return getChunkActorTransform(chunk).transform(getChunkLocalTransform(chunk)); + } + + void addChunkImpluseForceAtPos(Chunk& chunk, const PxVec3& impulse, const PxVec3& position, bool wakeup = true); + + PxVec3 getChunkWorldCentroid(const Chunk& chunk) const + { + return getChunkGlobalPose(chunk).transform(chunk.localSphereCenter); + } + + // This version saves a little time on consoles (saving a recalcualtion of the chunk global pose + PX_INLINE PxVec3 getChunkWorldCentroid(const Chunk& chunk, const PxTransform& chuckGlobalPose) + { + return chuckGlobalPose.transform(chunk.localSphereCenter); + } + + uint32_t newPxActorIslandReference(Chunk& chunk, PxRigidDynamic& nxActor); + void removePxActorIslandReferences(PxRigidDynamic& nxActor) const; + + uint32_t getSupportDepthChunkIndices(uint32_t* const OutChunkIndices, uint32_t MaxOutIndices) const + { + PX_ASSERT( supportDepthChunksNotExternallySupportedCount <= supportDepthChunks.size() ); + + uint32_t chunkNum = 0; + for ( ; chunkNum < supportDepthChunksNotExternallySupportedCount && chunkNum < MaxOutIndices; ++chunkNum ) + { + uint32_t chunkIndex = supportDepthChunks[chunkNum]; + Chunk const& chunk = chunks[chunkIndex]; + OutChunkIndices[chunkNum] = chunk.indexInAsset; + } + + return chunkNum; + } +}; + +} +} // end namespace nvidia + +#endif // __DESTRUCTIBLESTRUCTURE_H__ diff --git a/APEX_1.4/module/destructible/include/DestructibleStructureStressSolver.h b/APEX_1.4/module/destructible/include/DestructibleStructureStressSolver.h new file mode 100644 index 00000000..cf1b5ab8 --- /dev/null +++ b/APEX_1.4/module/destructible/include/DestructibleStructureStressSolver.h @@ -0,0 +1,413 @@ +/* + * 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 DESTRUCTIBLE_STRUCTURE_STRESS_SOLVER_H +#define DESTRUCTIBLE_STRUCTURE_STRESS_SOLVER_H + +#include "PsUserAllocated.h" +#include "ApexUsingNamespace.h" +#include "PsArray.h" + + +#include "DestructibleScene.h" +#include "Scene.h" +#include "ApexDefs.h" +#include <PxPhysics.h> +#include "cooking/PxCooking.h" + +#include <PxScene.h> +#include "extensions/PxExtensionsAPI.h" +#include "extensions/PxDefaultCpuDispatcher.h" +#include "extensions/PxDefaultSimulationFilterShader.h" +#include <PxFiltering.h> +#include <PxMaterial.h> +#include <PxFixedJoint.h> +#include <PxConstraint.h> + +namespace nvidia +{ +namespace destructible +{ + +class DestructibleStructure; +class DestructibleActorImpl; +struct ActorChunkPair; +struct FractureEvent; + +// a helper class for managing states using an array +template<class T, typename F, unsigned int N> +class ArraySet +{ +public: + explicit ArraySet(T v) + { + PX_COMPILE_TIME_ASSERT(N > 0); +#if defined(PX_PS4) + typedef char PxCompileTimeAssert_Dummy2[(N * sizeof(T) == sizeof(*this)) ? 1 : -1] __attribute__((unused)); +#else + typedef char PxCompileTimeAssert_Dummy2[(N * sizeof(T) == sizeof(*this)) ? 1 : -1]; +#endif + ::memset(static_cast<void*>(&t[0]), v, N * sizeof(T)); + } + ~ArraySet() + { + } + void set(unsigned int i, F f) + { + PX_ASSERT(i < N); + PX_ASSERT(!isSet(i, f)); + t[i] |= f; + } + void unset(unsigned int i, F f) + { + PX_ASSERT(i < N); + PX_ASSERT(isSet(i, f)); + t[i] &= ~f; + } + bool isSet(unsigned int i, F f) const + { + PX_ASSERT(i < N); + return (0 != (f & t[i])); + } + void reset(T v) + { + ::memset(static_cast<void*>(&t[0]), v, N * sizeof(T)); + } + const T (&get() const) [N] + { + return t; + } + const T * getPtr() const + { + return &t[0]; + } +private: + T t[N]; +}; // class ArraySet + +// Int-To-Type idiom +template<unsigned int I> +struct Int2Type +{ + enum + { + Value = I, + }; +}; // struct Int2Type + +// a type container used to identify the different ways of evaluating stresses on the structure +struct StressEvaluationType +{ + enum Enum + { + EvaluateByCount = 0, + EvaluateByMoment, + }; +}; // struct StressEvaluationType + +// a helper data structure used for recording bit values +struct StructureScratchBuffer +{ +public: + StructureScratchBuffer(uint8_t * const bufferStart, uint32_t bufferCount); + ~StructureScratchBuffer(); + + bool isOccupied(uint32_t index) const; + void setOccupied(uint32_t index); + +private: + StructureScratchBuffer(); + StructureScratchBuffer& operator=(const StructureScratchBuffer&); + + enum ByteState + { + ByteEmpty = 0x00, + ByteExist = 0xFF, + }; + + uint8_t * const bufferStart; + const uint32_t bufferCount; +}; // struct StructureScratchBuffer + +// a data structure used to collect and hold potential new island data +struct PeninsulaData +{ +public: + PeninsulaData(); + PeninsulaData(uint8_t peninsulaState, uint32_t chunkCount); + PeninsulaData(uint8_t peninsulaState, uint32_t chunkCount, float aggregateMass, PxVec3 geometricCenter); + ~PeninsulaData(); + enum PeninsulaFlag + { + PeninsulaEncounteredExternalSupport = (1 << 0), + PeninsulaEncounteredAnotherWeakLink = (1 << 1), + PeninsulaInvalidMaxFlag = (1 << 2), + }; + + bool isValid() const; + void resetData(); + void setFlag(PeninsulaData::PeninsulaFlag peninsulaFlag); + void setLinkedChunkData(const ActorChunkPair & actorChunkPair, Int2Type<StressEvaluationType::EvaluateByCount>); + void setLinkedChunkData(const ActorChunkPair & actorChunkPair, Int2Type<StressEvaluationType::EvaluateByMoment>); + void setRootLinkedChunkIndex(uint32_t linkedChunkIndex); + void assimilate(const PeninsulaData & that, Int2Type<StressEvaluationType::EvaluateByCount>); + void assimilate(const PeninsulaData & that, Int2Type<StressEvaluationType::EvaluateByMoment>); + bool hasFlag(PeninsulaData::PeninsulaFlag peninsulaFlag) const; + uint32_t getDataChunkCount() const; + float getDataAggregateMass() const; + const PxVec3 & getDataGeometricCenter() const; + uint32_t getRootLinkedChunkIndex() const; +private: + const PeninsulaData operator+ (const PeninsulaData &); + PeninsulaData & operator+= (const PeninsulaData &); + + uint32_t rootLinkedChunkIndex; + uint8_t peninsulaState; + uint32_t chunkCount; + float aggregateMass; + PxVec3 geometricCenter; +}; // struct PeninsulaData + +// a data structure used to hold minimally required fracture data +struct FractureEventProxy : public UserAllocated +{ +public: + uint32_t rootLinkedChunkIndex; + uint32_t chunkIndexInAsset; + uint32_t destructibleId; + uint32_t fractureEventProxyFlags; + PxVec3 rootLinkedChunkPosition; + PxVec3 impulse; +}; // struct FractureEventProxy + +// a data structure with a 1-N convertible relationship with fracture event(s) +struct SnapEvent : public UserAllocated +{ +public: + static SnapEvent* instantiate(FractureEventProxy * fractureEventProxyBufferStart, uint32_t fractureEventProxyBufferCount, float tickSecondsToSnap); + + void onDestroy(); + bool isRipeAfterUpdatingTime(float deltaTime); + bool isExpired() const; + uint32_t getFractureEventProxyCount() const; + const FractureEventProxy& getFractureEventProxy(uint32_t index) const; + +private: + SnapEvent(FractureEventProxy* fractureEventProxyBufferStart, uint32_t fractureEventProxyBufferCount, float tickSecondsToSnap); + SnapEvent& operator=(const SnapEvent&); + + ~SnapEvent(); + SnapEvent(); + + FractureEventProxy* fractureEventProxyBufferStart; + const uint32_t fractureEventProxyBufferCount; + float tickSecondsRemainingToSnap; +}; // struct SnapEvent + +// a solver with a 1-1 or 0-1 relationship with a destructible structure +class DestructibleStructureStressSolver : public UserAllocated +{ +public: + explicit DestructibleStructureStressSolver(const DestructibleStructure & bindedStructureAlias, float strength); + + ~DestructibleStructureStressSolver(); + + void onTick(float deltaTime); + void onUpdate(uint32_t linkedChunkIndex); + void onResolve(); +private: + DestructibleStructureStressSolver(); + DestructibleStructureStressSolver(const DestructibleStructureStressSolver &); + DestructibleStructureStressSolver & operator= (const DestructibleStructureStressSolver &); + enum StructureLinkFlag + { + LinkedChunkExist = (1 << 0), + LinkedChunkBroken = (1 << 1), + LinkedChunkStrained = (1 << 2), + LinkedChunkInvalidMaxFlag = (1 << 3), + }; + enum LinkTestParameters + { + LowerLimitActivationCount = 2, + UpperLimitActivationCount = 3, + }; + enum LinkTraverseParameters + { + PathTraversalCount = 2, + }; + static const StressEvaluationType::Enum StressEvaluationEnum = StressEvaluationType::EvaluateByMoment; + + void processLinkedChunkIndicesForEvaluation(physx::Array<uint32_t> & linkedChunkIndicesForEvaluation); + void evaluateForPotentialIslands(const physx::Array<uint32_t> & linkedChunkIndicesForEvaluation); + bool passLinkCountTest(uint32_t linkedChunkIndex, physx::Array<uint32_t> & unbrokenAdjacentLinkedChunkIndices) const; + bool passLinkAdjacencyTest(const physx::Array<uint32_t> & unbrokenAdjacentLinkedChunkIndices, uint32_t (&linkedChunkIndicesForTraversal)[2]) const; + void evaluateForPotentialPeninsulas(uint32_t rootLinkedChunkIndex, const uint32_t (&linkedChunkIndicesForTraversal)[2]); + PeninsulaData traverseLink(uint32_t linkedChunkIndex, StructureScratchBuffer & traverseRecord) const; + void evaluatePeninsulas(const PeninsulaData (&peninsulasForEvaluation)[2]); + SnapEvent * interpret(const PeninsulaData & peninsulaData, Int2Type<StressEvaluationType::EvaluateByCount>) const; + SnapEvent * interpret(const PeninsulaData & peninsulaData, Int2Type<StressEvaluationType::EvaluateByMoment>) const; + const FractureEvent & interpret(const FractureEventProxy & fractureEventProxy) const; + + bool isLinkedChunkBroken(uint32_t linkedChunkIndex) const; + void setLinkedChunkBroken(uint32_t linkedChunkIndex); + bool isLinkedChunkStrained(uint32_t linkedChunkIndex) const; + void setLinkedChunkStrained(uint32_t linkedChunkIndex); + void getUnbrokenAdjacentLinkedChunkIndices(uint32_t linkedChunkIndex, physx::Array<uint32_t> & unbrokenAdjacentLinkedChunkIndices) const; + bool areUnbrokenLinkedChunksAdjacent(uint32_t linkedChunkIndex, uint32_t linkedChunkIndexSubject) const; + ActorChunkPair getActorChunkPair(uint32_t chunkIndexInStructure) const; + StructureScratchBuffer acquireScratchBuffer() const; + void relinquishScratchBuffer() const; + DestructibleStructure & getBindedStructureMutable(); + bool assertLinkedChunkIndexOk(uint32_t linkedChunkIndex) const; + bool assertLinkedChunkIndicesForEvaluationOk(const physx::Array<uint32_t> & linkedChunkIndicesForEvaluation) const; + + const DestructibleStructure & bindedStructureAlias; + uint32_t structureLinkCount; + uint8_t * structureLinkCondition; + uint8_t * scratchBuffer; + mutable bool scratchBufferLocked; + float userTimeDelay; + float userMassThreshold; + physx::Array<uint32_t> recentlyBrokenLinkedChunkIndices; + physx::Array<uint32_t> strainedLinkedChunkIndices; + physx::Array<SnapEvent*> snapEventContainer; + + //Shadow scene to simulate a set of linked rigidbodies + public : + struct LinkedJoint + { + uint32_t actor1Index; + uint32_t actor2Index; + physx::PxFixedJoint * joint; + bool isDestroyed; + }; + + struct ShadowActor + { + physx::PxRigidDynamic* actor; + float currentForce; + float maxInitialForce; + bool isDestroyed; + }; +private: + //The basic assumption is that the initialize structure is valid, so we should know the maximum force for each link through initializing, and use it to calculate the threshold. + //So initializingMaxForce is to judge if it is initializing or something breaks the initializing. + bool initializingMaxForce; + + // The isNoChunkWarmingUpdate is the variable that fewer chunks updating during the warming, in this case, just quit warming. + bool isNoChunkWarmingUpdate; + + // The isSimulating symbol indicates if the shadowScene is simulating. + bool isSimulating; + + uint32_t continuousNoUpdationCount; + physx::Array<ShadowActor> shadowActors; + + //Hash the global chunk index to the support chunk's index + physx::Array<uint32_t> globalHashedtoSupportChunks; + + //initialWarmingKillList caches the chunks breaking during the warming stage, after warming is done, all chunks in this list will be removed from shadow scene. + physx::Array<uint32_t> initialWarmingKillList; + + //islandKillList caches the chunks removed by the reason of new island generation, all supported chunks will be removed from the shadow scene at once. + physx::Array<uint32_t> islandKillList; + + //forces[i] are the current force for supported chunk i in the scene. + physx::Array<float> forces; + + //linked joints are constructed as a network for chunk breaking prediction. + physx::Array<LinkedJoint> linkedJoint; + + //The SDK is usde to create the shadow scene + physx::PxPhysics * newSceneSDK; + + //The shadow scene is used to construct linked joints which are used for chunk breaking prediction + physx::PxScene* shadowScene; + + //Size of the supported chunk in the real scene. + uint32_t supportChunkSize; + + //The supportStrength is used for the stress solver. As this value is increased it takes more force to break apart the chunks under the effect of stress solver. + float supportStrength; + + //currentWarmingFrame increases by 1 in the warming stage. + uint32_t currentWarmingFrame; + + //initialWarmFrames is used with currentWarmingFrame. If currentWarmingFrame is larger than initialWarmFrames, the warming will stop. + uint32_t initialWarmFrames; + + //If no fracturing during one activCycle, just turn the mode to sleep. + uint32_t activeCycle; + + //It is used with the activeCycle, + uint32_t currentActiveSimulationFrame; + + //If any chunks break isActiveWakedUp is set to true indicates that the stress solver will wake up. + bool isActiveWakedUp; + + bool isSleep; +public : + // The isPhysxBasedSim is the variable that uses by the customer if they want to choose the physics based simulation mode. + bool isPhysxBasedSim; + + // The isCustomEnablesSimulating symbol is used by the user if the they would like to stop the shadowScene simulating after creating the shadow scene. + bool isCustomEnablesSimulating; + + //Functions: + uint32_t predictBreakChunk(float deltaTime, float supportStrength_); + //create the shadow scene + void createShadowScene(uint32_t initialWarmFrames_,uint32_t actCycle, float supStrength); + //calculate current maximum force + void calculateMaxForce(uint32_t& index, float supportStrength_); + + //If new island genereates, remove the chunks in the island + void removeChunkFromIsland(uint32_t index); + //Break specific chunk + void breakChunks(uint32_t index); + //Entry to use physx based stress solver + void physcsBasedStressSolverTick(); + void removeChunkFromShadowScene(bool localIndex, uint32_t index); + void resetSupportStrength(float supportStrength_); + void resetActiveCycle(uint32_t actCycle); + void resetInitialWarmFrames(uint32_t iniWarmFrames); + void enablePhyStressSolver(float strength); + // The stress solver will stop simulating after calling disablePhyStressSolver; + void disablePhyStressSolver(); + void removePhysStressSolver(); +}; // class DestructibleStructureStressSolver + +} // namespace destructible +} // namespace nvidia + +#endif // DESTRUCTIBLE_STRUCTURE_STRESS_SOLVER_H + +#if 0 +/* +issues and improvements: +1) performance - traverseLink() may generate a stack that is too deep - explore ways to return out earlier. + 1.1) tried to return out earlier by returning when we hit a strained link, but this will not work for some composite cases + 1.2) basic assumption that a strained link will go on and find an externally supported chunk may be true initially, + but this condition needs to be verified again subsequently. + 1.3) tried to evaluate past strained links for evaluation runs that contain recently broken links that used to be strained, + this seemed promising initially, but under an uncommon, yet possible scenario, an unsupported peninsula could be instantly + generated by breaking links, without the intermediate stage of it being strained. Thus, this method was abandoned. +2) performance - do less traversing by assimilating previously-traversed peninsula data + 2.1) while this will not lessen the stack generated, performance could be improved if somehow we can cache peninsula information + for an evaluation run. We can reliably reuse this peninsula information instead traversing past it again. Using the flag + PeninsulaEncounteredAnotherWeakLink could be useful for this purpose. Doing this may require significant refactoring. +3) realism - widen criteria for qualifying weak links + 3.1) we can improve passLinkCountTest() and passLinkAdjacencyTest() to qualify more links for peninsula assessment. For example, + we can try extending it to assess 4 links as well, and also possibly to assess 3 traversal paths. +4) realism - make better use of physical data to create better break-offs + 4.1) we can try and make a peninsula break off in a better direction, such as about the pivot (the weak link), instead of it + dropping down vertically. +*/ +#endif // notes diff --git a/APEX_1.4/module/destructible/include/ModuleDestructibleImpl.h b/APEX_1.4/module/destructible/include/ModuleDestructibleImpl.h new file mode 100644 index 00000000..24131733 --- /dev/null +++ b/APEX_1.4/module/destructible/include/ModuleDestructibleImpl.h @@ -0,0 +1,556 @@ +/* + * 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 __MODULE_DESTRUCTIBLE_IMPL_H__ +#define __MODULE_DESTRUCTIBLE_IMPL_H__ + +#include "Apex.h" +#include "ApexSDKIntl.h" +#include "ModuleIntl.h" +#include "ModuleBase.h" + +#include "FractureTools.h" + +#include "ModuleDestructible.h" + +#include "DestructibleActorJoint.h" +#include "DestructibleAssetImpl.h" +#include "PsMutex.h" +#include "ApexAuthorableObject.h" + +#include "ApexSDKCachedDataImpl.h" +#include "ApexRWLockable.h" +#include "ReadCheck.h" +#include "WriteCheck.h" +#include "ApexRand.h" + +#include "ModuleDestructibleRegistration.h" +#ifndef USE_DESTRUCTIBLE_RWLOCK +#define USE_DESTRUCTIBLE_RWLOCK 0 +#endif + +#define DECLARE_DISABLE_COPY_AND_ASSIGN(Class) private: Class(const Class &); Class & operator = (const Class &); + +namespace nvidia +{ +namespace destructible +{ + +/*** SyncParams ***/ +typedef UserDestructibleSyncHandler<DamageEventHeader> UserDamageEventHandler; +typedef UserDestructibleSyncHandler<FractureEventHeader> UserFractureEventHandler; +typedef UserDestructibleSyncHandler<ChunkTransformHeader> UserChunkMotionHandler; + +class DestructibleActorImpl; +class DestructibleScene; + +class DestructibleModuleCachedData : public ModuleCachedDataIntl, public UserAllocated +{ +public: + DestructibleModuleCachedData(AuthObjTypeID moduleID); + virtual ~DestructibleModuleCachedData(); + + virtual AuthObjTypeID getModuleID() const + { + return mModuleID; + } + + virtual NvParameterized::Interface* getCachedDataForAssetAtScale(Asset& asset, const PxVec3& scale); + virtual PxFileBuf& serialize(PxFileBuf& stream) const; + virtual PxFileBuf& deserialize(PxFileBuf& stream); + virtual void clear(bool force = true); + + void clearAssetCollisionSet(const DestructibleAssetImpl& asset); + physx::Array<PxConvexMesh*>* getConvexMeshesForActor(const DestructibleActorImpl& destructible); // increments ref counts + void releaseReferencesToConvexMeshesForActor(const DestructibleActorImpl& destructible); // decrements ref counts + + // The DestructibleActor::cacheModuleData() method needs to avoid incrementing the ref count + physx::Array<PxConvexMesh*>* getConvexMeshesForScale(const DestructibleAssetImpl& asset, const PxVec3& scale, bool incRef = true); + + DestructibleAssetCollision* getAssetCollisionSet(const DestructibleAssetImpl& asset); + + virtual PxFileBuf& serializeSingleAsset(Asset& asset, PxFileBuf& stream); + virtual PxFileBuf& deserializeSingleAsset(Asset& asset, PxFileBuf& stream); +private: + DestructibleAssetCollision* findAssetCollisionSet(const char* name); + + struct Version + { + enum Enum + { + First = 0, + + Count, + Current = Count - 1 + }; + }; + + AuthObjTypeID mModuleID; + physx::Array<DestructibleAssetCollision*> mAssetCollisionSets; +}; + +class ModuleDestructibleImpl : public ModuleDestructible, public ModuleIntl, public ModuleBase, public ApexRWLockable +{ +public: + APEX_RW_LOCKABLE_BOILERPLATE + + ModuleDestructibleImpl(ApexSDKIntl* sdk); + ~ModuleDestructibleImpl(); + + void destroy(); + + // base class methods + void init(NvParameterized::Interface& desc); + NvParameterized::Interface* getDefaultModuleDesc(); + void release() + { + ModuleBase::release(); + } + const char* getName() const + { + READ_ZONE(); + return ModuleBase::getName(); + } + bool isInitialized() + { + return m_isInitialized; + } + + bool setRenderLockMode(RenderLockMode::Enum, Scene&); + + RenderLockMode::Enum getRenderLockMode(const Scene&) const; + + bool lockModuleSceneRenderLock(Scene&); + + bool unlockModuleSceneRenderLock(Scene&); + + void setIntValue(uint32_t parameterIndex, uint32_t value); + ModuleSceneIntl* createInternalModuleScene(SceneIntl&, RenderDebugInterface*); + void releaseModuleSceneIntl(ModuleSceneIntl&); + uint32_t forceLoadAssets(); + AuthObjTypeID getModuleID() const; + RenderableIterator* createRenderableIterator(const Scene&); + + DestructibleActorJoint* createDestructibleActorJoint(const DestructibleActorJointDesc&, Scene&); + bool isDestructibleActorJointActive(const DestructibleActorJoint*, Scene&) const; + + void setMaxDynamicChunkIslandCount(uint32_t maxCount); + void setMaxChunkCount(uint32_t maxCount); + + void setSortByBenefit(bool sortByBenefit); + void setMaxChunkDepthOffset(uint32_t offset); + void setMaxChunkSeparationLOD(float separationLOD); + + void setChunkReport(UserChunkReport* chunkReport); + void setImpactDamageReportCallback(UserImpactDamageReport* impactDamageReport); + void setChunkReportBitMask(uint32_t chunkReportBitMask); + void setDestructiblePhysXActorReport(UserDestructiblePhysXActorReport* destructiblePhysXActorReport); + void setChunkReportMaxFractureEventDepth(uint32_t chunkReportMaxFractureEventDepth); + void scheduleChunkStateEventCallback(DestructibleCallbackSchedule::Enum chunkStateEventCallbackSchedule); + void setChunkCrumbleReport(UserChunkParticleReport* chunkCrumbleReport); + void setChunkDustReport(UserChunkParticleReport* chunkDustReport); + void setWorldSupportPhysXScene(Scene& apexScene, PxScene* physxScene); + + bool owns(const PxRigidActor* actor) const; +#if APEX_RUNTIME_FRACTURE + bool isRuntimeFractureShape(const PxShape& shape) const; +#endif + + DestructibleActor* getDestructibleAndChunk(const PxShape* shape, int32_t* chunkIndex) const; + + void applyRadiusDamage(Scene& scene, float damage, float momentum, + const PxVec3& position, float radius, bool falloff); + + void setMaxActorCreatesPerFrame(uint32_t maxActorsPerFrame); + void setMaxFracturesProcessedPerFrame(uint32_t maxActorsPerFrame); + void setValidBoundsPadding(float); + +#if 0 // dead code + void releaseBufferedConvexMeshes(); +#endif + + ModuleCachedDataIntl* getModuleDataCache() + { + return mCachedData; + } + + PX_INLINE NvParameterized::Interface* getApexDestructiblePreviewParams(void) const + { + return mApexDestructiblePreviewParams; + } + + void setUseLegacyChunkBoundsTesting(bool useLegacyChunkBoundsTesting); + bool getUseLegacyChunkBoundsTesting() const + { + return mUseLegacyChunkBoundsTesting; + } + + void setUseLegacyDamageRadiusSpread(bool useLegacyDamageRadiusSpread); + bool getUseLegacyDamageRadiusSpread() const + { + return mUseLegacyDamageRadiusSpread; + } + + bool setMassScaling(float massScale, float scaledMassExponent, Scene& apexScene); + + void invalidateBounds(const PxBounds3* bounds, uint32_t boundsCount, Scene& apexScene); + + void setDamageApplicationRaycastFlags(nvidia::DestructibleActorRaycastFlags::Enum flags, Scene& apexScene); + + bool setChunkCollisionHullCookingScale(const PxVec3& scale); + + PxVec3 getChunkCollisionHullCookingScale() const { READ_ZONE(); return mChunkCollisionHullCookingScale; } + + virtual class FractureToolsAPI* getFractureTools() const + { + READ_ZONE(); +#ifdef WITHOUT_APEX_AUTHORING + APEX_DEBUG_WARNING("FractureTools are not available in release builds."); +#endif + return (FractureToolsAPI*)mFractureTools; + } + + DestructibleModuleParameters* getModuleParameters() + { + return mModuleParams; + } + +#if 0 // dead code + physx::Array<PxConvexMesh*> convexMeshKillList; +#endif + +private: + // Private interface, used by Destructible* classes + + DestructibleScene* getDestructibleScene(const Scene& apexScene) const; + + bool m_isInitialized; + + // Max chunk depth offset (for LOD) - effectively reduces the max chunk depth in all destructibles by this number + uint32_t m_maxChunkDepthOffset; + // Where in the assets' min-max range to place the lifetime and max. separation + float m_maxChunkSeparationLOD; + float m_validBoundsPadding; + uint32_t m_maxFracturesProcessedPerFrame; + uint32_t m_maxActorsCreateablePerFrame; + uint32_t m_dynamicActorFIFOMax; + uint32_t m_chunkFIFOMax; + bool m_sortByBenefit; + UserChunkReport* m_chunkReport; + UserImpactDamageReport* m_impactDamageReport; + uint32_t m_chunkReportBitMask; + UserDestructiblePhysXActorReport* m_destructiblePhysXActorReport; + uint32_t m_chunkReportMaxFractureEventDepth; + DestructibleCallbackSchedule::Enum m_chunkStateEventCallbackSchedule; + UserChunkParticleReport* m_chunkCrumbleReport; + UserChunkParticleReport* m_chunkDustReport; + + float m_massScale; + float m_scaledMassExponent; + + ResourceList m_destructibleSceneList; + + ResourceList mAuthorableObjects; + + NvParameterized::Interface* mApexDestructiblePreviewParams; + DestructibleModuleParameters* mModuleParams; + + DestructibleModuleCachedData* mCachedData; + + nvidia::QDSRand mRandom; + + bool mUseLegacyChunkBoundsTesting; + bool mUseLegacyDamageRadiusSpread; + + PxVec3 mChunkCollisionHullCookingScale; + + class FractureTools* mFractureTools; + + /*** ModuleDestructibleImpl::SyncParams ***/ +public: + bool setSyncParams(UserDamageEventHandler * userDamageEventHandler, UserFractureEventHandler * userFractureEventHandler, UserChunkMotionHandler * userChunkMotionHandler); +public: + class SyncParams + { + friend bool ModuleDestructibleImpl::setSyncParams(UserDamageEventHandler *, UserFractureEventHandler *, UserChunkMotionHandler *); + public: + SyncParams(); + ~SyncParams(); + UserDamageEventHandler * getUserDamageEventHandler() const; + UserFractureEventHandler * getUserFractureEventHandler() const; + UserChunkMotionHandler * getUserChunkMotionHandler() const; + template<typename T> uint32_t getSize() const; + private: + DECLARE_DISABLE_COPY_AND_ASSIGN(SyncParams); + UserDamageEventHandler * userDamageEventHandler; + UserFractureEventHandler * userFractureEventHandler; + UserChunkMotionHandler * userChunkMotionHandler; + }; + const ModuleDestructibleImpl::SyncParams & getSyncParams() const; +private: + SyncParams mSyncParams; + +private: + friend class DestructibleActorImpl; + friend class DestructibleActorJointImpl; + friend class DestructibleAssetImpl; + friend class DestructibleStructure; + friend class DestructibleScene; + friend class DestructibleContactReport; + friend class DestructibleContactModify; + friend class ApexDamageEventReportDataImpl; + friend struct DestructibleNXActorCreator; +}; + + + +#ifndef WITHOUT_APEX_AUTHORING +// API for FractureTools from our shared/internal code +class FractureTools : public nvidia::apex::FractureToolsAPI, public UserAllocated +{ +public: + virtual ~FractureTools() {}; + + virtual ::FractureTools::CutoutSet* createCutoutSet() + { + return ::FractureTools::createCutoutSet(); + } + + virtual void buildCutoutSet(::FractureTools::CutoutSet& cutoutSet, const uint8_t* pixelBuffer, uint32_t bufferWidth, uint32_t bufferHeight, float snapThreshold, bool periodic) + { + return ::FractureTools::buildCutoutSet(cutoutSet, pixelBuffer, bufferWidth, bufferHeight, snapThreshold, periodic); + } + + virtual bool calculateCutoutUVMapping(const nvidia::ExplicitRenderTriangle& triangle, PxMat33& theMapping) + { + return ::FractureTools::calculateCutoutUVMapping(triangle, theMapping); + } + + virtual bool calculateCutoutUVMapping(nvidia::ExplicitHierarchicalMesh& hMesh, const PxVec3& targetDirection, PxMat33& theMapping) + { + return ::FractureTools::calculateCutoutUVMapping(hMesh, targetDirection, theMapping); + } + + virtual bool createVoronoiSplitMesh + ( + nvidia::ExplicitHierarchicalMesh& hMesh, + nvidia::ExplicitHierarchicalMesh& iHMeshCore, + bool exportCoreMesh, + int32_t coreMeshImprintSubmeshIndex, + const ::FractureTools::MeshProcessingParameters& meshProcessingParams, + const ::FractureTools::FractureVoronoiDesc& desc, + const CollisionDesc& collisionDesc, + uint32_t randomSeed, + nvidia::IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::createVoronoiSplitMesh(hMesh, iHMeshCore, exportCoreMesh, coreMeshImprintSubmeshIndex, meshProcessingParams, desc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual uint32_t createVoronoiSitesInsideMesh + ( + nvidia::ExplicitHierarchicalMesh& hMesh, + PxVec3* siteBuffer, + uint32_t* siteChunkIndices, + uint32_t siteCount, + uint32_t* randomSeed, + uint32_t* microgridSize, + BSPOpenMode::Enum meshMode, + nvidia::IProgressListener& progressListener, + uint32_t chunkIndex = 0xFFFFFFFF + ) + { + return ::FractureTools::createVoronoiSitesInsideMesh(hMesh, siteBuffer, siteChunkIndices, siteCount, randomSeed, microgridSize, meshMode, progressListener, chunkIndex); + } + + virtual uint32_t createScatterMeshSites + ( + uint8_t* meshIndices, + PxMat44* relativeTransforms, + uint32_t* chunkMeshStarts, + uint32_t scatterMeshInstancesBufferSize, + nvidia::ExplicitHierarchicalMesh& hMesh, + uint32_t targetChunkCount, + const uint16_t* targetChunkIndices, + uint32_t* randomSeed, + uint32_t scatterMeshAssetCount, + nvidia::RenderMeshAsset** scatterMeshAssets, + const uint32_t* minCount, + const uint32_t* maxCount, + const float* minScales, + const float* maxScales, + const float* maxAngles + ) + { + return ::FractureTools::createScatterMeshSites(meshIndices, relativeTransforms, chunkMeshStarts, scatterMeshInstancesBufferSize, hMesh, targetChunkCount, + targetChunkIndices, randomSeed, scatterMeshAssetCount, scatterMeshAssets, minCount, maxCount, minScales, maxScales, maxAngles); + } + + virtual void visualizeVoronoiCells + ( + nvidia::RenderDebugInterface& debugRender, + const PxVec3* sites, + uint32_t siteCount, + const uint32_t* cellColors, + uint32_t cellColorCount, + const PxBounds3& bounds, + uint32_t cellIndex = 0xFFFFFFFF + ) + { + ::FractureTools::visualizeVoronoiCells(debugRender, sites, siteCount, cellColors, cellColorCount, bounds, cellIndex); + } + + virtual bool buildExplicitHierarchicalMesh + ( + nvidia::ExplicitHierarchicalMesh& iHMesh, + const nvidia::ExplicitRenderTriangle* meshTriangles, + uint32_t meshTriangleCount, + const nvidia::ExplicitSubmeshData* submeshData, + uint32_t submeshCount, + uint32_t* meshPartition = NULL, + uint32_t meshPartitionCount = 0, + int32_t* parentIndices = NULL, + uint32_t parentIndexCount = 0 + + ) + { + return ::FractureTools::buildExplicitHierarchicalMesh(iHMesh, meshTriangles, meshTriangleCount, submeshData, submeshCount, meshPartition, meshPartitionCount, parentIndices, parentIndexCount); + } + + virtual void setBSPTolerances + ( + float linearTolerance, + float angularTolerance, + float baseTolerance, + float clipTolerance, + float cleaningTolerance + ) + { + ::FractureTools::setBSPTolerances(linearTolerance, angularTolerance, baseTolerance, clipTolerance, cleaningTolerance); + } + + virtual void setBSPBuildParameters + ( + float logAreaSigmaThreshold, + uint32_t testSetSize, + float splitWeight, + float imbalanceWeight + ) + { + ::FractureTools::setBSPBuildParameters(logAreaSigmaThreshold, testSetSize, splitWeight, imbalanceWeight); + } + + virtual bool buildExplicitHierarchicalMeshFromRenderMeshAsset(nvidia::ExplicitHierarchicalMesh& iHMesh, const nvidia::RenderMeshAsset& renderMeshAsset, uint32_t maxRootDepth = UINT32_MAX) + { + return ::FractureTools::buildExplicitHierarchicalMeshFromRenderMeshAsset(iHMesh, renderMeshAsset, maxRootDepth); + } + + virtual bool buildExplicitHierarchicalMeshFromDestructibleAsset(nvidia::ExplicitHierarchicalMesh& iHMesh, const nvidia::DestructibleAsset& destructibleAsset, uint32_t maxRootDepth = UINT32_MAX) + { + return ::FractureTools::buildExplicitHierarchicalMeshFromDestructibleAsset(iHMesh, destructibleAsset, maxRootDepth); + } + + virtual bool createHierarchicallySplitMesh + ( + nvidia::ExplicitHierarchicalMesh& hMesh, + nvidia::ExplicitHierarchicalMesh& iHMeshCore, + bool exportCoreMesh, + int32_t coreMeshImprintSubmeshIndex, + const ::FractureTools::MeshProcessingParameters& meshProcessingParams, + const ::FractureTools::FractureSliceDesc& desc, + const CollisionDesc& collisionDesc, + uint32_t randomSeed, + nvidia::IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::createHierarchicallySplitMesh(hMesh, iHMeshCore, exportCoreMesh, coreMeshImprintSubmeshIndex, meshProcessingParams, desc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual bool createChippedMesh + ( + nvidia::ExplicitHierarchicalMesh& hMesh, + const ::FractureTools::MeshProcessingParameters& meshProcessingParams, + const ::FractureTools::FractureCutoutDesc& desc, + const ::FractureTools::CutoutSet& iCutoutSet, + const ::FractureTools::FractureSliceDesc& sliceDesc, + const ::FractureTools::FractureVoronoiDesc& voronoiDesc, + const CollisionDesc& collisionDesc, + uint32_t randomSeed, + nvidia::IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::createChippedMesh(hMesh, meshProcessingParams, desc, iCutoutSet, sliceDesc, voronoiDesc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual bool hierarchicallySplitChunk + ( + nvidia::ExplicitHierarchicalMesh& hMesh, + uint32_t chunkIndex, + const ::FractureTools::MeshProcessingParameters& meshProcessingParams, + const ::FractureTools::FractureSliceDesc& desc, + const CollisionDesc& collisionDesc, + uint32_t* randomSeed, + nvidia::IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::hierarchicallySplitChunk(hMesh, chunkIndex, meshProcessingParams, desc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual bool voronoiSplitChunk + ( + nvidia::ExplicitHierarchicalMesh& hMesh, + uint32_t chunkIndex, + const ::FractureTools::MeshProcessingParameters& meshProcessingParams, + const ::FractureTools::FractureVoronoiDesc& desc, + const CollisionDesc& collisionDesc, + uint32_t* randomSeed, + nvidia::IProgressListener& progressListener, + volatile bool* cancel = NULL + ) + { + return ::FractureTools::voronoiSplitChunk(hMesh, chunkIndex, meshProcessingParams, desc, collisionDesc, randomSeed, progressListener, cancel); + } + + virtual bool buildSliceMesh + ( + IntersectMesh& intersectMesh, + nvidia::ExplicitHierarchicalMesh& referenceMesh, + const PxPlane& slicePlane, + const ::FractureTools::NoiseParameters& noiseParameters, + uint32_t randomSeed + ) + { + return ::FractureTools::buildSliceMesh(intersectMesh, referenceMesh, slicePlane, noiseParameters, randomSeed); + } + + virtual nvidia::ExplicitHierarchicalMesh* createExplicitHierarchicalMesh() + { + return ::FractureTools::createExplicitHierarchicalMesh(); + } + + virtual nvidia::ExplicitHierarchicalMesh::ConvexHull* createExplicitHierarchicalMeshConvexHull() + { + return ::FractureTools::createExplicitHierarchicalMeshConvexHull(); + } +}; +#endif + + + +} +} // end namespace nvidia + + +#endif // __MODULE_DESTRUCTIBLE_IMPL_H__ diff --git a/APEX_1.4/module/destructible/include/ModuleEventDefs.h b/APEX_1.4/module/destructible/include/ModuleEventDefs.h new file mode 100644 index 00000000..933cdde0 --- /dev/null +++ b/APEX_1.4/module/destructible/include/ModuleEventDefs.h @@ -0,0 +1,61 @@ +/* + * 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. + */ + + +// This file is used to define a list of AgPerfMon events. +// +// This file is included exclusively by AgPerfMonEventSrcAPI.h +// and by AgPerfMonEventSrcAPI.cpp, for the purpose of building +// an enumeration (enum xx) and an array of strings () +// that contain the list of events. +// +// This file should only contain event definitions, using the +// DEFINE_EVENT macro. E.g.: +// +// DEFINE_EVENT(sample_name_1) +// DEFINE_EVENT(sample_name_2) +// DEFINE_EVENT(sample_name_3) + +DEFINE_EVENT(DestructibleFetchResults) +DEFINE_EVENT(DestructibleUpdateRenderResources) +DEFINE_EVENT(DestructibleDispatchRenderResources) +DEFINE_EVENT(DestructibleSeparateUnsupportedIslands) +DEFINE_EVENT(DestructibleCreateDynamicIsland) +DEFINE_EVENT(DestructibleCookChunkCollisionMeshes) +DEFINE_EVENT(DestructibleAddActors) +DEFINE_EVENT(DestructibleCreateRoot) +DEFINE_EVENT(DestructibleAppendShape) +DEFINE_EVENT(DestructibleStructureTick) +DEFINE_EVENT(DestructiblePhysBasedStressSolver) +DEFINE_EVENT(DestructiblePhysBasedStressSolverInitial) +DEFINE_EVENT(DestructiblePhysBasedStressSolverCalculateForce) +DEFINE_EVENT(DestructiblePhysBasedStressSolverRemoveChunk) +DEFINE_EVENT(DestructibleStructureBoundsCalculateOverlaps) +DEFINE_EVENT(DestructibleStructureDetailedOverlapTest) +DEFINE_EVENT(DestructibleCreateActor) +DEFINE_EVENT(DestructibleCacheChunkCookedCollisionMeshes) +DEFINE_EVENT(DestructibleFractureChunk) +DEFINE_EVENT(DestructibleChunkReport) +DEFINE_EVENT(DestructibleRayCastFindVisibleChunk) +DEFINE_EVENT(DestructibleRayCastFindDeepestChunk) +DEFINE_EVENT(DestructibleRayCastProcessChunk) +DEFINE_EVENT(DestructibleRemoveChunksForBudget) +DEFINE_EVENT(DestructibleProcessFractureBuffer) +DEFINE_EVENT(DestructibleKillStructures) +DEFINE_EVENT(DestructibleOnContactConstraint) +DEFINE_EVENT(DestructibleOnContactNotify) +DEFINE_EVENT(DestructibleBeforeTickLockRenderables) +DEFINE_EVENT(DestructibleUpdateRenderMeshBonePoses) +DEFINE_EVENT(DestructibleStructureBuildSupportGraph) +DEFINE_EVENT(DestructibleSimulate) +DEFINE_EVENT(DestructibleCalcStaticChunkBenefit) +DEFINE_EVENT(DestructibleGatherNonessentialChunks) +DEFINE_EVENT(DestructibleCalculateBenefit) +DEFINE_EVENT(DestructibleGetChunkGlobalPose) diff --git a/APEX_1.4/module/destructible/include/ModulePerfScope.h b/APEX_1.4/module/destructible/include/ModulePerfScope.h new file mode 100644 index 00000000..fd53d00e --- /dev/null +++ b/APEX_1.4/module/destructible/include/ModulePerfScope.h @@ -0,0 +1,18 @@ +/* + * 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 __MODULE_PERF_SCOPE_H___ +#define __MODULE_PERF_SCOPE_H___ + +#define MODULE_NAMESPACE destructible +#include "ModuleProfileCommon.h" + +#endif
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/include/autogen/CachedOverlaps.h b/APEX_1.4/module/destructible/include/autogen/CachedOverlaps.h new file mode 100644 index 00000000..e1c34060 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/CachedOverlaps.h @@ -0,0 +1,245 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_CachedOverlaps_h +#define HEADER_CachedOverlaps_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace CachedOverlapsNS +{ + +struct IntPair_Type; + +struct IntPair_DynamicArray1D_Type +{ + IntPair_Type* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct IntPair_Type +{ + int32_t i0; + int32_t i1; +}; + +struct ParametersStruct +{ + + bool isCached; + IntPair_DynamicArray1D_Type overlaps; + +}; + +static const uint32_t checksum[] = { 0x42ce64a0, 0x9634fff2, 0x6f308fbe, 0xf3ce7bcd, }; + +} // namespace CachedOverlapsNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class CachedOverlaps : public NvParameterized::NvParameters, public CachedOverlapsNS::ParametersStruct +{ +public: + CachedOverlaps(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~CachedOverlaps(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("CachedOverlaps"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)1; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(CachedOverlapsNS::checksum); + return CachedOverlapsNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const CachedOverlapsNS::ParametersStruct& parameters(void) const + { + CachedOverlaps* tmpThis = const_cast<CachedOverlaps*>(this); + return *(static_cast<CachedOverlapsNS::ParametersStruct*>(tmpThis)); + } + + CachedOverlapsNS::ParametersStruct& parameters(void) + { + return *(static_cast<CachedOverlapsNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class CachedOverlapsFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + CachedOverlaps::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(CachedOverlaps), CachedOverlaps::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, CachedOverlaps::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class CachedOverlaps"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(CachedOverlaps)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, CachedOverlaps)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, CachedOverlaps::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, CachedOverlaps::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class CachedOverlaps"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of CachedOverlaps here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (CachedOverlaps*)bufObj; + } + + virtual const char* getClassName() + { + return (CachedOverlaps::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (CachedOverlaps::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (CachedOverlaps::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (CachedOverlaps::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/DestructibleActorChunks.h b/APEX_1.4/module/destructible/include/autogen/DestructibleActorChunks.h new file mode 100644 index 00000000..893224e9 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/DestructibleActorChunks.h @@ -0,0 +1,253 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_DestructibleActorChunks_h +#define HEADER_DestructibleActorChunks_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace DestructibleActorChunksNS +{ + +struct Chunk_Type; + +struct Chunk_DynamicArray1D_Type +{ + Chunk_Type* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct Chunk_Type +{ + uint8_t state; + uint8_t flags; + uint32_t islandID; + float damage; + physx::PxVec4 localSphere; + physx::PxVec3 localOffset; + int32_t visibleAncestorIndex; + uint32_t shapesCount; + physx::PxTransform globalPose; + physx::PxVec3 linearVelocity; + physx::PxVec3 angularVelocity; +}; + +struct ParametersStruct +{ + + Chunk_DynamicArray1D_Type data; + +}; + +static const uint32_t checksum[] = { 0x1f4e04ad, 0x95dc5558, 0x4dae15a1, 0x46caf98e, }; + +} // namespace DestructibleActorChunksNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class DestructibleActorChunks : public NvParameterized::NvParameters, public DestructibleActorChunksNS::ParametersStruct +{ +public: + DestructibleActorChunks(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~DestructibleActorChunks(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("DestructibleActorChunks"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)0; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(DestructibleActorChunksNS::checksum); + return DestructibleActorChunksNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const DestructibleActorChunksNS::ParametersStruct& parameters(void) const + { + DestructibleActorChunks* tmpThis = const_cast<DestructibleActorChunks*>(this); + return *(static_cast<DestructibleActorChunksNS::ParametersStruct*>(tmpThis)); + } + + DestructibleActorChunksNS::ParametersStruct& parameters(void) + { + return *(static_cast<DestructibleActorChunksNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class DestructibleActorChunksFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + DestructibleActorChunks::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(DestructibleActorChunks), DestructibleActorChunks::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, DestructibleActorChunks::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleActorChunks"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(DestructibleActorChunks)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, DestructibleActorChunks)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, DestructibleActorChunks::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, DestructibleActorChunks::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleActorChunks"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of DestructibleActorChunks here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (DestructibleActorChunks*)bufObj; + } + + virtual const char* getClassName() + { + return (DestructibleActorChunks::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (DestructibleActorChunks::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (DestructibleActorChunks::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (DestructibleActorChunks::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/DestructibleActorParam.h b/APEX_1.4/module/destructible/include/autogen/DestructibleActorParam.h new file mode 100644 index 00000000..9fb50b5c --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/DestructibleActorParam.h @@ -0,0 +1,606 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_DestructibleActorParam_h +#define HEADER_DestructibleActorParam_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace DestructibleActorParamNS +{ + +struct GroupsMask_Type; +struct ShapeDescFlags_Type; +struct ShapeDescTemplate_Type; +struct ContactPairFlag_Type; +struct ActorDescFlags_Type; +struct ActorDescTemplate_Type; +struct BodyDescFlags_Type; +struct BodyDescTemplate_Type; +struct DestructibleDepthParameters_Type; +struct DestructibleParametersFlag_Type; +struct FractureGlass_Type; +struct FractureVoronoi_Type; +struct FractureAttachment_Type; +struct RuntimeFracture_Type; +struct DestructibleParameters_Type; +struct DamageSpreadFunction_Type; +struct P3FilterData_Type; +struct P3ShapeFlags_Type; +struct P3PairFlag_Type; +struct P3ShapeDescTemplate_Type; +struct P3ActorFlags_Type; +struct P3ActorDescTemplate_Type; +struct P3BodyDescFlags_Type; +struct P3BodyDescTemplate_Type; +struct StructureSettings_Type; +struct BehaviorGroup_Type; + +struct STRING_DynamicArray1D_Type +{ + NvParameterized::DummyStringStruct* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct DestructibleDepthParameters_DynamicArray1D_Type +{ + DestructibleDepthParameters_Type* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct BehaviorGroup_DynamicArray1D_Type +{ + BehaviorGroup_Type* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct DestructibleDepthParameters_Type +{ + bool OVERRIDE_IMPACT_DAMAGE; + bool OVERRIDE_IMPACT_DAMAGE_VALUE; + bool IGNORE_POSE_UPDATES; + bool IGNORE_RAYCAST_CALLBACKS; + bool IGNORE_CONTACT_CALLBACKS; + bool USER_FLAG_0; + bool USER_FLAG_1; + bool USER_FLAG_2; + bool USER_FLAG_3; +}; +struct P3BodyDescFlags_Type +{ + bool eKINEMATIC; + bool eENABLE_CCD; +}; +struct GroupsMask_Type +{ + bool useGroupsMask; + uint32_t bits0; + uint32_t bits1; + uint32_t bits2; + uint32_t bits3; +}; +struct DestructibleParametersFlag_Type +{ + bool ACCUMULATE_DAMAGE; + bool DEBRIS_TIMEOUT; + bool DEBRIS_MAX_SEPARATION; + bool CRUMBLE_SMALLEST_CHUNKS; + bool ACCURATE_RAYCASTS; + bool USE_VALID_BOUNDS; + bool CRUMBLE_VIA_RUNTIME_FRACTURE; +}; +struct ShapeDescFlags_Type +{ + bool NX_TRIGGER_ON_ENTER; + bool NX_TRIGGER_ON_LEAVE; + bool NX_TRIGGER_ON_STAY; + bool NX_SF_VISUALIZATION; + bool NX_SF_DISABLE_COLLISION; + bool NX_SF_FEATURE_INDICES; + bool NX_SF_DISABLE_RAYCASTING; + bool NX_SF_POINT_CONTACT_FORCE; + bool NX_SF_FLUID_DRAIN; + bool NX_SF_FLUID_DISABLE_COLLISION; + bool NX_SF_FLUID_TWOWAY; + bool NX_SF_DISABLE_RESPONSE; + bool NX_SF_DYNAMIC_DYNAMIC_CCD; + bool NX_SF_DISABLE_SCENE_QUERIES; + bool NX_SF_CLOTH_DRAIN; + bool NX_SF_CLOTH_DISABLE_COLLISION; + bool NX_SF_CLOTH_TWOWAY; + bool NX_SF_SOFTBODY_DRAIN; + bool NX_SF_SOFTBODY_DISABLE_COLLISION; + bool NX_SF_SOFTBODY_TWOWAY; +}; +struct ShapeDescTemplate_Type +{ + ShapeDescFlags_Type flags; + uint16_t collisionGroup; + GroupsMask_Type groupsMask; + uint16_t materialIndex; + float density; + float skinWidth; + uint64_t userData; + uint64_t name; +}; +struct P3FilterData_Type +{ + uint32_t word0; + uint32_t word1; + uint32_t word2; + uint32_t word3; +}; +struct StructureSettings_Type +{ + bool useStressSolver; + float stressSolverTimeDelay; + float stressSolverMassThreshold; +}; +struct FractureGlass_Type +{ + uint32_t numSectors; + float sectorRand; + float firstSegmentSize; + float segmentScale; + float segmentRand; +}; +struct DamageSpreadFunction_Type +{ + float minimumRadius; + float radiusMultiplier; + float falloffExponent; +}; +struct FractureVoronoi_Type +{ + physx::PxVec3 dimensions; + uint32_t numCells; + float biasExp; + float maxDist; +}; +struct BehaviorGroup_Type +{ + NvParameterized::DummyStringStruct name; + float damageThreshold; + float damageToRadius; + DamageSpreadFunction_Type damageSpread; + DamageSpreadFunction_Type damageColorSpread; + physx::PxVec4 damageColorChange; + float materialStrength; + float density; + float fadeOut; + float maxDepenetrationVelocity; + GroupsMask_Type groupsMask; + uint64_t userData; +}; +struct P3ShapeFlags_Type +{ + bool eSIMULATION_SHAPE; + bool eSCENE_QUERY_SHAPE; + bool eTRIGGER_SHAPE; + bool eVISUALIZATION; + bool ePARTICLE_DRAIN; + bool eDEFORMABLE_DRAIN; +}; +struct P3ShapeDescTemplate_Type +{ + P3ShapeFlags_Type flags; + P3FilterData_Type simulationFilterData; + P3FilterData_Type queryFilterData; + uint64_t material; + float contactOffset; + float restOffset; + uint64_t userData; + uint64_t name; +}; +struct P3ActorFlags_Type +{ + bool eVISUALIZATION; + bool eDISABLE_GRAVITY; + bool eSEND_SLEEP_NOTIFIES; +}; +struct P3BodyDescTemplate_Type +{ + float density; + P3BodyDescFlags_Type flags; + float sleepThreshold; + float wakeUpCounter; + float linearDamping; + float angularDamping; + float maxAngularVelocity; + uint32_t solverIterationCount; + uint32_t velocityIterationCount; + float contactReportThreshold; + float sleepLinearVelocity; +}; +struct ContactPairFlag_Type +{ + bool NX_IGNORE_PAIR; + bool NX_NOTIFY_ON_START_TOUCH; + bool NX_NOTIFY_ON_END_TOUCH; + bool NX_NOTIFY_ON_TOUCH; + bool NX_NOTIFY_ON_IMPACT; + bool NX_NOTIFY_ON_ROLL; + bool NX_NOTIFY_ON_SLIDE; + bool NX_NOTIFY_FORCES; + bool NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD; + bool NX_NOTIFY_ON_END_TOUCH_FORCE_THRESHOLD; + bool NX_NOTIFY_ON_TOUCH_FORCE_THRESHOLD; + bool NX_NOTIFY_CONTACT_MODIFICATION; +}; +struct BodyDescFlags_Type +{ + bool NX_BF_DISABLE_GRAVITY; + bool NX_BF_FILTER_SLEEP_VEL; + bool NX_BF_ENERGY_SLEEP_TEST; + bool NX_BF_VISUALIZATION; +}; +struct BodyDescTemplate_Type +{ + BodyDescFlags_Type flags; + float wakeUpCounter; + float linearDamping; + float angularDamping; + float maxAngularVelocity; + float CCDMotionThreshold; + float sleepLinearVelocity; + float sleepAngularVelocity; + uint32_t solverIterationCount; + float sleepEnergyThreshold; + float sleepDamping; + float contactReportThreshold; +}; +struct FractureAttachment_Type +{ + bool posX; + bool negX; + bool posY; + bool negY; + bool posZ; + bool negZ; +}; +struct RuntimeFracture_Type +{ + const char* RuntimeFractureType; + bool sheetFracture; + uint32_t depthLimit; + bool destroyIfAtDepthLimit; + float minConvexSize; + float impulseScale; + FractureGlass_Type glass; + FractureVoronoi_Type voronoi; + FractureAttachment_Type attachment; +}; +struct DestructibleParameters_Type +{ + float damageCap; + float forceToDamage; + float impactVelocityThreshold; + uint32_t minimumFractureDepth; + int32_t impactDamageDefaultDepth; + int32_t debrisDepth; + uint32_t essentialDepth; + float debrisLifetimeMin; + float debrisLifetimeMax; + float debrisMaxSeparationMin; + float debrisMaxSeparationMax; + float debrisDestructionProbability; + physx::PxBounds3 validBounds; + float maxChunkSpeed; + DestructibleParametersFlag_Type flags; + float fractureImpulseScale; + uint16_t damageDepthLimit; + uint16_t dynamicChunkDominanceGroup; + GroupsMask_Type dynamicChunksGroupsMask; + RuntimeFracture_Type runtimeFracture; + float supportStrength; + int8_t legacyChunkBoundsTestSetting; + int8_t legacyDamageRadiusSpreadSetting; + bool alwaysDrawScatterMesh; +}; +struct ActorDescFlags_Type +{ + bool NX_AF_DISABLE_COLLISION; + bool NX_AF_DISABLE_RESPONSE; + bool NX_AF_LOCK_COM; + bool NX_AF_FLUID_DISABLE_COLLISION; + bool NX_AF_CONTACT_MODIFICATION; + bool NX_AF_FORCE_CONE_FRICTION; + bool NX_AF_USER_ACTOR_PAIR_FILTERING; +}; +struct ActorDescTemplate_Type +{ + ActorDescFlags_Type flags; + float density; + uint16_t actorCollisionGroup; + uint16_t dominanceGroup; + ContactPairFlag_Type contactReportFlags; + uint16_t forceFieldMaterial; + uint64_t userData; + uint64_t name; + uint64_t compartment; +}; +struct P3PairFlag_Type +{ + bool eSOLVE_CONTACT; + bool eMODIFY_CONTACTS; + bool eNOTIFY_TOUCH_FOUND; + bool eNOTIFY_TOUCH_PERSISTS; + bool eNOTIFY_TOUCH_LOST; + bool eNOTIFY_THRESHOLD_FORCE_FOUND; + bool eNOTIFY_THRESHOLD_FORCE_PERSISTS; + bool eNOTIFY_THRESHOLD_FORCE_LOST; + bool eNOTIFY_CONTACT_POINTS; + bool eNOTIFY_CONTACT_FORCES; + bool eNOTIFY_CONTACT_FORCE_PER_POINT; + bool eNOTIFY_CONTACT_FEATURE_INDICES_PER_POINT; + bool eDETECT_CCD_CONTACT; + bool eCONTACT_DEFAULT; + bool eTRIGGER_DEFAULT; +}; +struct P3ActorDescTemplate_Type +{ + P3ActorFlags_Type flags; + uint8_t dominanceGroup; + uint8_t ownerClient; + uint32_t clientBehaviorBits; + P3PairFlag_Type contactReportFlags; + uint64_t userData; + uint64_t name; +}; + +struct ParametersStruct +{ + + NvParameterized::DummyStringStruct crumbleEmitterName; + float crumbleParticleSpacing; + NvParameterized::DummyStringStruct dustEmitterName; + float dustParticleSpacing; + physx::PxTransform globalPose; + physx::PxVec3 scale; + bool dynamic; + uint32_t supportDepth; + bool formExtendedStructures; + bool performDetailedOverlapTestForExtendedStructures; + bool keepPreviousFrameBoneBuffer; + bool doNotCreateRenderable; + bool useAssetDefinedSupport; + bool useWorldSupport; + bool renderStaticChunksSeparately; + bool keepVisibleBonesPacked; + bool createChunkEvents; + STRING_DynamicArray1D_Type overrideSkinnedMaterialNames; + STRING_DynamicArray1D_Type overrideStaticMaterialNames; + float sleepVelocityFrameDecayConstant; + bool useHardSleeping; + DestructibleParameters_Type destructibleParameters; + DestructibleDepthParameters_DynamicArray1D_Type depthParameters; + ShapeDescTemplate_Type shapeDescTemplate; + ActorDescTemplate_Type actorDescTemplate; + BodyDescTemplate_Type bodyDescTemplate; + P3ShapeDescTemplate_Type p3ShapeDescTemplate; + P3ActorDescTemplate_Type p3ActorDescTemplate; + P3BodyDescTemplate_Type p3BodyDescTemplate; + StructureSettings_Type structureSettings; + BehaviorGroup_Type defaultBehaviorGroup; + BehaviorGroup_DynamicArray1D_Type behaviorGroups; + bool deleteChunksLeavingUserDefinedBB; + bool deleteChunksEnteringUserDefinedBB; + +}; + +static const uint32_t checksum[] = { 0x2f148a8b, 0x0ef80948, 0x34293f31, 0x363a5ff0, }; + +} // namespace DestructibleActorParamNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class DestructibleActorParam : public NvParameterized::NvParameters, public DestructibleActorParamNS::ParametersStruct +{ +public: + DestructibleActorParam(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~DestructibleActorParam(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("DestructibleActorParam"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)32; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(DestructibleActorParamNS::checksum); + return DestructibleActorParamNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const DestructibleActorParamNS::ParametersStruct& parameters(void) const + { + DestructibleActorParam* tmpThis = const_cast<DestructibleActorParam*>(this); + return *(static_cast<DestructibleActorParamNS::ParametersStruct*>(tmpThis)); + } + + DestructibleActorParamNS::ParametersStruct& parameters(void) + { + return *(static_cast<DestructibleActorParamNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class DestructibleActorParamFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + DestructibleActorParam::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(DestructibleActorParam), DestructibleActorParam::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, DestructibleActorParam::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleActorParam"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(DestructibleActorParam)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, DestructibleActorParam)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, DestructibleActorParam::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, DestructibleActorParam::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleActorParam"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of DestructibleActorParam here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (DestructibleActorParam*)bufObj; + } + + virtual const char* getClassName() + { + return (DestructibleActorParam::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (DestructibleActorParam::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (DestructibleActorParam::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (DestructibleActorParam::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/DestructibleActorState.h b/APEX_1.4/module/destructible/include/autogen/DestructibleActorState.h new file mode 100644 index 00000000..066a881f --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/DestructibleActorState.h @@ -0,0 +1,445 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_DestructibleActorState_h +#define HEADER_DestructibleActorState_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace DestructibleActorStateNS +{ + +struct GroupsMask_Type; +struct ShapeDescFlags_Type; +struct ShapeDescTemplate_Type; +struct ContactPairFlag_Type; +struct ActorDescFlags_Type; +struct ActorDescTemplate_Type; +struct BodyDescFlags_Type; +struct BodyDescTemplate_Type; +struct DestructibleDepthParameters_Type; +struct DestructibleParametersFlag_Type; +struct FractureGlass_Type; +struct FractureVoronoi_Type; +struct FractureAttachment_Type; +struct RuntimeFracture_Type; +struct DestructibleParameters_Type; +struct DamageSpreadFunction_Type; + +struct DestructibleDepthParameters_Type +{ + bool OVERRIDE_IMPACT_DAMAGE; + bool OVERRIDE_IMPACT_DAMAGE_VALUE; + bool IGNORE_POSE_UPDATES; + bool IGNORE_RAYCAST_CALLBACKS; + bool IGNORE_CONTACT_CALLBACKS; + bool USER_FLAG_0; + bool USER_FLAG_1; + bool USER_FLAG_2; + bool USER_FLAG_3; +}; +struct GroupsMask_Type +{ + bool useGroupsMask; + uint32_t bits0; + uint32_t bits1; + uint32_t bits2; + uint32_t bits3; +}; +struct DestructibleParametersFlag_Type +{ + bool ACCUMULATE_DAMAGE; + bool DEBRIS_TIMEOUT; + bool DEBRIS_MAX_SEPARATION; + bool CRUMBLE_SMALLEST_CHUNKS; + bool ACCURATE_RAYCASTS; + bool USE_VALID_BOUNDS; + bool CRUMBLE_VIA_RUNTIME_FRACTURE; +}; +struct ShapeDescFlags_Type +{ + bool NX_TRIGGER_ON_ENTER; + bool NX_TRIGGER_ON_LEAVE; + bool NX_TRIGGER_ON_STAY; + bool NX_SF_VISUALIZATION; + bool NX_SF_DISABLE_COLLISION; + bool NX_SF_FEATURE_INDICES; + bool NX_SF_DISABLE_RAYCASTING; + bool NX_SF_POINT_CONTACT_FORCE; + bool NX_SF_FLUID_DRAIN; + bool NX_SF_FLUID_DISABLE_COLLISION; + bool NX_SF_FLUID_TWOWAY; + bool NX_SF_DISABLE_RESPONSE; + bool NX_SF_DYNAMIC_DYNAMIC_CCD; + bool NX_SF_DISABLE_SCENE_QUERIES; + bool NX_SF_CLOTH_DRAIN; + bool NX_SF_CLOTH_DISABLE_COLLISION; + bool NX_SF_CLOTH_TWOWAY; + bool NX_SF_SOFTBODY_DRAIN; + bool NX_SF_SOFTBODY_DISABLE_COLLISION; + bool NX_SF_SOFTBODY_TWOWAY; +}; +struct ShapeDescTemplate_Type +{ + ShapeDescFlags_Type flags; + uint16_t collisionGroup; + GroupsMask_Type groupsMask; + uint16_t materialIndex; + float density; + float skinWidth; + uint64_t userData; + uint64_t name; +}; +struct FractureGlass_Type +{ + uint32_t numSectors; + float sectorRand; + float firstSegmentSize; + float segmentScale; + float segmentRand; +}; +struct DamageSpreadFunction_Type +{ + float minimumRadius; + float radiusMultiplier; + float falloffExponent; +}; +struct FractureVoronoi_Type +{ + physx::PxVec3 dimensions; + uint32_t numCells; + float biasExp; + float maxDist; +}; +struct ContactPairFlag_Type +{ + bool NX_IGNORE_PAIR; + bool NX_NOTIFY_ON_START_TOUCH; + bool NX_NOTIFY_ON_END_TOUCH; + bool NX_NOTIFY_ON_TOUCH; + bool NX_NOTIFY_ON_IMPACT; + bool NX_NOTIFY_ON_ROLL; + bool NX_NOTIFY_ON_SLIDE; + bool NX_NOTIFY_FORCES; + bool NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD; + bool NX_NOTIFY_ON_END_TOUCH_FORCE_THRESHOLD; + bool NX_NOTIFY_ON_TOUCH_FORCE_THRESHOLD; + bool NX_NOTIFY_CONTACT_MODIFICATION; +}; +struct BodyDescFlags_Type +{ + bool NX_BF_DISABLE_GRAVITY; + bool NX_BF_FILTER_SLEEP_VEL; + bool NX_BF_ENERGY_SLEEP_TEST; + bool NX_BF_VISUALIZATION; +}; +struct BodyDescTemplate_Type +{ + BodyDescFlags_Type flags; + float wakeUpCounter; + float linearDamping; + float angularDamping; + float maxAngularVelocity; + float CCDMotionThreshold; + float sleepLinearVelocity; + float sleepAngularVelocity; + uint32_t solverIterationCount; + float sleepEnergyThreshold; + float sleepDamping; + float contactReportThreshold; +}; +struct FractureAttachment_Type +{ + bool posX; + bool negX; + bool posY; + bool negY; + bool posZ; + bool negZ; +}; +struct RuntimeFracture_Type +{ + const char* RuntimeFractureType; + bool sheetFracture; + uint32_t depthLimit; + bool destroyIfAtDepthLimit; + float minConvexSize; + float impulseScale; + FractureGlass_Type glass; + FractureVoronoi_Type voronoi; + FractureAttachment_Type attachment; +}; +struct DestructibleParameters_Type +{ + float damageCap; + float forceToDamage; + float impactVelocityThreshold; + uint32_t minimumFractureDepth; + int32_t impactDamageDefaultDepth; + int32_t debrisDepth; + uint32_t essentialDepth; + float debrisLifetimeMin; + float debrisLifetimeMax; + float debrisMaxSeparationMin; + float debrisMaxSeparationMax; + float debrisDestructionProbability; + physx::PxBounds3 validBounds; + float maxChunkSpeed; + DestructibleParametersFlag_Type flags; + float fractureImpulseScale; + uint16_t damageDepthLimit; + uint16_t dynamicChunkDominanceGroup; + GroupsMask_Type dynamicChunksGroupsMask; + RuntimeFracture_Type runtimeFracture; + float supportStrength; + int8_t legacyChunkBoundsTestSetting; + int8_t legacyDamageRadiusSpreadSetting; + bool alwaysDrawScatterMesh; +}; +struct ActorDescFlags_Type +{ + bool NX_AF_DISABLE_COLLISION; + bool NX_AF_DISABLE_RESPONSE; + bool NX_AF_LOCK_COM; + bool NX_AF_FLUID_DISABLE_COLLISION; + bool NX_AF_CONTACT_MODIFICATION; + bool NX_AF_FORCE_CONE_FRICTION; + bool NX_AF_USER_ACTOR_PAIR_FILTERING; +}; +struct ActorDescTemplate_Type +{ + ActorDescFlags_Type flags; + float density; + uint16_t actorCollisionGroup; + uint16_t dominanceGroup; + ContactPairFlag_Type contactReportFlags; + uint16_t forceFieldMaterial; + uint64_t userData; + uint64_t name; + uint64_t compartment; +}; + +struct ParametersStruct +{ + + bool enableCrumbleEmitter; + bool enableDustEmitter; + uint32_t lod; + bool forceLod; + DestructibleParameters_Type destructibleParameters; + uint64_t userData; + NvParameterized::Interface* actorParameters; + NvParameterized::Interface* actorChunks; + +}; + +static const uint32_t checksum[] = { 0xc6984ee8, 0x0dae2202, 0x4f638ad1, 0x24536329, }; + +} // namespace DestructibleActorStateNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class DestructibleActorState : public NvParameterized::NvParameters, public DestructibleActorStateNS::ParametersStruct +{ +public: + DestructibleActorState(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~DestructibleActorState(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("DestructibleActorState"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)4; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(DestructibleActorStateNS::checksum); + return DestructibleActorStateNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const DestructibleActorStateNS::ParametersStruct& parameters(void) const + { + DestructibleActorState* tmpThis = const_cast<DestructibleActorState*>(this); + return *(static_cast<DestructibleActorStateNS::ParametersStruct*>(tmpThis)); + } + + DestructibleActorStateNS::ParametersStruct& parameters(void) + { + return *(static_cast<DestructibleActorStateNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class DestructibleActorStateFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + DestructibleActorState::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(DestructibleActorState), DestructibleActorState::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, DestructibleActorState::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleActorState"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(DestructibleActorState)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, DestructibleActorState)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, DestructibleActorState::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, DestructibleActorState::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleActorState"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of DestructibleActorState here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (DestructibleActorState*)bufObj; + } + + virtual const char* getClassName() + { + return (DestructibleActorState::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (DestructibleActorState::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (DestructibleActorState::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (DestructibleActorState::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/DestructibleAssetCollisionDataSet.h b/APEX_1.4/module/destructible/include/autogen/DestructibleAssetCollisionDataSet.h new file mode 100644 index 00000000..ea14b856 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/DestructibleAssetCollisionDataSet.h @@ -0,0 +1,250 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_DestructibleAssetCollisionDataSet_h +#define HEADER_DestructibleAssetCollisionDataSet_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace DestructibleAssetCollisionDataSetNS +{ + + +struct VEC3_DynamicArray1D_Type +{ + physx::PxVec3* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct REF_DynamicArray1D_Type +{ + NvParameterized::Interface** buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + + +struct ParametersStruct +{ + + NvParameterized::DummyStringStruct assetName; + uint32_t cookingPlatform; + uint32_t cookingVersionNum; + VEC3_DynamicArray1D_Type scales; + REF_DynamicArray1D_Type meshCookedCollisionStreamsAtScale; + +}; + +static const uint32_t checksum[] = { 0x716db49d, 0xccc81ef4, 0x85f3752e, 0x9cf18dc6, }; + +} // namespace DestructibleAssetCollisionDataSetNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class DestructibleAssetCollisionDataSet : public NvParameterized::NvParameters, public DestructibleAssetCollisionDataSetNS::ParametersStruct +{ +public: + DestructibleAssetCollisionDataSet(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~DestructibleAssetCollisionDataSet(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("DestructibleAssetCollisionDataSet"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)0; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(DestructibleAssetCollisionDataSetNS::checksum); + return DestructibleAssetCollisionDataSetNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const DestructibleAssetCollisionDataSetNS::ParametersStruct& parameters(void) const + { + DestructibleAssetCollisionDataSet* tmpThis = const_cast<DestructibleAssetCollisionDataSet*>(this); + return *(static_cast<DestructibleAssetCollisionDataSetNS::ParametersStruct*>(tmpThis)); + } + + DestructibleAssetCollisionDataSetNS::ParametersStruct& parameters(void) + { + return *(static_cast<DestructibleAssetCollisionDataSetNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class DestructibleAssetCollisionDataSetFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + DestructibleAssetCollisionDataSet::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(DestructibleAssetCollisionDataSet), DestructibleAssetCollisionDataSet::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, DestructibleAssetCollisionDataSet::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleAssetCollisionDataSet"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(DestructibleAssetCollisionDataSet)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, DestructibleAssetCollisionDataSet)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, DestructibleAssetCollisionDataSet::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, DestructibleAssetCollisionDataSet::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleAssetCollisionDataSet"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of DestructibleAssetCollisionDataSet here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (DestructibleAssetCollisionDataSet*)bufObj; + } + + virtual const char* getClassName() + { + return (DestructibleAssetCollisionDataSet::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (DestructibleAssetCollisionDataSet::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (DestructibleAssetCollisionDataSet::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (DestructibleAssetCollisionDataSet::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/DestructibleAssetParameters.h b/APEX_1.4/module/destructible/include/autogen/DestructibleAssetParameters.h new file mode 100644 index 00000000..5dfd8d79 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/DestructibleAssetParameters.h @@ -0,0 +1,675 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_DestructibleAssetParameters_h +#define HEADER_DestructibleAssetParameters_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace DestructibleAssetParametersNS +{ + +struct GroupsMask_Type; +struct ShapeDescFlags_Type; +struct ShapeDescTemplate_Type; +struct ContactPairFlag_Type; +struct ActorDescFlags_Type; +struct ActorDescTemplate_Type; +struct BodyDescFlags_Type; +struct BodyDescTemplate_Type; +struct DestructibleDepthParameters_Type; +struct DestructibleParametersFlag_Type; +struct FractureGlass_Type; +struct FractureVoronoi_Type; +struct FractureAttachment_Type; +struct RuntimeFracture_Type; +struct DestructibleParameters_Type; +struct DamageSpreadFunction_Type; +struct BufferFormat_Type; +struct U8x2_Type; +struct U8x3_Type; +struct U8x4_Type; +struct U16x2_Type; +struct U16x3_Type; +struct U16x4_Type; +struct U32x2_Type; +struct U32x3_Type; +struct U32x4_Type; +struct F32x2_Type; +struct F32x3_Type; +struct F32x4_Type; +struct Plane_Type; +struct BehaviorGroup_Type; +struct Chunk_Type; +struct InstanceInfo_Type; + +struct BehaviorGroup_DynamicArray1D_Type +{ + BehaviorGroup_Type* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct Chunk_DynamicArray1D_Type +{ + Chunk_Type* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct REF_DynamicArray1D_Type +{ + NvParameterized::Interface** buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct U32_DynamicArray1D_Type +{ + uint32_t* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct DestructibleDepthParameters_DynamicArray1D_Type +{ + DestructibleDepthParameters_Type* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct InstanceInfo_DynamicArray1D_Type +{ + InstanceInfo_Type* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct STRING_DynamicArray1D_Type +{ + NvParameterized::DummyStringStruct* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct MAT44_DynamicArray1D_Type +{ + physx::PxMat44* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct U8_DynamicArray1D_Type +{ + uint8_t* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct F32x3_Type +{ + float x; + float y; + float z; +}; +struct U32x2_Type +{ + uint32_t x; + uint32_t y; +}; +struct DestructibleParametersFlag_Type +{ + bool ACCUMULATE_DAMAGE; + bool DEBRIS_TIMEOUT; + bool DEBRIS_MAX_SEPARATION; + bool CRUMBLE_SMALLEST_CHUNKS; + bool ACCURATE_RAYCASTS; + bool USE_VALID_BOUNDS; + bool CRUMBLE_VIA_RUNTIME_FRACTURE; +}; +struct U32x4_Type +{ + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t w; +}; +struct ShapeDescFlags_Type +{ + bool NX_TRIGGER_ON_ENTER; + bool NX_TRIGGER_ON_LEAVE; + bool NX_TRIGGER_ON_STAY; + bool NX_SF_VISUALIZATION; + bool NX_SF_DISABLE_COLLISION; + bool NX_SF_FEATURE_INDICES; + bool NX_SF_DISABLE_RAYCASTING; + bool NX_SF_POINT_CONTACT_FORCE; + bool NX_SF_FLUID_DRAIN; + bool NX_SF_FLUID_DISABLE_COLLISION; + bool NX_SF_FLUID_TWOWAY; + bool NX_SF_DISABLE_RESPONSE; + bool NX_SF_DYNAMIC_DYNAMIC_CCD; + bool NX_SF_DISABLE_SCENE_QUERIES; + bool NX_SF_CLOTH_DRAIN; + bool NX_SF_CLOTH_DISABLE_COLLISION; + bool NX_SF_CLOTH_TWOWAY; + bool NX_SF_SOFTBODY_DRAIN; + bool NX_SF_SOFTBODY_DISABLE_COLLISION; + bool NX_SF_SOFTBODY_TWOWAY; +}; +struct F32x2_Type +{ + float x; + float y; +}; +struct InstanceInfo_Type +{ + uint16_t partIndex; + physx::PxVec3 chunkPositionOffset; + physx::PxVec2 chunkUVOffset; +}; +struct Plane_Type +{ + physx::PxVec3 normal; + float d; +}; +struct U16x2_Type +{ + uint16_t x; + uint16_t y; +}; +struct U8x2_Type +{ + uint8_t x; + uint8_t y; +}; +struct DamageSpreadFunction_Type +{ + float minimumRadius; + float radiusMultiplier; + float falloffExponent; +}; +struct FractureVoronoi_Type +{ + physx::PxVec3 dimensions; + uint32_t numCells; + float biasExp; + float maxDist; +}; +struct U8x3_Type +{ + uint8_t x; + uint8_t y; + uint8_t z; +}; +struct ContactPairFlag_Type +{ + bool NX_IGNORE_PAIR; + bool NX_NOTIFY_ON_START_TOUCH; + bool NX_NOTIFY_ON_END_TOUCH; + bool NX_NOTIFY_ON_TOUCH; + bool NX_NOTIFY_ON_IMPACT; + bool NX_NOTIFY_ON_ROLL; + bool NX_NOTIFY_ON_SLIDE; + bool NX_NOTIFY_FORCES; + bool NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD; + bool NX_NOTIFY_ON_END_TOUCH_FORCE_THRESHOLD; + bool NX_NOTIFY_ON_TOUCH_FORCE_THRESHOLD; + bool NX_NOTIFY_CONTACT_MODIFICATION; +}; +struct BodyDescFlags_Type +{ + bool NX_BF_DISABLE_GRAVITY; + bool NX_BF_FILTER_SLEEP_VEL; + bool NX_BF_ENERGY_SLEEP_TEST; + bool NX_BF_VISUALIZATION; +}; +struct BufferFormat_Type +{ + NvParameterized::DummyStringStruct name; + int32_t semantic; + uint32_t id; + uint32_t format; + uint32_t access; + bool serialize; +}; +struct FractureAttachment_Type +{ + bool posX; + bool negX; + bool posY; + bool negY; + bool posZ; + bool negZ; +}; +struct Chunk_Type +{ + uint16_t depth; + uint16_t parentIndex; + uint16_t firstChildIndex; + uint16_t numChildren; + uint16_t meshPartIndex; + uint16_t flags; + physx::PxVec3 surfaceNormal; + int8_t behaviorGroupIndex; + uint16_t firstScatterMesh; + uint16_t scatterMeshCount; +}; +struct DestructibleDepthParameters_Type +{ + bool OVERRIDE_IMPACT_DAMAGE; + bool OVERRIDE_IMPACT_DAMAGE_VALUE; + bool IGNORE_POSE_UPDATES; + bool IGNORE_RAYCAST_CALLBACKS; + bool IGNORE_CONTACT_CALLBACKS; + bool USER_FLAG_0; + bool USER_FLAG_1; + bool USER_FLAG_2; + bool USER_FLAG_3; +}; +struct U16x4_Type +{ + uint16_t x; + uint16_t y; + uint16_t z; + uint16_t w; +}; +struct GroupsMask_Type +{ + bool useGroupsMask; + uint32_t bits0; + uint32_t bits1; + uint32_t bits2; + uint32_t bits3; +}; +struct ShapeDescTemplate_Type +{ + ShapeDescFlags_Type flags; + uint16_t collisionGroup; + GroupsMask_Type groupsMask; + uint16_t materialIndex; + float density; + float skinWidth; + uint64_t userData; + uint64_t name; +}; +struct BodyDescTemplate_Type +{ + BodyDescFlags_Type flags; + float wakeUpCounter; + float linearDamping; + float angularDamping; + float maxAngularVelocity; + float CCDMotionThreshold; + float sleepLinearVelocity; + float sleepAngularVelocity; + uint32_t solverIterationCount; + float sleepEnergyThreshold; + float sleepDamping; + float contactReportThreshold; +}; +struct U32x3_Type +{ + uint32_t x; + uint32_t y; + uint32_t z; +}; +struct U16x3_Type +{ + uint16_t x; + uint16_t y; + uint16_t z; +}; +struct F32x4_Type +{ + PX_ALIGN(16, float x); + float y; + float z; + float w; +}; +struct FractureGlass_Type +{ + uint32_t numSectors; + float sectorRand; + float firstSegmentSize; + float segmentScale; + float segmentRand; +}; +struct RuntimeFracture_Type +{ + const char* RuntimeFractureType; + bool sheetFracture; + uint32_t depthLimit; + bool destroyIfAtDepthLimit; + float minConvexSize; + float impulseScale; + FractureGlass_Type glass; + FractureVoronoi_Type voronoi; + FractureAttachment_Type attachment; +}; +struct DestructibleParameters_Type +{ + float damageCap; + float forceToDamage; + float impactVelocityThreshold; + uint32_t minimumFractureDepth; + int32_t impactDamageDefaultDepth; + int32_t debrisDepth; + uint32_t essentialDepth; + float debrisLifetimeMin; + float debrisLifetimeMax; + float debrisMaxSeparationMin; + float debrisMaxSeparationMax; + float debrisDestructionProbability; + physx::PxBounds3 validBounds; + float maxChunkSpeed; + DestructibleParametersFlag_Type flags; + float fractureImpulseScale; + uint16_t damageDepthLimit; + uint16_t dynamicChunkDominanceGroup; + GroupsMask_Type dynamicChunksGroupsMask; + RuntimeFracture_Type runtimeFracture; + float supportStrength; + int8_t legacyChunkBoundsTestSetting; + int8_t legacyDamageRadiusSpreadSetting; + bool alwaysDrawScatterMesh; +}; +struct BehaviorGroup_Type +{ + NvParameterized::DummyStringStruct name; + float damageThreshold; + float damageToRadius; + DamageSpreadFunction_Type damageSpread; + DamageSpreadFunction_Type damageColorSpread; + physx::PxVec4 damageColorChange; + float materialStrength; + float density; + float fadeOut; + float maxDepenetrationVelocity; + uint64_t userData; +}; +struct U8x4_Type +{ + uint8_t x; + uint8_t y; + uint8_t z; + uint8_t w; +}; +struct ActorDescFlags_Type +{ + bool NX_AF_DISABLE_COLLISION; + bool NX_AF_DISABLE_RESPONSE; + bool NX_AF_LOCK_COM; + bool NX_AF_FLUID_DISABLE_COLLISION; + bool NX_AF_CONTACT_MODIFICATION; + bool NX_AF_FORCE_CONE_FRICTION; + bool NX_AF_USER_ACTOR_PAIR_FILTERING; +}; +struct ActorDescTemplate_Type +{ + ActorDescFlags_Type flags; + float density; + uint16_t actorCollisionGroup; + uint16_t dominanceGroup; + ContactPairFlag_Type contactReportFlags; + uint16_t forceFieldMaterial; + uint64_t userData; + uint64_t name; + uint64_t compartment; +}; + +struct ParametersStruct +{ + + NvParameterized::DummyStringStruct comments; + uint32_t depthCount; + uint32_t originalDepthCount; + physx::PxBounds3 bounds; + BehaviorGroup_Type defaultBehaviorGroup; + BehaviorGroup_DynamicArray1D_Type behaviorGroups; + int8_t RTFractureBehaviorGroup; + Chunk_DynamicArray1D_Type chunks; + REF_DynamicArray1D_Type chunkConvexHulls; + U32_DynamicArray1D_Type chunkConvexHullStartIndices; + DestructibleParameters_Type destructibleParameters; + DestructibleDepthParameters_DynamicArray1D_Type depthParameters; + NvParameterized::DummyStringStruct crumbleEmitterName; + NvParameterized::DummyStringStruct dustEmitterName; + NvParameterized::Interface* collisionData; + NvParameterized::Interface* renderMeshAsset; + uint32_t initialDestructibleActorAllowanceForInstancing; + InstanceInfo_DynamicArray1D_Type chunkInstanceInfo; + STRING_DynamicArray1D_Type staticMaterialNames; + float neighborPadding; + REF_DynamicArray1D_Type overlapsAtDepth; + U32_DynamicArray1D_Type firstChunkAtDepth; + uint32_t supportDepth; + bool formExtendedStructures; + bool useAssetDefinedSupport; + bool useWorldSupport; + MAT44_DynamicArray1D_Type actorTransforms; + REF_DynamicArray1D_Type scatterMeshAssets; + U8_DynamicArray1D_Type scatterMeshIndices; + MAT44_DynamicArray1D_Type scatterMeshTransforms; + +}; + +static const uint32_t checksum[] = { 0xb0082230, 0x839469d7, 0xd24a9c81, 0xc8df3469, }; + +} // namespace DestructibleAssetParametersNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class DestructibleAssetParameters : public NvParameterized::NvParameters, public DestructibleAssetParametersNS::ParametersStruct +{ +public: + DestructibleAssetParameters(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~DestructibleAssetParameters(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("DestructibleAssetParameters"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)26; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(DestructibleAssetParametersNS::checksum); + return DestructibleAssetParametersNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const DestructibleAssetParametersNS::ParametersStruct& parameters(void) const + { + DestructibleAssetParameters* tmpThis = const_cast<DestructibleAssetParameters*>(this); + return *(static_cast<DestructibleAssetParametersNS::ParametersStruct*>(tmpThis)); + } + + DestructibleAssetParametersNS::ParametersStruct& parameters(void) + { + return *(static_cast<DestructibleAssetParametersNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class DestructibleAssetParametersFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + DestructibleAssetParameters::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(DestructibleAssetParameters), DestructibleAssetParameters::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, DestructibleAssetParameters::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleAssetParameters"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(DestructibleAssetParameters)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, DestructibleAssetParameters)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, DestructibleAssetParameters::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, DestructibleAssetParameters::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleAssetParameters"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of DestructibleAssetParameters here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (DestructibleAssetParameters*)bufObj; + } + + virtual const char* getClassName() + { + return (DestructibleAssetParameters::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (DestructibleAssetParameters::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (DestructibleAssetParameters::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (DestructibleAssetParameters::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/DestructibleDebugRenderParams.h b/APEX_1.4/module/destructible/include/autogen/DestructibleDebugRenderParams.h new file mode 100644 index 00000000..be004876 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/DestructibleDebugRenderParams.h @@ -0,0 +1,238 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_DestructibleDebugRenderParams_h +#define HEADER_DestructibleDebugRenderParams_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace DestructibleDebugRenderParamsNS +{ + + + +struct ParametersStruct +{ + + bool VISUALIZE_DESTRUCTIBLE_ACTOR; + float VISUALIZE_DESTRUCTIBLE_BOUNDS; + float VISUALIZE_DESTRUCTIBLE_SUPPORT; + bool VISUALIZE_DESTRUCTIBLE_ACTOR_POSE; + float THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_POSE; + bool VISUALIZE_DESTRUCTIBLE_ACTOR_NAME; + float THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_NAME; + bool VISUALIZE_DESTRUCTIBLE_FRAGMENT_POSE; + float THRESHOLD_DISTANCE_DESTRUCTIBLE_FRAGMENT_POSE; + +}; + +static const uint32_t checksum[] = { 0xf9b70cc9, 0xc8a5ed52, 0x51f40e6a, 0x14b18d85, }; + +} // namespace DestructibleDebugRenderParamsNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class DestructibleDebugRenderParams : public NvParameterized::NvParameters, public DestructibleDebugRenderParamsNS::ParametersStruct +{ +public: + DestructibleDebugRenderParams(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~DestructibleDebugRenderParams(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("DestructibleDebugRenderParams"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)0; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(DestructibleDebugRenderParamsNS::checksum); + return DestructibleDebugRenderParamsNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const DestructibleDebugRenderParamsNS::ParametersStruct& parameters(void) const + { + DestructibleDebugRenderParams* tmpThis = const_cast<DestructibleDebugRenderParams*>(this); + return *(static_cast<DestructibleDebugRenderParamsNS::ParametersStruct*>(tmpThis)); + } + + DestructibleDebugRenderParamsNS::ParametersStruct& parameters(void) + { + return *(static_cast<DestructibleDebugRenderParamsNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class DestructibleDebugRenderParamsFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + DestructibleDebugRenderParams::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(DestructibleDebugRenderParams), DestructibleDebugRenderParams::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, DestructibleDebugRenderParams::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleDebugRenderParams"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(DestructibleDebugRenderParams)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, DestructibleDebugRenderParams)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, DestructibleDebugRenderParams::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, DestructibleDebugRenderParams::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleDebugRenderParams"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of DestructibleDebugRenderParams here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (DestructibleDebugRenderParams*)bufObj; + } + + virtual const char* getClassName() + { + return (DestructibleDebugRenderParams::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (DestructibleDebugRenderParams::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (DestructibleDebugRenderParams::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (DestructibleDebugRenderParams::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/DestructibleModuleParameters.h b/APEX_1.4/module/destructible/include/autogen/DestructibleModuleParameters.h new file mode 100644 index 00000000..2c4cb1c6 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/DestructibleModuleParameters.h @@ -0,0 +1,237 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_DestructibleModuleParameters_h +#define HEADER_DestructibleModuleParameters_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace DestructibleModuleParametersNS +{ + + + +struct ParametersStruct +{ + + uint32_t maxDynamicChunkIslandCount; + bool sortFIFOByBenefit; + float validBoundsPadding; + float maxChunkSeparationLOD; + uint32_t maxActorCreatesPerFrame; + uint32_t maxChunkDepthOffset; + float massScale; + float scaledMassExponent; + +}; + +static const uint32_t checksum[] = { 0xea4f5a53, 0x75a1901c, 0xd7138e07, 0xef8c1364, }; + +} // namespace DestructibleModuleParametersNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class DestructibleModuleParameters : public NvParameterized::NvParameters, public DestructibleModuleParametersNS::ParametersStruct +{ +public: + DestructibleModuleParameters(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~DestructibleModuleParameters(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("DestructibleModuleParameters"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)3; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(DestructibleModuleParametersNS::checksum); + return DestructibleModuleParametersNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const DestructibleModuleParametersNS::ParametersStruct& parameters(void) const + { + DestructibleModuleParameters* tmpThis = const_cast<DestructibleModuleParameters*>(this); + return *(static_cast<DestructibleModuleParametersNS::ParametersStruct*>(tmpThis)); + } + + DestructibleModuleParametersNS::ParametersStruct& parameters(void) + { + return *(static_cast<DestructibleModuleParametersNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class DestructibleModuleParametersFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + DestructibleModuleParameters::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(DestructibleModuleParameters), DestructibleModuleParameters::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, DestructibleModuleParameters::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleModuleParameters"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(DestructibleModuleParameters)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, DestructibleModuleParameters)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, DestructibleModuleParameters::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, DestructibleModuleParameters::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructibleModuleParameters"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of DestructibleModuleParameters here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (DestructibleModuleParameters*)bufObj; + } + + virtual const char* getClassName() + { + return (DestructibleModuleParameters::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (DestructibleModuleParameters::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (DestructibleModuleParameters::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (DestructibleModuleParameters::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/DestructiblePreviewParam.h b/APEX_1.4/module/destructible/include/autogen/DestructiblePreviewParam.h new file mode 100644 index 00000000..c1f32df8 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/DestructiblePreviewParam.h @@ -0,0 +1,244 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_DestructiblePreviewParam_h +#define HEADER_DestructiblePreviewParam_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace DestructiblePreviewParamNS +{ + + +struct STRING_DynamicArray1D_Type +{ + NvParameterized::DummyStringStruct* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + + +struct ParametersStruct +{ + + physx::PxMat44 globalPose; + uint32_t chunkDepth; + float explodeAmount; + bool renderUnexplodedChunksStatically; + STRING_DynamicArray1D_Type overrideSkinnedMaterialNames; + STRING_DynamicArray1D_Type overrideStaticMaterialNames; + uint64_t userData; + +}; + +static const uint32_t checksum[] = { 0x3637da2c, 0x7fa3add1, 0xf223f0ff, 0x3a06c4b3, }; + +} // namespace DestructiblePreviewParamNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class DestructiblePreviewParam : public NvParameterized::NvParameters, public DestructiblePreviewParamNS::ParametersStruct +{ +public: + DestructiblePreviewParam(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~DestructiblePreviewParam(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("DestructiblePreviewParam"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)0; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(DestructiblePreviewParamNS::checksum); + return DestructiblePreviewParamNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const DestructiblePreviewParamNS::ParametersStruct& parameters(void) const + { + DestructiblePreviewParam* tmpThis = const_cast<DestructiblePreviewParam*>(this); + return *(static_cast<DestructiblePreviewParamNS::ParametersStruct*>(tmpThis)); + } + + DestructiblePreviewParamNS::ParametersStruct& parameters(void) + { + return *(static_cast<DestructiblePreviewParamNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class DestructiblePreviewParamFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + DestructiblePreviewParam::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(DestructiblePreviewParam), DestructiblePreviewParam::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, DestructiblePreviewParam::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructiblePreviewParam"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(DestructiblePreviewParam)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, DestructiblePreviewParam)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, DestructiblePreviewParam::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, DestructiblePreviewParam::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class DestructiblePreviewParam"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of DestructiblePreviewParam here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (DestructiblePreviewParam*)bufObj; + } + + virtual const char* getClassName() + { + return (DestructiblePreviewParam::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (DestructiblePreviewParam::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (DestructiblePreviewParam::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (DestructiblePreviewParam::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/MeshCookedCollisionStream.h b/APEX_1.4/module/destructible/include/autogen/MeshCookedCollisionStream.h new file mode 100644 index 00000000..9cdb5088 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/MeshCookedCollisionStream.h @@ -0,0 +1,238 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_MeshCookedCollisionStream_h +#define HEADER_MeshCookedCollisionStream_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace MeshCookedCollisionStreamNS +{ + + +struct U8_DynamicArray1D_Type +{ + uint8_t* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + + +struct ParametersStruct +{ + + U8_DynamicArray1D_Type bytes; + +}; + +static const uint32_t checksum[] = { 0x10ac85d4, 0x690961af, 0x1dfeb2cb, 0x4494e6fa, }; + +} // namespace MeshCookedCollisionStreamNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class MeshCookedCollisionStream : public NvParameterized::NvParameters, public MeshCookedCollisionStreamNS::ParametersStruct +{ +public: + MeshCookedCollisionStream(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~MeshCookedCollisionStream(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("MeshCookedCollisionStream"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)0; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(MeshCookedCollisionStreamNS::checksum); + return MeshCookedCollisionStreamNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const MeshCookedCollisionStreamNS::ParametersStruct& parameters(void) const + { + MeshCookedCollisionStream* tmpThis = const_cast<MeshCookedCollisionStream*>(this); + return *(static_cast<MeshCookedCollisionStreamNS::ParametersStruct*>(tmpThis)); + } + + MeshCookedCollisionStreamNS::ParametersStruct& parameters(void) + { + return *(static_cast<MeshCookedCollisionStreamNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class MeshCookedCollisionStreamFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + MeshCookedCollisionStream::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(MeshCookedCollisionStream), MeshCookedCollisionStream::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, MeshCookedCollisionStream::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class MeshCookedCollisionStream"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(MeshCookedCollisionStream)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, MeshCookedCollisionStream)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, MeshCookedCollisionStream::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, MeshCookedCollisionStream::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class MeshCookedCollisionStream"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of MeshCookedCollisionStream here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (MeshCookedCollisionStream*)bufObj; + } + + virtual const char* getClassName() + { + return (MeshCookedCollisionStream::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (MeshCookedCollisionStream::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (MeshCookedCollisionStream::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (MeshCookedCollisionStream::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/MeshCookedCollisionStreamsAtScale.h b/APEX_1.4/module/destructible/include/autogen/MeshCookedCollisionStreamsAtScale.h new file mode 100644 index 00000000..3f2565c8 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/MeshCookedCollisionStreamsAtScale.h @@ -0,0 +1,238 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_MeshCookedCollisionStreamsAtScale_h +#define HEADER_MeshCookedCollisionStreamsAtScale_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace MeshCookedCollisionStreamsAtScaleNS +{ + + +struct REF_DynamicArray1D_Type +{ + NvParameterized::Interface** buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + + +struct ParametersStruct +{ + + REF_DynamicArray1D_Type meshCookedCollisionStreams; + +}; + +static const uint32_t checksum[] = { 0xf356e0c1, 0xf4812209, 0x4cf28347, 0xc18b1923, }; + +} // namespace MeshCookedCollisionStreamsAtScaleNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class MeshCookedCollisionStreamsAtScale : public NvParameterized::NvParameters, public MeshCookedCollisionStreamsAtScaleNS::ParametersStruct +{ +public: + MeshCookedCollisionStreamsAtScale(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~MeshCookedCollisionStreamsAtScale(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("MeshCookedCollisionStreamsAtScale"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)0; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(MeshCookedCollisionStreamsAtScaleNS::checksum); + return MeshCookedCollisionStreamsAtScaleNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const MeshCookedCollisionStreamsAtScaleNS::ParametersStruct& parameters(void) const + { + MeshCookedCollisionStreamsAtScale* tmpThis = const_cast<MeshCookedCollisionStreamsAtScale*>(this); + return *(static_cast<MeshCookedCollisionStreamsAtScaleNS::ParametersStruct*>(tmpThis)); + } + + MeshCookedCollisionStreamsAtScaleNS::ParametersStruct& parameters(void) + { + return *(static_cast<MeshCookedCollisionStreamsAtScaleNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class MeshCookedCollisionStreamsAtScaleFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + MeshCookedCollisionStreamsAtScale::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(MeshCookedCollisionStreamsAtScale), MeshCookedCollisionStreamsAtScale::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, MeshCookedCollisionStreamsAtScale::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class MeshCookedCollisionStreamsAtScale"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(MeshCookedCollisionStreamsAtScale)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, MeshCookedCollisionStreamsAtScale)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, MeshCookedCollisionStreamsAtScale::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, MeshCookedCollisionStreamsAtScale::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class MeshCookedCollisionStreamsAtScale"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of MeshCookedCollisionStreamsAtScale here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (MeshCookedCollisionStreamsAtScale*)bufObj; + } + + virtual const char* getClassName() + { + return (MeshCookedCollisionStreamsAtScale::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (MeshCookedCollisionStreamsAtScale::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (MeshCookedCollisionStreamsAtScale::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (MeshCookedCollisionStreamsAtScale::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/ModuleDestructibleRegistration.h b/APEX_1.4/module/destructible/include/autogen/ModuleDestructibleRegistration.h new file mode 100644 index 00000000..05c9e353 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/ModuleDestructibleRegistration.h @@ -0,0 +1,150 @@ +/* + * 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 MODULE_MODULEDESTRUCTIBLEREGISTRATIONH_H +#define MODULE_MODULEDESTRUCTIBLEREGISTRATIONH_H + +#include "PsAllocator.h" +#include "NvRegistrationsForTraitsBase.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "PxAssert.h" +#include <stdint.h> + +// INCLUDE GENERATED FACTORIES +#include "DestructibleActorParam.h" +#include "DestructibleActorChunks.h" +#include "DestructibleActorState.h" +#include "SurfaceTraceParameters.h" +#include "SurfaceTraceSetParameters.h" +#include "CachedOverlaps.h" +#include "MeshCookedCollisionStream.h" +#include "MeshCookedCollisionStreamsAtScale.h" +#include "DestructibleAssetCollisionDataSet.h" +#include "DestructibleAssetParameters.h" +#include "DestructiblePreviewParam.h" +#include "DestructibleDebugRenderParams.h" +#include "DestructibleModuleParameters.h" + + +// INCLUDE GENERATED CONVERSION + + +namespace nvidia { +namespace destructible { + + +class ModuleDestructibleRegistration : public NvParameterized::RegistrationsForTraitsBase +{ +public: + static void invokeRegistration(NvParameterized::Traits* parameterizedTraits) + { + if (parameterizedTraits) + { + ModuleDestructibleRegistration().registerAll(*parameterizedTraits); + } + } + + static void invokeUnregistration(NvParameterized::Traits* parameterizedTraits) + { + if (parameterizedTraits) + { + ModuleDestructibleRegistration().unregisterAll(*parameterizedTraits); + } + } + + void registerAvailableFactories(NvParameterized::Traits& parameterizedTraits) + { + ::NvParameterized::Factory* factoriesToRegister[] = { +// REGISTER GENERATED FACTORIES + new nvidia::destructible::DestructibleActorParamFactory(), + new nvidia::destructible::DestructibleActorChunksFactory(), + new nvidia::destructible::DestructibleActorStateFactory(), + new nvidia::destructible::SurfaceTraceParametersFactory(), + new nvidia::destructible::SurfaceTraceSetParametersFactory(), + new nvidia::destructible::CachedOverlapsFactory(), + new nvidia::destructible::MeshCookedCollisionStreamFactory(), + new nvidia::destructible::MeshCookedCollisionStreamsAtScaleFactory(), + new nvidia::destructible::DestructibleAssetCollisionDataSetFactory(), + new nvidia::destructible::DestructibleAssetParametersFactory(), + new nvidia::destructible::DestructiblePreviewParamFactory(), + new nvidia::destructible::DestructibleDebugRenderParamsFactory(), + new nvidia::destructible::DestructibleModuleParametersFactory(), + + }; + + for (size_t i = 0; i < sizeof(factoriesToRegister)/sizeof(factoriesToRegister[0]); ++i) + { + parameterizedTraits.registerFactory(*factoriesToRegister[i]); + } + } + + virtual void registerAvailableConverters(NvParameterized::Traits& parameterizedTraits) + { +// REGISTER GENERATED CONVERSION +PX_UNUSED(parameterizedTraits); + + } + + void unregisterAvailableFactories(NvParameterized::Traits& parameterizedTraits) + { + struct FactoryDesc + { + const char* name; + uint32_t version; + }; + + ::NvParameterized::Factory* factoriesToUnregister[] = { +// UNREGISTER GENERATED FACTORIES + new nvidia::destructible::DestructibleActorParamFactory(), + new nvidia::destructible::DestructibleActorChunksFactory(), + new nvidia::destructible::DestructibleActorStateFactory(), + new nvidia::destructible::SurfaceTraceParametersFactory(), + new nvidia::destructible::SurfaceTraceSetParametersFactory(), + new nvidia::destructible::CachedOverlapsFactory(), + new nvidia::destructible::MeshCookedCollisionStreamFactory(), + new nvidia::destructible::MeshCookedCollisionStreamsAtScaleFactory(), + new nvidia::destructible::DestructibleAssetCollisionDataSetFactory(), + new nvidia::destructible::DestructibleAssetParametersFactory(), + new nvidia::destructible::DestructiblePreviewParamFactory(), + new nvidia::destructible::DestructibleDebugRenderParamsFactory(), + new nvidia::destructible::DestructibleModuleParametersFactory(), + + }; + + for (size_t i = 0; i < sizeof(factoriesToUnregister)/sizeof(factoriesToUnregister[0]); ++i) + { + ::NvParameterized::Factory* removedFactory = parameterizedTraits.removeFactory(factoriesToUnregister[i]->getClassName(), factoriesToUnregister[i]->getVersion()); + if (!removedFactory) + { + PX_ASSERT_WITH_MESSAGE(0, "Factory can not be removed!"); + } + else + { + removedFactory->freeParameterDefinitionTable(¶meterizedTraits); + delete removedFactory; + delete factoriesToUnregister[i]; + } + } + } + + virtual void unregisterAvailableConverters(NvParameterized::Traits& parameterizedTraits) + { +// UNREGISTER GENERATED CONVERSION +PX_UNUSED(parameterizedTraits); + + } + +}; + + +} +} //nvidia::destructible + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/SurfaceTraceParameters.h b/APEX_1.4/module/destructible/include/autogen/SurfaceTraceParameters.h new file mode 100644 index 00000000..82219197 --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/SurfaceTraceParameters.h @@ -0,0 +1,248 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_SurfaceTraceParameters_h +#define HEADER_SurfaceTraceParameters_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace SurfaceTraceParametersNS +{ + + +struct U8_DynamicArray1D_Type +{ + uint8_t* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + +struct U32_DynamicArray1D_Type +{ + uint32_t* buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + + +struct ParametersStruct +{ + + U8_DynamicArray1D_Type submeshIndices; + U32_DynamicArray1D_Type vertexIndices; + physx::PxVec3 defaultNormal; + +}; + +static const uint32_t checksum[] = { 0x97a690a9, 0x7c950c3a, 0x7e771c34, 0x41bed788, }; + +} // namespace SurfaceTraceParametersNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class SurfaceTraceParameters : public NvParameterized::NvParameters, public SurfaceTraceParametersNS::ParametersStruct +{ +public: + SurfaceTraceParameters(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~SurfaceTraceParameters(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("SurfaceTraceParameters"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)0; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(SurfaceTraceParametersNS::checksum); + return SurfaceTraceParametersNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const SurfaceTraceParametersNS::ParametersStruct& parameters(void) const + { + SurfaceTraceParameters* tmpThis = const_cast<SurfaceTraceParameters*>(this); + return *(static_cast<SurfaceTraceParametersNS::ParametersStruct*>(tmpThis)); + } + + SurfaceTraceParametersNS::ParametersStruct& parameters(void) + { + return *(static_cast<SurfaceTraceParametersNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class SurfaceTraceParametersFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + SurfaceTraceParameters::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(SurfaceTraceParameters), SurfaceTraceParameters::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, SurfaceTraceParameters::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class SurfaceTraceParameters"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(SurfaceTraceParameters)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, SurfaceTraceParameters)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, SurfaceTraceParameters::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, SurfaceTraceParameters::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class SurfaceTraceParameters"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of SurfaceTraceParameters here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (SurfaceTraceParameters*)bufObj; + } + + virtual const char* getClassName() + { + return (SurfaceTraceParameters::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (SurfaceTraceParameters::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (SurfaceTraceParameters::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (SurfaceTraceParameters::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/include/autogen/SurfaceTraceSetParameters.h b/APEX_1.4/module/destructible/include/autogen/SurfaceTraceSetParameters.h new file mode 100644 index 00000000..3bf77c6d --- /dev/null +++ b/APEX_1.4/module/destructible/include/autogen/SurfaceTraceSetParameters.h @@ -0,0 +1,239 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#ifndef HEADER_SurfaceTraceSetParameters_h +#define HEADER_SurfaceTraceSetParameters_h + +#include "NvParametersTypes.h" + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParameterizedTraits.h" +#include "NvParameters.h" +#include "NvTraitsInternal.h" +#endif + +namespace nvidia +{ +namespace destructible +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#endif + +namespace SurfaceTraceSetParametersNS +{ + + +struct REF_DynamicArray1D_Type +{ + NvParameterized::Interface** buf; + bool isAllocated; + int32_t elementSize; + int32_t arraySizes[1]; +}; + + +struct ParametersStruct +{ + + REF_DynamicArray1D_Type traces; + physx::PxVec3 positionOffset; + +}; + +static const uint32_t checksum[] = { 0x7825b62c, 0x9ed33f77, 0x7851a472, 0xb4319f34, }; + +} // namespace SurfaceTraceSetParametersNS + +#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS +class SurfaceTraceSetParameters : public NvParameterized::NvParameters, public SurfaceTraceSetParametersNS::ParametersStruct +{ +public: + SurfaceTraceSetParameters(NvParameterized::Traits* traits, void* buf = 0, int32_t* refCount = 0); + + virtual ~SurfaceTraceSetParameters(); + + virtual void destroy(); + + static const char* staticClassName(void) + { + return("SurfaceTraceSetParameters"); + } + + const char* className(void) const + { + return(staticClassName()); + } + + static const uint32_t ClassVersion = ((uint32_t)0 << 16) + (uint32_t)2; + + static uint32_t staticVersion(void) + { + return ClassVersion; + } + + uint32_t version(void) const + { + return(staticVersion()); + } + + static const uint32_t ClassAlignment = 8; + + static const uint32_t* staticChecksum(uint32_t& bits) + { + bits = 8 * sizeof(SurfaceTraceSetParametersNS::checksum); + return SurfaceTraceSetParametersNS::checksum; + } + + static void freeParameterDefinitionTable(NvParameterized::Traits* traits); + + const uint32_t* checksum(uint32_t& bits) const + { + return staticChecksum(bits); + } + + const SurfaceTraceSetParametersNS::ParametersStruct& parameters(void) const + { + SurfaceTraceSetParameters* tmpThis = const_cast<SurfaceTraceSetParameters*>(this); + return *(static_cast<SurfaceTraceSetParametersNS::ParametersStruct*>(tmpThis)); + } + + SurfaceTraceSetParametersNS::ParametersStruct& parameters(void) + { + return *(static_cast<SurfaceTraceSetParametersNS::ParametersStruct*>(this)); + } + + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle) const; + virtual NvParameterized::ErrorType getParameterHandle(const char* long_name, NvParameterized::Handle& handle); + + void initDefaults(void); + +protected: + + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void); + virtual const NvParameterized::DefinitionImpl* getParameterDefinitionTree(void) const; + + + virtual void getVarPtr(const NvParameterized::Handle& handle, void*& ptr, size_t& offset) const; + +private: + + void buildTree(void); + void initDynamicArrays(void); + void initStrings(void); + void initReferences(void); + void freeDynamicArrays(void); + void freeStrings(void); + void freeReferences(void); + + static bool mBuiltFlag; + static NvParameterized::MutexType mBuiltFlagMutex; +}; + +class SurfaceTraceSetParametersFactory : public NvParameterized::Factory +{ + static const char* const vptr; + +public: + + virtual void freeParameterDefinitionTable(NvParameterized::Traits* traits) + { + SurfaceTraceSetParameters::freeParameterDefinitionTable(traits); + } + + virtual NvParameterized::Interface* create(NvParameterized::Traits* paramTraits) + { + // placement new on this class using mParameterizedTraits + + void* newPtr = paramTraits->alloc(sizeof(SurfaceTraceSetParameters), SurfaceTraceSetParameters::ClassAlignment); + if (!NvParameterized::IsAligned(newPtr, SurfaceTraceSetParameters::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class SurfaceTraceSetParameters"); + paramTraits->free(newPtr); + return 0; + } + + memset(newPtr, 0, sizeof(SurfaceTraceSetParameters)); // always initialize memory allocated to zero for default values + return NV_PARAM_PLACEMENT_NEW(newPtr, SurfaceTraceSetParameters)(paramTraits); + } + + virtual NvParameterized::Interface* finish(NvParameterized::Traits* paramTraits, void* bufObj, void* bufStart, int32_t* refCount) + { + if (!NvParameterized::IsAligned(bufObj, SurfaceTraceSetParameters::ClassAlignment) + || !NvParameterized::IsAligned(bufStart, SurfaceTraceSetParameters::ClassAlignment)) + { + NV_PARAM_TRAITS_WARNING(paramTraits, "Unaligned memory allocation for class SurfaceTraceSetParameters"); + return 0; + } + + // Init NvParameters-part + // We used to call empty constructor of SurfaceTraceSetParameters here + // but it may call default constructors of members and spoil the data + NV_PARAM_PLACEMENT_NEW(bufObj, NvParameterized::NvParameters)(paramTraits, bufStart, refCount); + + // Init vtable (everything else is already initialized) + *(const char**)bufObj = vptr; + + return (SurfaceTraceSetParameters*)bufObj; + } + + virtual const char* getClassName() + { + return (SurfaceTraceSetParameters::staticClassName()); + } + + virtual uint32_t getVersion() + { + return (SurfaceTraceSetParameters::staticVersion()); + } + + virtual uint32_t getAlignment() + { + return (SurfaceTraceSetParameters::ClassAlignment); + } + + virtual const uint32_t* getChecksum(uint32_t& bits) + { + return (SurfaceTraceSetParameters::staticChecksum(bits)); + } +}; +#endif // NV_PARAMETERIZED_ONLY_LAYOUTS + +} // namespace destructible +} // namespace nvidia + +#if PX_VC +#pragma warning(pop) +#endif + +#endif diff --git a/APEX_1.4/module/destructible/src/DestructibleActorImpl.cpp b/APEX_1.4/module/destructible/src/DestructibleActorImpl.cpp new file mode 100644 index 00000000..849dab58 --- /dev/null +++ b/APEX_1.4/module/destructible/src/DestructibleActorImpl.cpp @@ -0,0 +1,3854 @@ +/* + * 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. + */ + + +#include "ApexDefs.h" +#include "Apex.h" +#include "ScopedPhysXLock.h" +#include "ModuleDestructibleImpl.h" +#include "DestructibleActorImpl.h" +#include "DestructibleScene.h" +#include "SceneIntl.h" +#include "DestructibleStructure.h" +#include "DestructibleActorProxy.h" +#include "ModulePerfScope.h" + +#if APEX_USE_PARTICLES +#include "EmitterAsset.h" +#include "EmitterActor.h" +#endif // APEX_USE_PARTICLES + +#include "PxMath.h" +#include <PxMaterial.h> + +#include "PsString.h" + +#include "RenderMeshAssetIntl.h" + +#include "DestructibleActorUtils.h" + +namespace nvidia +{ +namespace destructible +{ +using namespace physx; + +/////////////////////////////////////////////////////////////////////////// +namespace +{ +bool isPxActorSleeping(const physx::PxRigidDynamic & actor) +{ + PX_ASSERT(NULL != &actor); + SCOPED_PHYSX_LOCK_READ(actor.getScene()); + return actor.isSleeping(); +} +} // namespace nameless + +template<class type> +PX_INLINE void combsort(type* a, uint32_t num) +{ + uint32_t gap = num; + bool swapped = false; + do + { + swapped = false; + gap = (gap * 10) / 13; + if (gap == 9 || gap == 10) + { + gap = 11; + } + else if (gap < 1) + { + gap = 1; + } + for (type* ai = a, *aend = a + (num - gap); ai < aend; ai++) + { + type* aj = ai + gap; + if (*ai > *aj) + { + swapped = true; + nvidia::swap(*ai, *aj); + } + } + } + while (gap > 1 || swapped); +} + +static NvParameterized::Interface* createDefaultState(NvParameterized::Interface* params = NULL) +{ + NvParameterized::Interface* state = GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(DestructibleActorState::staticClassName()); + PX_ASSERT(NULL != state); + if(state) + { + NvParameterized::Handle handle(*state); + VERIFY_PARAM(state->getParameterHandle("actorParameters", handle)); + if (params) + handle.setParamRef(params); + else + handle.initParamRef(DestructibleActorParam::staticClassName()); + + VERIFY_PARAM(state->getParameterHandle("actorChunks", handle)); + handle.initParamRef(DestructibleActorChunks::staticClassName()); + } + return state; +} + +DestructibleActorImpl::DestructibleActorImpl(DestructibleActor* _api, DestructibleAssetImpl& _asset, DestructibleScene& scene ) : + mState(NULL), + mParams(NULL), + mChunks(NULL), + mTM(PxMat44(PxIdentity)), + mRelTM(PxMat44(PxIdentity)), + mVisibleDynamicChunkShapeCount(0), + mEssentialVisibleDynamicChunkShapeCount(0), + mDestructibleScene(&scene), + mAPI(_api), + mFlags(0), + mInternalFlags(0), + mStructure(NULL), + mAsset(&_asset), + mID((uint32_t)InvalidID), + mLinearSize(0.0f), + mCrumbleEmitter(NULL), + mDustEmitter(NULL), + mCrumbleRenderVolume(NULL), + mDustRenderVolume(NULL), + mStartTime(scene.mElapsedTime), + mBenefit(0.0f), + mInitializedFromState(false), + mRenderable(NULL), + mDescOverrideSkinnedMaterialCount(0), + mDescOverrideSkinnedMaterials(NULL), + mDescOverrideStaticMaterialCount(0), + mPhysXActorBufferAcquired(false), + mInDeleteChunkMode(false), + mAwakeActorCount(0), + mActiveFrames(0), + mDamageEventReportIndex(0xFFFFFFFF) +#if APEX_RUNTIME_FRACTURE + //,mRTActor((PX_NEW(DestructibleRTActor)(*this))) + ,mRTActor(NULL) +#endif +#if USE_DESTRUCTIBLE_RWLOCK + , mLock(NULL) +#endif + , mWakeForEvent(false) +{ + // The client (DestructibleActorProxy) is responsible for calling initialize() +} + +void DestructibleActorImpl::initialize(NvParameterized::Interface* p) +{ + // Given actor state + if (NULL != p && isType(p, DestructibleParameterizedType::State)) + { + initializeFromState(p); + initializeCommon(); + } + // Given actor params + else if(NULL != p && isType(p, DestructibleParameterizedType::Params)) + { + initializeFromParams(p); + initializeCommon(); + } + else + { + PX_ALWAYS_ASSERT(); + APEX_INTERNAL_ERROR("Invalid destructible actor creation arguments."); + } +} + +void DestructibleActorImpl::initializeFromState(NvParameterized::Interface* state) +{ + setState(state); + mInitializedFromState = true; +} + +void DestructibleActorImpl::initializeFromParams(NvParameterized::Interface* params) +{ + setState(createDefaultState(params)); + mInitializedFromState = false; + mState->enableCrumbleEmitter = APEX_USE_PARTICLES ? true : false; + mState->enableDustEmitter = APEX_USE_PARTICLES ? true : false; + mState->lod = PxMax(mAsset->getDepthCount(), (uint32_t)1) - 1; +} + +void DestructibleActorImpl::initializeCommon() +{ + setInitialGlobalPose(getParams()->globalPose); + + mFlags = (uint16_t)(getParams()->dynamic ? Dynamic : 0); + + mDescOverrideSkinnedMaterialCount = (uint32_t)getParams()->overrideSkinnedMaterialNames.arraySizes[0]; + mDescOverrideStaticMaterialCount = (uint32_t)getParams()->overrideStaticMaterialNames.arraySizes[0]; + mDescOverrideSkinnedMaterials = (const char**)PX_ALLOC(sizeof(const char*)*(mDescOverrideSkinnedMaterialCount > 0 ? mDescOverrideSkinnedMaterialCount : 1), PX_DEBUG_EXP("DestructibleActor::initializeCommon_mDescOverrideSkinnedMaterials")); + for (uint32_t i = 0; i < mDescOverrideSkinnedMaterialCount; ++i) + { + mDescOverrideSkinnedMaterials[i] = getParams()->overrideSkinnedMaterialNames.buf[i].buf; + } + PX_ALLOCA(staticMaterialNames, const char*, mDescOverrideStaticMaterialCount > 0 ? mDescOverrideStaticMaterialCount : 1); + for (uint32_t i = 0; i < mDescOverrideStaticMaterialCount; ++i) + { + staticMaterialNames[i] = getParams()->overrideStaticMaterialNames.buf[i].buf; + } + + DestructibleActorParam* p = getParams(); + DestructibleActorParamNS::ParametersStruct* ps = static_cast<DestructibleActorParamNS::ParametersStruct*>(p); + + PhysX3DescTemplateImpl p3Desc; + deserialize(p3Desc, ps->p3ActorDescTemplate, ps->p3BodyDescTemplate, ps->p3ShapeDescTemplate); + setPhysX3Template(&p3Desc); + +#if USE_DESTRUCTIBLE_RWLOCK + if (NULL == mLock) + { + mLock = (shdfnd::ReadWriteLock*)PX_ALLOC(sizeof(shdfnd::ReadWriteLock), PX_DEBUG_EXP("DestructibleActor::RWLock")); + PX_PLACEMENT_NEW(mLock, shdfnd::ReadWriteLock); + } +#endif + + PxVec3 extents = mAsset->getBounds().getExtents(); + mLinearSize = PxMax(PxMax(extents.x*getScale().x, extents.y*getScale().y), extents.z*getScale().z); + + setDestructibleParameters(getParams()->destructibleParameters, getParams()->depthParameters); + + initializeActor(); + + if ((getDestructibleParameters().flags & nvidia::apex::DestructibleParametersFlag::CRUMBLE_VIA_RUNTIME_FRACTURE) != 0) + { + initializeRTActor(); + } +} + +float DestructibleActorImpl::getCrumbleParticleSpacing() const +{ + if (mParams->crumbleParticleSpacing > 0.0f) + { + return mParams->crumbleParticleSpacing; + } +#if APEX_USE_PARTICLES + if (getCrumbleEmitter()) + { + return 2 * getCrumbleEmitter()->getObjectRadius(); + } +#endif // APEX_USE_PARTICLES + return 0.0f; +} + +float DestructibleActorImpl::getDustParticleSpacing() const +{ + if (mParams->dustParticleSpacing > 0.0f) + { + return mParams->dustParticleSpacing; + } +#if APEX_USE + if (getDustEmitter()) + { + return 2 * getDustEmitter()->getObjectRadius(); + } +#endif // APEX_USE_PARTICLES + return 0.0f; +} + +void DestructibleActorImpl::setInitialGlobalPose(const PxMat44& pose) +{ + mTM = pose; + mOriginalBounds = mAsset->getBounds(); + PxMat44 scaledTM = mTM; + scaledTM.scale(PxVec4(getScale(), 1.f)); + PxBounds3Transform(mOriginalBounds, scaledTM); +} + +void DestructibleActorImpl::setState(NvParameterized::Interface* state) +{ + if (mState != state) + { + // wrong name? + if (NULL != state && !isType(state, DestructibleParameterizedType::State)) + { + APEX_INTERNAL_ERROR( + "The parameterized interface is of type <%s> instead of <%s>. " + "This object will be initialized by an empty one instead!", + state->className(), + DestructibleActorState::staticClassName()); + + state->destroy(); + state = NULL; + } + else if (NULL != state) + { + //TODO: Verify parameters + } + + // If no state was given, create the default state + if (NULL == state) + { + state = GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(DestructibleActorState::staticClassName()); +} + PX_ASSERT(state); + + // Reset the state if it already exists + if (mState != NULL) + { + mState->setSerializationCallback(NULL); + PX_ASSERT(mDestructibleScene && "Expected destructible scene with existing actor state."); + reset(); + } + + mState = static_cast<DestructibleActorState*>(state); + mParams = NULL; + mChunks = NULL; + + if (NULL != mState) + { + mState->setSerializationCallback(this, (void*)((intptr_t)DestructibleParameterizedType::State)); + + // Cache a handle to the actorParameters + NvParameterized::Handle handle(*mState); + NvParameterized::Interface* p = NULL; + mState->getParameterHandle("actorParameters", handle); + mState->getParamRef(handle, p); + if (NULL != p) + { + mParams = static_cast<DestructibleActorParam*>(p); + mParams->setSerializationCallback(this, (void*)((intptr_t)DestructibleParameterizedType::Params)); + } + else + APEX_INTERNAL_ERROR("Invalid destructible actor state parameterization of actor params."); + + // Cache a handle to the actorChunks + p = NULL; + mState->getParameterHandle("actorChunks", handle); + mState->getParamRef(handle, p); + if (NULL != p) + { + mChunks = static_cast<DestructibleActorChunks*>(p); + } + else + APEX_INTERNAL_ERROR("Invalid destructible actor state parameterization of actor params."); + } + } +} + +void DestructibleActorImpl::createRenderable() +{ + RenderMeshActor* renderMeshActors[DestructibleActorMeshType::Count]; + for (int meshN = 0; meshN < DestructibleActorMeshType::Count; ++meshN) + { + renderMeshActors[meshN] = NULL; + } + + // There were three choices here as to the context in which to create this renderMeshActor. + // a) Use the global ApexSDK context + // b) Make the destructible actor itself an Context + // c) Use the destructible actor's context (mContext) + // + // The decision was made to use option A, the global context, and have the destrucible actor's destructor + // call the render mesh actor's release() method. Option B was too much overhead for a single sub-actor + // and option C would have introduced race conditions at context deletion time. + PX_ASSERT(mAsset->getRenderMeshAsset()); + RenderMeshActorDesc renderableMeshDesc; + renderableMeshDesc.visible = false; + renderableMeshDesc.bufferVisibility = true; + renderableMeshDesc.indexBufferHint = RenderBufferHint::DYNAMIC; + renderableMeshDesc.keepVisibleBonesPacked = keepVisibleBonesPacked(); + renderableMeshDesc.forceBoneIndexChannel = !renderableMeshDesc.keepVisibleBonesPacked; + renderableMeshDesc.overrideMaterials = mDescOverrideSkinnedMaterials; + renderableMeshDesc.overrideMaterialCount = mDescOverrideSkinnedMaterialCount; + renderableMeshDesc.keepPreviousFrameBoneBuffer = keepPreviousFrameBoneBuffer(); + + renderMeshActors[DestructibleActorMeshType::Skinned] = mAsset->getRenderMeshAsset()->createActor(renderableMeshDesc); + + if (drawStaticChunksInSeparateMesh() && !(getFlags() & Dynamic)) + { + // Create static render mesh + renderableMeshDesc.renderWithoutSkinning = true; + renderableMeshDesc.keepPreviousFrameBoneBuffer = false; + PX_ALLOCA(staticMaterialNames, const char*, PxMax(mAsset->mParams->staticMaterialNames.arraySizes[0], 1)); + if (mDescOverrideStaticMaterialCount > 0) + { + // If static override materials are defined, use them + renderableMeshDesc.overrideMaterialCount = mDescOverrideStaticMaterialCount; + renderableMeshDesc.overrideMaterials = mDescOverrideStaticMaterials; + } + else + { + // Otherwise, use the static materials in the asset, if they're defined + renderableMeshDesc.overrideMaterialCount = (uint32_t)mAsset->mParams->staticMaterialNames.arraySizes[0]; + renderableMeshDesc.overrideMaterials = (const char**)staticMaterialNames; + for (int i = 0; i < mAsset->mParams->staticMaterialNames.arraySizes[0]; ++i) + { + staticMaterialNames[i] = mAsset->mParams->staticMaterialNames.buf[i].buf; + } + } + renderMeshActors[DestructibleActorMeshType::Static] = mAsset->getRenderMeshAsset()->createActor(renderableMeshDesc); + } + + //#if APEX_RUNTIME_FRACTURE + //mRenderable = PX_NEW(DestructibleRTRenderable)(renderMeshActors,mRTActor); + //#else + mRenderable = PX_NEW(DestructibleRenderableImpl)(renderMeshActors,getDestructibleAsset(),(int32_t)m_listIndex); + //#endif +} + +void DestructibleActorImpl::initializeActor(void) +{ + if (!mParams->doNotCreateRenderable) + { + createRenderable(); + } + + mFirstChunkIndex = DestructibleAssetImpl::InvalidChunkIndex; + + // Allow color channel replacement if requested + mUseDamageColoring = getParams()->defaultBehaviorGroup.damageColorChange.magnitudeSquared() != 0.0f; + for (int32_t behaviorGroupN = 0; !mUseDamageColoring && behaviorGroupN < getParams()->behaviorGroups.arraySizes[0]; ++behaviorGroupN) + { + mUseDamageColoring = getParams()->behaviorGroups.buf[behaviorGroupN].damageColorChange.magnitudeSquared() != 0.0f; + } + if (mUseDamageColoring) + { + RenderMeshAsset* rma = mAsset->getRenderMeshAsset(); + mDamageColorArrays.resize(rma->getSubmeshCount()); + for (uint32_t submeshIndex = 0; submeshIndex < rma->getSubmeshCount(); ++submeshIndex) + { + physx::Array<ColorRGBA>& damageColorArray = mDamageColorArrays[submeshIndex]; + const RenderSubmesh& submesh = rma->getSubmesh(submeshIndex); + const VertexBuffer& vb = submesh.getVertexBuffer(); + const VertexFormat& vf = vb.getFormat(); + const int32_t colorBufferIndex = vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::COLOR)); + // Fix asset on &damageColorArray[0] + if (vb.getVertexCount() != 0) + { + damageColorArray.resize(vb.getVertexCount()); + intrinsics::memZero(&damageColorArray[0], sizeof(ColorRGBA)*damageColorArray.size()); // Default to zero in case this array doesn't exist in the asset + if (colorBufferIndex >= 0) + { + vb.getBufferData(&damageColorArray[0], RenderDataFormat::R8G8B8A8, 0, (uint32_t)colorBufferIndex, 0, vb.getVertexCount()); + } + for (uint32_t typeN = 0; typeN < DestructibleActorMeshType::Count; ++typeN) + { + RenderMeshActorIntl* renderMeshActor = (RenderMeshActorIntl*)getRenderMeshActor((DestructibleActorMeshType::Enum)typeN); + if (renderMeshActor != NULL) + { + renderMeshActor->setStaticColorReplacement(submeshIndex, &damageColorArray[0]); + } + } + } + } + } + + initializeEmitters(); + + mVisibleChunks.reserve(mAsset->getChunkCount()); + mVisibleChunks.lockCapacity(true); + + // This is done to handle old formats, and ensure we have a sufficient # of DepthParameters + while (mDestructibleParameters.depthParametersCount < mAsset->getDepthCount() && mDestructibleParameters.depthParametersCount < DestructibleParameters::kDepthParametersCountMax) + { + DestructibleDepthParameters& params = mDestructibleParameters.depthParameters[mDestructibleParameters.depthParametersCount]; + if (mDestructibleParameters.depthParametersCount == 0) + { + // Set level 0 parameters to the more expensive settings + memset(¶ms, 0xFF, sizeof(params)); + } + ++mDestructibleParameters.depthParametersCount; + } + + // When we add ourselves to the ApexScene, it will call us back with setPhysXScene + if (!findSelfInContext(*mDestructibleScene->mApexScene->getApexContext())) + addSelfToContext(*mDestructibleScene->mApexScene->getApexContext()); + + // Add ourself to our DestructibleScene + if (!findSelfInContext(*DYNAMIC_CAST(ApexContext*)(mDestructibleScene))) + { + addSelfToContext(*DYNAMIC_CAST(ApexContext*)(mDestructibleScene)); + + if (mAsset->mParams->chunkInstanceInfo.arraySizes[0] || mAsset->mParams->scatterMeshAssets.arraySizes[0]) + { + mDestructibleScene->addInstancedActor(this); + } + } + + // Set a reasonable initial bounds until the first physics update + mRenderBounds = getOriginalBounds(); + if (mRenderable != NULL) + { + mRenderable->setBounds(mRenderBounds); + } + mNonInstancedBounds = mRenderBounds; + mInstancedBounds.setEmpty(); +} + +void DestructibleActorImpl::initializeRTActor(void) +{ +#if APEX_RUNTIME_FRACTURE + //mRTActor->initialize(); + PX_DELETE(mRTActor); + mRTActor = (nvidia::fracture::Actor*)mDestructibleScene->getDestructibleRTScene()->createActor(this); +#endif +} + +void DestructibleActorImpl::initializeEmitters(void) +{ +#if APEX_USE_PARTICLES + if (getCrumbleEmitterName() || mAsset->getCrumbleEmitterName()) + { + const char* name; + if (getCrumbleEmitterName()) + { + name = getCrumbleEmitterName(); + mAsset->mCrumbleAssetTracker.addAssetName(name, false); + } + else + { + name = mAsset->getCrumbleEmitterName(); + } + initCrumbleSystem(name); + } + { + const char* name; + if (getDustEmitterName()) + { + name = getDustEmitterName(); + mAsset->mDustAssetTracker.addAssetName(name, false); + } + else + { + name = mAsset->getDustEmitterName(); + } + initDustSystem(name); + } +#endif // APEX_USE_PARTICLES +} + +void DestructibleActorImpl::setDestructibleParameters(const DestructibleActorParamNS::DestructibleParameters_Type& destructibleParameters, + const DestructibleActorParamNS::DestructibleDepthParameters_DynamicArray1D_Type& destructibleDepthParameters) +{ + DestructibleParameters parameters; + deserialize(destructibleParameters, destructibleDepthParameters, parameters); + setDestructibleParameters(parameters); +} + +void DestructibleActorImpl::setDestructibleParameters(const DestructibleParameters& _destructibleParameters) +{ + // If essentialDepth changes, must re-count essential visible chunks + if(_destructibleParameters.essentialDepth != mDestructibleParameters.essentialDepth) + { + mEssentialVisibleDynamicChunkShapeCount = 0; + const uint16_t* chunkIndexPtr = mVisibleChunks.usedIndices(); + const uint16_t* chunkIndexPtrStop = chunkIndexPtr + mVisibleChunks.usedCount(); + while (chunkIndexPtr < chunkIndexPtrStop) + { + uint16_t chunkIndex = *chunkIndexPtr++; + if(getDynamic(chunkIndex)) + { + if((uint32_t)getDestructibleAsset()->mParams->chunks.buf[chunkIndex].depth <= _destructibleParameters.essentialDepth) + { + mEssentialVisibleDynamicChunkShapeCount += getDestructibleAsset()->getChunkHullCount(chunkIndex); + } + } + } + } + + // For now we keep a cached copy of the parameters + // At some point we may want to move completely into the state + mDestructibleParameters = _destructibleParameters; + + + getParams()->supportDepth = PxClamp(getSupportDepth(), (uint32_t)0, mAsset->getDepthCount() - 1); + + // Make sure the depth params are filled completely + uint32_t oldSize = mDestructibleParameters.depthParametersCount; + uint32_t neededSize = mAsset->getDepthCount(); + if (neededSize > DestructibleParameters::kDepthParametersCountMax) + { + neededSize = DestructibleParameters::kDepthParametersCountMax; + } + mDestructibleParameters.depthParametersCount = neededSize; + // Fill in remaining with asset defaults + for (uint32_t i = oldSize; i < neededSize; ++i) + { + mDestructibleParameters.depthParameters[i].setToDefault(); + } +} + +/* An (emitter) actor in our context has been released */ +void DestructibleActorImpl::removeActorAtIndex(uint32_t index) +{ +#if APEX_USE_PARTICLES + if (mDustEmitter == mActorArray[index]->getActor()) + { + mDustEmitter = 0; + } + if (mCrumbleEmitter == mActorArray[index]->getActor()) + { + mCrumbleEmitter = 0; + } +#endif // APEX_USE_PARTICLES + + ApexContext::removeActorAtIndex(index); +} + + +void DestructibleActorImpl::wakeUp(void) +{ + PX_ASSERT(mDestructibleScene); + if (mDestructibleScene) + { + mDestructibleScene->addToAwakeList(*this); + } +} + +void DestructibleActorImpl::putToSleep(void) +{ + PX_ASSERT(mDestructibleScene); + if (mDestructibleScene) + { + mDestructibleScene->removeFromAwakeList(*this); + } +} + +// TODO: clean up mAwakeActorCount management with mUsingActiveTransforms +// [APEX-671] mind that un/referencedByActor() also call these functions + +void DestructibleActorImpl::incrementWakeCount(void) +{ + if (!mAwakeActorCount) + { + wakeUp(); + } + mAwakeActorCount++; +} + +void DestructibleActorImpl::referencedByActor(PxRigidDynamic* actor) +{ + if (mReferencingActors.find(actor) == mReferencingActors.end()) + { + // We need to check IS_SLEEPING instead of actor->isSleeping, + // because the state might have changed between the last callback and now. + // Here, the state of the last callback is needed. + PhysXObjectDescIntl* desc = (PhysXObjectDescIntl*)(GetInternalApexSDK()->getPhysXObjectInfo(actor)); + if (mDestructibleScene != NULL && !mDestructibleScene->mUsingActiveTransforms && desc != NULL && !desc->getUserDefinedFlag(PhysXActorFlags::IS_SLEEPING)) + { + incrementWakeCount(); + } + mReferencingActors.pushBack(actor); + } +} + +void DestructibleActorImpl::unreferencedByActor(PxRigidDynamic* actor) +{ + if (mReferencingActors.findAndReplaceWithLast(actor)) + { + PhysXObjectDescIntl* desc = (PhysXObjectDescIntl*)(GetInternalApexSDK()->getPhysXObjectInfo(actor)); + if (mDestructibleScene != NULL && !mDestructibleScene->mUsingActiveTransforms && desc != NULL && !desc->getUserDefinedFlag(PhysXActorFlags::IS_SLEEPING)) + { + decrementWakeCount(); + } + } +} + +void DestructibleActorImpl::wakeForEvent() +{ + if (!mWakeForEvent) + { + mWakeForEvent = true; + incrementWakeCount(); + } +} + +void DestructibleActorImpl::resetWakeForEvent() +{ + if (mWakeForEvent) + { + mWakeForEvent = false; + decrementWakeCount(); + } +} + +void DestructibleActorImpl::decrementWakeCount(void) +{ + // this assert shouldn't happen, so if it does it means bad things, tell james. + // basically we keep a counter of the number of awake bodies in a destructible actor + // so that when its zero we know no updates are needed (normally updates are really expensive + // per-destructible). So, if wake count is 0 and its trying to decrement it means + // this value is completely out of sync and that can result in bad things (performance loss + // or behavior loss). So, don't remove this assert! + + PX_ASSERT(mAwakeActorCount > 0); + if (mAwakeActorCount > 0) + { + mAwakeActorCount--; + if (!mAwakeActorCount) + { + putToSleep(); + } + } +} + +void DestructibleActorImpl::setChunkVisibility(uint16_t index, bool visibility) +{ + PX_ASSERT((int32_t)index < mAsset->mParams->chunks.arraySizes[0]); + if (visibility) + { + if(mVisibleChunks.use(index)) + { + if (createChunkEvents()) + { + mChunkEventBufferLock.lock(); + + if (mChunkEventBuffer.size() == 0 && mDestructibleScene->getModuleDestructible()->m_chunkStateEventCallbackSchedule != DestructibleCallbackSchedule::Disabled) + { + mStructure->dscene->mActorsWithChunkStateEvents.pushBack(this); + } + + DestructibleChunkEvent& chunkEvent = mChunkEventBuffer.insert(); + chunkEvent.chunkIndex = index; + chunkEvent.event = DestructibleChunkEvent::VisibilityChanged | DestructibleChunkEvent::ChunkVisible; + + mChunkEventBufferLock.unlock(); + } + if(getDynamic(index)) + { + const uint32_t chunkShapeCount = getDestructibleAsset()->getChunkHullCount(index); + mVisibleDynamicChunkShapeCount += chunkShapeCount; + if((uint32_t)getDestructibleAsset()->mParams->chunks.buf[index].depth <= mDestructibleParameters.essentialDepth) + { + mEssentialVisibleDynamicChunkShapeCount += chunkShapeCount; + } + } + } + } + else + { + if(mVisibleChunks.free(index)) + { + if(getDynamic(index)) + { + const uint32_t chunkShapeCount = getDestructibleAsset()->getChunkHullCount(index); + mVisibleDynamicChunkShapeCount = mVisibleDynamicChunkShapeCount >= chunkShapeCount ? mVisibleDynamicChunkShapeCount - chunkShapeCount : 0; + if((uint32_t)getDestructibleAsset()->mParams->chunks.buf[index].depth <= mDestructibleParameters.essentialDepth) + { + mEssentialVisibleDynamicChunkShapeCount = mEssentialVisibleDynamicChunkShapeCount >= chunkShapeCount ? mEssentialVisibleDynamicChunkShapeCount - chunkShapeCount : 0; + } + } + if (createChunkEvents()) + { + mChunkEventBufferLock.lock(); + + if (mChunkEventBuffer.size() == 0 && mDestructibleScene->getModuleDestructible()->m_chunkStateEventCallbackSchedule != DestructibleCallbackSchedule::Disabled) + { + mStructure->dscene->mActorsWithChunkStateEvents.pushBack(this); + } + + DestructibleChunkEvent& chunkEvent = mChunkEventBuffer.insert(); + chunkEvent.chunkIndex = index; + chunkEvent.event = DestructibleChunkEvent::VisibilityChanged; + + mChunkEventBufferLock.unlock(); + } + } + } + DestructibleAssetParametersNS::Chunk_Type& sourceChunk = mAsset->mParams->chunks.buf[index]; + if ((sourceChunk.flags & DestructibleAssetImpl::Instanced) == 0) + { + // Not instanced - need to choose the static or dynamic mesh, and set visibility for the render mesh actor + const DestructibleActorMeshType::Enum typeN = (getDynamic(index) || !drawStaticChunksInSeparateMesh()) ? + DestructibleActorMeshType::Skinned : DestructibleActorMeshType::Static; + RenderMeshActor* rma = getRenderMeshActor(typeN); + if (rma != NULL) + { + RenderMeshActorIntl* rmi = static_cast<RenderMeshActorIntl*>(rma); + const bool visibilityChanged = rmi->setVisibility(visibility, sourceChunk.meshPartIndex); + if (keepPreviousFrameBoneBuffer() && visibilityChanged && visibility) + { + // Visibility changed from false to true. If we're keeping the previous frame bone buffer, be sure to seed the previous frame buffer + if (!mStructure->chunks[index + mFirstChunkIndex].isDestroyed()) + { + rmi->setLastFrameTM(getChunkPose(index), getScale(), sourceChunk.meshPartIndex); + } + } + } + } +} + +void DestructibleActorImpl::cacheModuleData() const +{ + PX_PROFILE_ZONE("DestructibleCacheChunkCookedCollisionMeshes", GetInternalApexSDK()->getContextId()); + + if (mAsset == NULL) + { + PX_ASSERT(!"cacheModuleData: asset is NULL.\n"); + return; + } + // The DestructibleActor::cacheModuleData() method needs to avoid incrementing the ref count + bool incCacheRefCount = false; + physx::Array<PxConvexMesh*>* meshes = mStructure->dscene->mModule->mCachedData->getConvexMeshesForScale(*this->mAsset, + getDestructibleScene()->getModuleDestructible()->getChunkCollisionHullCookingScale(), + incCacheRefCount); + if (meshes == NULL) + { + PX_ASSERT(!"cacheModuleData: failed to create convex mesh cache for actor.\n"); + return; + } +} + +/* Called by Scene when the actor is added to the scene context or when the Scene's + * PxScene reference changes. PxScene can be NULL if the Scene is losing its PxScene reference. + */ +void DestructibleActorImpl::setPhysXScene(PxScene* pxScene) +{ + if (pxScene) + { + PX_ASSERT(mStructure == NULL); + mDestructibleScene->insertDestructibleActor(mAPI); + } + else + { + PX_ASSERT(mStructure != NULL); + removeSelfFromStructure(); + } +} + +PxScene* DestructibleActorImpl::getPhysXScene() const +{ + return mDestructibleScene->mPhysXScene; +} + +void DestructibleActorImpl::removeSelfFromStructure() +{ + if (!mStructure) + { + return; + } + + DestructibleStructure* oldStructure = mStructure; + + mStructure->removeActor(this); + + if (oldStructure->destructibles.size() == 0) + { + oldStructure->dscene->removeStructure(oldStructure); + } + + for (uint32_t typeN = 0; typeN < DestructibleActorMeshType::Count; ++typeN) + { + RenderMeshActor* renderMeshActor = getRenderMeshActor((DestructibleActorMeshType::Enum)typeN); + if (renderMeshActor != NULL) + { + while (renderMeshActor->visiblePartCount() > 0) + { + renderMeshActor->setVisibility(false, (uint16_t)renderMeshActor->getVisibleParts()[renderMeshActor->visiblePartCount() - 1]); + } + } + } + + mDestructibleScene->mTotalChunkCount -= mVisibleChunks.usedCount(); + + mVisibleChunks.clear(mAsset->getChunkCount()); +} + +void DestructibleActorImpl::removeSelfFromScene() +{ + if (mDestructibleScene == NULL) + { + return; + } + + mDestructibleScene->mDestructibles.direct(mID) = NULL; + mDestructibleScene->mDestructibles.free(mID); + + mID = (uint32_t)InvalidID; +} + +DestructibleActorImpl::~DestructibleActorImpl() +{ +#if APEX_RUNTIME_FRACTURE + PX_DELETE(mRTActor); + mRTActor = NULL; +#endif +} + +void DestructibleActorImpl::release() +{ + if (mInRelease) + { + return; + } + mInRelease = true; + + mAsset->module->mCachedData->releaseReferencesToConvexMeshesForActor(*this); + + // after this call, mAsset and all other members are freed and unusable + mAsset->releaseDestructibleActor(*mAPI); + + // HC SVNT DRACONES +} + +void DestructibleActorImpl::destroy() +{ + mDestructibleScene->removeReferencesToActor(*this); + + if (NULL != mDescOverrideSkinnedMaterials) + { + PX_FREE_AND_RESET(mDescOverrideSkinnedMaterials); + } + + //ApexActor::destroy(); + mInRelease = true; + renderDataLock(); + for (uint32_t i = 0 ; i < mContexts.size() ; i++) + { + ContextTrack& t = mContexts[i]; + t.ctx->removeActorAtIndex(t.index); + } + mContexts.clear(); + renderDataUnLock(); + + ApexResource::removeSelf(); + + // BRG - moving down here from the top of this function - mState seems to be needed + if (NULL != mState) + { + mState->destroy(); + mState = NULL; + } + +#if APEX_RUNTIME_FRACTURE + //if (mRTActor != NULL) + //{ + // mRTActor->notifyParentActorDestroyed(); + //} +#endif + + if (mRenderable != NULL) + { + mRenderable->release(); + mRenderable = NULL; + } + +#if APEX_USE_PARTICLES + if (mDustEmitter) + { + mDustEmitter->release(); + mDustEmitter = NULL; + } + + if (mCrumbleEmitter) + { + mCrumbleEmitter->release(); + mCrumbleEmitter = NULL; + } +#endif // APEX_USE_PARTICLES + +#if USE_DESTRUCTIBLE_RWLOCK + if (mLock) + { + mLock->~shdfnd::ReadWriteLock(); + PX_FREE(mLock); + } + mLock = NULL; +#endif + + // acquire the buffer so we can properly release it + const DestructibleChunkEvent* tmpChunkEventBuffer=NULL; + uint32_t tmpChunkEventBufferSize = 0; + acquireChunkEventBuffer(tmpChunkEventBuffer, tmpChunkEventBufferSize); + + releaseChunkEventBuffer(); + + releasePhysXActorBuffer(); + + removeSelfFromScene(); + + if(0 != mSyncParams.getUserActorID()) + { + setSyncParams(0, 0, NULL, NULL); + } +} + +void DestructibleActorImpl::reset() +{ + destroy(); + + mInRelease = false; + + /////////////////////////////////////////////////////////////////////////// + + mState = NULL; + mParams = NULL; + mTM = PxMat44(PxIdentity); + mFlags = 0; + mInternalFlags = 0; + mStructure = NULL; + mID = (uint32_t)InvalidID; + mLinearSize = 0.0f; + mCrumbleEmitter = NULL; + mDustEmitter = NULL; + mCrumbleRenderVolume = NULL; + mDustRenderVolume = NULL; + mStartTime = mDestructibleScene->mElapsedTime; + mInitializedFromState = false; + mAwakeActorCount = 0; + mDescOverrideSkinnedMaterialCount = 0; + mDescOverrideStaticMaterialCount = 0; + + mStaticRoots.clear(); + mVisibleChunks.clear(); + + #if APEX_RUNTIME_FRACTURE + PX_DELETE(mRTActor); + mRTActor = NULL; + #endif +} + +void DestructibleActorImpl::initializeChunk(uint32_t index, DestructibleStructure::Chunk& target) const +{ + const DestructibleAssetParametersNS::Chunk_Type& source = getDestructibleAsset()->mParams->chunks.buf[index]; + + // Derived parameters + target.destructibleID = getID(); + target.reportID = (uint32_t)DestructibleScene::InvalidReportID; + target.indexInAsset = (uint16_t)index; + target.islandID = (uint32_t)DestructibleStructure::InvalidID; + + // Serialized parameters + if (mInitializedFromState && (int32_t)index < mChunks->data.arraySizes[0]) + { + deserializeChunkData(mChunks->data.buf[index], target); + if (target.visibleAncestorIndex != (int32_t)DestructibleStructure::InvalidChunkIndex) + target.visibleAncestorIndex += getFirstChunkIndex(); + } + // Default parameters + else + { + target.state = uint8_t(isInitiallyDynamic() ? ChunkDynamic : 0); + target.flags = 0; + target.damage = 0; + target.localOffset = getScale().multiply(getDestructibleAsset()->getChunkPositionOffset(index)); + const PxBounds3& bounds = getDestructibleAsset()->getChunkShapeLocalBounds(index); + PxVec3 center = bounds.getCenter(); + PxVec3 extents = bounds.getExtents(); + center = center.multiply(getScale()); + extents = extents.multiply(getScale()); + target.localSphereCenter = center; + target.localSphereRadius = extents.magnitude(); + target.clearShapes(); + target.controlledChunk = NULL; + + if (source.numChildren == 0) + { + target.flags |= ChunkMissingChild; + } + } + +#if USE_CHUNK_RWLOCK + target.lock = (shdfnd::ReadWriteLock*)PX_ALLOC(sizeof(shdfnd::ReadWriteLock), PX_DEBUG_EXP("DestructibleActor::RWLock")); + PX_PLACEMENT_NEW(target.lock, shdfnd::ReadWriteLock); +#endif + + // I have not yet determined if this flag should be set for all actors, + // or only for those initialized purely from params + /*if (source.numChildren == 0) + { + target.flags |= ChunkMissingChild; + }*/ +} + + +const DestructibleStructure::Chunk& DestructibleActorImpl::getChunk(uint32_t index) const +{ + PX_ASSERT(mStructure != NULL); + PX_ASSERT(index + mFirstChunkIndex < mStructure->chunks.size()); + return mStructure->chunks[index + mFirstChunkIndex]; +} + +PxTransform DestructibleActorImpl::getChunkPose(uint32_t index) const +{ + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + + PX_ASSERT(mStructure != NULL); + PX_ASSERT(index + mFirstChunkIndex < mStructure->chunks.size()); + PX_ASSERT(!mStructure->chunks[index + mFirstChunkIndex].isDestroyed()); + return mStructure->getChunkGlobalPose(mStructure->chunks[index + mFirstChunkIndex]); +} + +PxTransform DestructibleActorImpl::getChunkTransform(uint32_t index) const +{ + PX_ASSERT(mStructure != NULL); + PX_ASSERT(index + mFirstChunkIndex < mStructure->chunks.size()); + PX_ASSERT(!mStructure->chunks[index + mFirstChunkIndex].isDestroyed()); + return mStructure->getChunkGlobalTransform(mStructure->chunks[index + mFirstChunkIndex]); +} + +bool DestructibleActorImpl::getInitialChunkDestroyed(uint32_t index) const +{ + PX_ASSERT((int32_t)index < mChunks->data.arraySizes[0]); + return (int32_t)index < mChunks->data.arraySizes[0] + ? (mChunks->data.buf[index].shapesCount == 0 && mChunks->data.buf[index].visibleAncestorIndex == (int32_t)DestructibleStructure::InvalidChunkIndex) + : false; +} + +bool DestructibleActorImpl::getInitialChunkDynamic(uint32_t index) const +{ + PX_ASSERT((int32_t)index < mChunks->data.arraySizes[0]); + return ((int32_t)index < mChunks->data.arraySizes[0]) + ? ((mChunks->data.buf[index].state & ChunkDynamic) != 0) : true; +} + +bool DestructibleActorImpl::getInitialChunkVisible(uint32_t index) const +{ + PX_ASSERT((index == 0 && mChunks->data.arraySizes[0] == 0) || + (int32_t)index < mChunks->data.arraySizes[0]); + return ((int32_t)index < mChunks->data.arraySizes[0]) + ? ((mChunks->data.buf[index].state & ChunkVisible) != 0) : true; +} + +PxTransform DestructibleActorImpl::getInitialChunkGlobalPose(uint32_t index) const +{ + PX_ASSERT((int32_t)index < mChunks->data.arraySizes[0]); + return (int32_t)index < mChunks->data.arraySizes[0] + ? mChunks->data.buf[index].globalPose : PxTransform(PxIdentity); +} + +PxTransform DestructibleActorImpl::getInitialChunkLocalPose(uint32_t index) const +{ + return PxTransform(getDestructibleAsset()->getChunkPositionOffset(index)); +} + +PxVec3 DestructibleActorImpl::getInitialChunkLinearVelocity(uint32_t index) const +{ + PX_ASSERT((int32_t)index < mChunks->data.arraySizes[0]); + return (int32_t)index < mChunks->data.arraySizes[0] + ? mChunks->data.buf[index].linearVelocity : PxVec3(0); +} + +PxVec3 DestructibleActorImpl::getInitialChunkAngularVelocity(uint32_t index) const +{ + PX_ASSERT((int32_t)index < mChunks->data.arraySizes[0]); + return (int32_t)index < mChunks->data.arraySizes[0] + ? mChunks->data.buf[index].angularVelocity : PxVec3(0); +} + +PxVec3 DestructibleActorImpl::getChunkLinearVelocity(uint32_t index) const +{ + PX_ASSERT(mStructure != NULL); + PX_ASSERT(index + mFirstChunkIndex < mStructure->chunks.size()); + PX_ASSERT(!mStructure->chunks[index + mFirstChunkIndex].isDestroyed()); + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + return getChunkActor(index)->getLinearVelocity(); +} + +PxVec3 DestructibleActorImpl::getChunkAngularVelocity(uint32_t index) const +{ + PX_ASSERT(mStructure != NULL); + PX_ASSERT(index + mFirstChunkIndex < mStructure->chunks.size()); + PX_ASSERT(!mStructure->chunks[index + mFirstChunkIndex].isDestroyed()); + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + return getChunkActor(index)->getAngularVelocity(); +} + +PxRigidDynamic* DestructibleActorImpl::getChunkActor(uint32_t index) +{ + PX_ASSERT(mStructure != NULL); + PX_ASSERT(index + mFirstChunkIndex < mStructure->chunks.size()); + DestructibleStructure::Chunk& chunk = mStructure->chunks[index + mFirstChunkIndex]; + return mStructure->getChunkActor(chunk); +} + +const PxRigidDynamic* DestructibleActorImpl::getChunkActor(uint32_t index) const +{ + PX_ASSERT(mStructure != NULL); + PX_ASSERT(index + mFirstChunkIndex < mStructure->chunks.size()); + DestructibleStructure::Chunk& chunk = mStructure->chunks[index + mFirstChunkIndex]; + return mStructure->getChunkActor(chunk); +} + +uint32_t DestructibleActorImpl::getChunkPhysXShapes(physx::PxShape**& shapes, uint32_t chunkIndex) const +{ + PX_ASSERT(mStructure != NULL); + PX_ASSERT(chunkIndex + mFirstChunkIndex < mStructure->chunks.size()); + DestructibleStructure::Chunk& chunk = mStructure->chunks[chunkIndex + mFirstChunkIndex]; + physx::Array<PxShape*>& shapeArray = mStructure->getChunkShapes(chunk); + shapes = shapeArray.size() ? &shapeArray[0] : NULL; + return shapeArray.size(); +} + +uint32_t DestructibleActorImpl::getChunkActorFlags(uint32_t index) const +{ + PX_ASSERT(mStructure != NULL); + PX_ASSERT(index + mFirstChunkIndex < mStructure->chunks.size()); + DestructibleStructure::Chunk& chunk = mStructure->chunks[index + mFirstChunkIndex]; + uint32_t flags = 0; + if (chunk.flags & ChunkWorldSupported) + { + flags |= DestructibleActorChunkFlags::ChunkIsWorldSupported; + } + return flags; +} + +void DestructibleActorImpl::applyDamage(float damage, float momentum, const PxVec3& position, const PxVec3& direction, int32_t chunkIndex, void* damageUserData) +{ + DamageEvent& damageEvent = mStructure->dscene->getDamageWriteBuffer().pushBack(); + damageEvent.destructibleID = mID; + damageEvent.damage = damage; + damageEvent.momentum = momentum; + damageEvent.position = position; + damageEvent.direction = direction; + damageEvent.radius = 0.0f; + damageEvent.chunkIndexInAsset = chunkIndex >= 0 ? chunkIndex : ModuleDestructibleConst::INVALID_CHUNK_INDEX; + damageEvent.flags = 0; + damageEvent.impactDamageActor = NULL; + damageEvent.appliedDamageUserData = damageUserData; +} + +void DestructibleActorImpl::applyRadiusDamage(float damage, float momentum, const PxVec3& position, float radius, bool falloff, void* damageUserData) +{ + DamageEvent& damageEvent = mStructure->dscene->getDamageWriteBuffer().pushBack(); + damageEvent.destructibleID = mID; + damageEvent.damage = damage; + damageEvent.momentum = momentum; + damageEvent.position = position; + damageEvent.direction = PxVec3(0.0f); // not used + damageEvent.radius = radius; + damageEvent.chunkIndexInAsset = ModuleDestructibleConst::INVALID_CHUNK_INDEX; + damageEvent.flags = DamageEvent::UseRadius; + damageEvent.impactDamageActor = NULL; + damageEvent.appliedDamageUserData = damageUserData; + if (falloff) + { + damageEvent.flags |= DamageEvent::HasFalloff; + } +} + +void DestructibleActorImpl::takeImpact(const PxVec3& force, const PxVec3& position, uint16_t chunkIndex, PxActor const* damageActor) +{ + if (chunkIndex >= (uint16_t)mAsset->mParams->chunks.arraySizes[0]) + { + return; + } + DestructibleAssetParametersNS::Chunk_Type& source = mAsset->mParams->chunks.buf[chunkIndex]; + if (!takesImpactDamageAtDepth(source.depth)) + { + return; + } + DamageEvent& damageEvent = mStructure->dscene->getDamageWriteBuffer().pushBack(); + damageEvent.direction = force; + damageEvent.destructibleID = mID; + const float magnitude = damageEvent.direction.normalize(); + damageEvent.damage = magnitude * mDestructibleParameters.forceToDamage; + damageEvent.momentum = 0.0f; + damageEvent.position = position; + damageEvent.radius = 0.0f; + damageEvent.chunkIndexInAsset = chunkIndex; + damageEvent.flags = DamageEvent::IsFromImpact; + damageEvent.impactDamageActor = damageActor; + damageEvent.appliedDamageUserData = NULL; + + if (mStructure->dscene->mModule->m_impactDamageReport != NULL) + { + ImpactDamageEventData& data = mStructure->dscene->mImpactDamageEventData.insert(); + (DamageEventCoreData&)data = (DamageEventCoreData&)damageEvent; // Copy core data + data.destructible = mAPI; + data.direction = damageEvent.direction; + data.impactDamageActor = damageActor; + } +} + +int32_t DestructibleActorImpl::pointOrOBBSweep(float& time, PxVec3& normal, const PxVec3& worldBoxCenter, const PxVec3& worldBoxExtents, const PxMat33& worldBoxRT, const PxVec3& pxWorldDisp, + DestructibleActorRaycastFlags::Enum flags, int32_t parentChunkIndex) const +{ + PX_PROFILE_ZONE("DestructibleActorPointOrOBBSweep", GetInternalApexSDK()->getContextId()); + + // use the scene lock to protect chunk data for + // multi-threaded obbSweep calls on destructible actors + // (different lock would be good, but mixing locks can cause deadlocks) + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + + // TODO: the normal is not always output, for instance, when accurateRaycasts is false, can we generate a decent normal in this case? + const bool pointSweep = (worldBoxExtents.magnitudeSquared() == 0.0f); + + const uint32_t dynamicStateFlags = ((uint32_t)flags)&DestructibleActorRaycastFlags::AllChunks; + if (dynamicStateFlags == 0) + { + return ModuleDestructibleConst::INVALID_CHUNK_INDEX; + } + + const PxVec3 worldBoxAxes[3] = { worldBoxRT.column0, worldBoxRT.column1, worldBoxRT.column2 }; + const PxVec3 worldDisp = pxWorldDisp; + + // Project box along displacement direction, for the entire sweep + const float worldDisp2 = worldDisp.magnitudeSquared(); + const bool sweep = (worldDisp2 != 0.0f); + const float recipWorldDisp2 = sweep ? 1.0f / worldDisp2 : 0.0f; + const float boxProjectedRadius = worldBoxExtents.x * PxAbs(worldDisp.dot(worldBoxAxes[0])) + + worldBoxExtents.y * PxAbs(worldDisp.dot(worldBoxAxes[1])) + + worldBoxExtents.z * PxAbs(worldDisp.dot(worldBoxAxes[2])); + const float boxProjectedCenter = worldDisp.dot(worldBoxCenter); + const float boxBSphereRadius = worldBoxExtents.magnitude(); // May reduce this by projecting the box along worldDisp + + float boxSweptMax; + float minRayT; + float maxRayT; + + const float boxProjectedMin = boxProjectedCenter - boxProjectedRadius; + const float boxProjectedMax = boxProjectedCenter + boxProjectedRadius; + if ((flags & DestructibleActorRaycastFlags::SegmentIntersect) != 0) + { + boxSweptMax = boxProjectedMax + worldDisp2; + minRayT = 0.0f; + maxRayT = 1.0f; + } + else + { + boxSweptMax = PX_MAX_F32; + minRayT = -PX_MAX_F32; + maxRayT = PX_MAX_F32; + } + + PxVec3 rayorig; + PxVec3 raydir; + +// OverlapLineSegmentAABBCache segmentCache; + if (pointSweep) + { +// computeOverlapLineSegmentAABBCache(segmentCache, worldDisplacement); + rayorig = worldBoxCenter; + raydir = worldDisp; + } + + float minTime = PX_MAX_F32; + uint32_t totalVisibleChunkCount; + const uint16_t* visibleChunkIndices; + uint16_t dummyIndexArray = (uint16_t)parentChunkIndex; + if (parentChunkIndex == ModuleDestructibleConst::INVALID_CHUNK_INDEX) + { + totalVisibleChunkCount = mVisibleChunks.usedCount(); + visibleChunkIndices = mVisibleChunks.usedIndices(); + } + else + { + totalVisibleChunkCount = 1; + visibleChunkIndices = &dummyIndexArray; + } + + IndexedReal* chunkProjectedMinima = (IndexedReal*)PxAlloca(totalVisibleChunkCount * sizeof(IndexedReal)); + uint32_t* chunkIndices = (uint32_t*)PxAlloca(totalVisibleChunkCount * sizeof(uint32_t)); + PxTransform* chunkTMs = (PxTransform*)PxAlloca(totalVisibleChunkCount * sizeof(PxTransform)); + +#if USE_DESTRUCTIBLE_RWLOCK + mLock->lockReader(); +#endif + { + // Must find an intersecting visible chunk. + PX_PROFILE_ZONE("DestructibleRayCastFindVisibleChunk", GetInternalApexSDK()->getContextId()); + + // Find candidate chunks + uint32_t candidateChunkCount = 0; + + for (uint32_t chunkNum = 0; chunkNum < totalVisibleChunkCount; ++chunkNum) + { + if (candidateChunkCount >= totalVisibleChunkCount) + { + PX_ALWAYS_ASSERT(); + break; + } + const uint32_t chunkIndexInAsset = visibleChunkIndices[chunkNum]; + DestructibleStructure::Chunk& chunk = mStructure->chunks[chunkIndexInAsset + mFirstChunkIndex]; + DestructibleAssetParametersNS::Chunk_Type& chunkSource = mAsset->mParams->chunks.buf[chunkIndexInAsset]; + if (mDestructibleParameters.depthParameters[chunkSource.depth].ignoresRaycastCallbacks()) + { + continue; + } + if ((chunk.state & ChunkVisible) == 0) + { + continue; // In case a valid parentChunkIndex was passed in + } +#if USE_CHUNK_RWLOCK + DestructibleStructure::ChunkScopedReadLock chunkReadLock(chunk); +#endif + if (chunk.isDestroyed()) + { + continue; + } + + if (dynamicStateFlags != DestructibleActorRaycastFlags::AllChunks) + { + if ((chunk.state & ChunkDynamic)==0) + { + if ((flags & DestructibleActorRaycastFlags::StaticChunks) == 0) + { + continue; + } + } + else + { + if ((flags & DestructibleActorRaycastFlags::DynamicChunks) == 0) + { + continue; + } + } + } + + PxTransform& tm = chunkTMs[candidateChunkCount]; + tm = mStructure->getChunkGlobalPose(chunk); // Cache this off + IndexedReal& chunkProjectedMin = chunkProjectedMinima[candidateChunkCount]; + + if (sweep) + { + // Project chunk bounds along displacement direction + PxVec3 rM = tm.q.rotateInv(pxWorldDisp); + const float chunkProjectedCenter = rM.dot(chunk.localSphereCenter) + pxWorldDisp.dot(tm.p); + PxVec3 chunkLocalExtents = mAsset->getChunkShapeLocalBounds(chunkIndexInAsset).getExtents(); + chunkLocalExtents = chunkLocalExtents.multiply(getScale()); + const float chunkProjectedRadius = chunkLocalExtents.x * PxAbs(rM.x) + + chunkLocalExtents.y * PxAbs(rM.y) + + chunkLocalExtents.z * PxAbs(rM.z); + chunkProjectedMin.value = chunkProjectedCenter - chunkProjectedRadius; + if (boxProjectedMin >= chunkProjectedCenter + chunkProjectedRadius || boxSweptMax <= chunkProjectedMin.value) + { + // Beyond or before projected sweep + continue; + } + + // Perform "corridor test" + const PxVec3 X = tm.transform(chunk.localSphereCenter) - worldBoxCenter; + const float sumRadius = boxBSphereRadius + chunk.localSphereRadius; + const float Xv = X.dot(pxWorldDisp); + if (worldDisp2 * (X.magnitudeSquared() - sumRadius * sumRadius) >= Xv * Xv) + { + // Outside of corridor + continue; + } + } + else + { + // Overlap test + const PxVec3 X = tm.transform(chunk.localSphereCenter) - worldBoxCenter; + const float sumRadius = boxBSphereRadius + chunk.localSphereRadius; + if (X.magnitudeSquared() >= sumRadius * sumRadius) + { + continue; + } + } + + // We'll keep this one + chunkProjectedMin.index = candidateChunkCount; + chunkIndices[candidateChunkCount++] = chunkIndexInAsset; +#if USE_CHUNK_RWLOCK + chunk.lock->lockReader(); // Add another read lock, be sure to unlock after use in next loop +#endif + } + + // Sort chunk bounds projected minima + if (sweep && candidateChunkCount > 1) + { + combsort(chunkProjectedMinima, candidateChunkCount); + } + + uint32_t candidateChunkNum = 0; + for (; candidateChunkNum < candidateChunkCount; ++candidateChunkNum) + { + IndexedReal& indexedChunkMin = chunkProjectedMinima[candidateChunkNum]; + if (sweep && minTime <= (indexedChunkMin.value - boxProjectedMax)*recipWorldDisp2) + { + // Early-out + break; + } + uint16_t chunkIndexInAsset = (uint16_t)chunkIndices[indexedChunkMin.index]; +#if USE_CHUNK_RWLOCK + DestructibleStructure::Chunk& chunk = mStructure->chunks[chunkIndexInAsset + mFirstChunkIndex]; +#endif + for (uint32_t hullIndex = mAsset->getChunkHullIndexStart(chunkIndexInAsset); hullIndex < mAsset->getChunkHullIndexStop(chunkIndexInAsset); ++hullIndex) + { + ConvexHullImpl& chunkSourceConvexHull = mAsset->chunkConvexHulls[hullIndex]; + float in = minRayT; + float out = maxRayT; + PxVec3 n; + PxVec3 pxWorldBoxAxes[3]; + pxWorldBoxAxes[0] = worldBoxAxes[0]; + pxWorldBoxAxes[1] = worldBoxAxes[1]; + pxWorldBoxAxes[2] = worldBoxAxes[2]; + const bool hit = pointSweep ? (/* overlapLineSegmentAABBCached(rayorig, segmentCache, chunkSource.bounds) && */ + chunkSourceConvexHull.rayCast(in, out, rayorig, raydir, chunkTMs[indexedChunkMin.index], getScale(), &n)) : + chunkSourceConvexHull.obbSweep(in, out, worldBoxCenter, worldBoxExtents, pxWorldBoxAxes, pxWorldDisp, chunkTMs[indexedChunkMin.index], getScale(), &n); + if (hit) + { + if (out > minRayT && in < minTime) + { + minTime = in; + normal = n; + parentChunkIndex = chunkIndexInAsset != (uint16_t)DestructibleAssetImpl::InvalidChunkIndex ? chunkIndexInAsset : (uint16_t)ModuleDestructibleConst::INVALID_CHUNK_INDEX; + } + } + } +#if USE_CHUNK_RWLOCK + chunk.lock->unlockReader(); // Releasing lock from end of previous loop +#endif + } + +#if USE_CHUNK_RWLOCK + // Release remaining locks + for (; candidateChunkNum < candidateChunkCount; ++candidateChunkNum) + { + IndexedReal& indexedChunkMin = chunkProjectedMinima[candidateChunkNum]; + uint16_t chunkIndexInAsset = (uint16_t)chunkIndices[indexedChunkMin.index]; + DestructibleStructure::Chunk& chunk = mStructure->chunks[chunkIndexInAsset + mFirstChunkIndex]; + chunk.lock->unlockReader(); + } +#endif + } + +#if USE_DESTRUCTIBLE_RWLOCK + mLock->unlockReader(); +#endif + + if (minTime != PX_MAX_F32) + { + time = minTime; + } + + bool accurateRaycasts = (mDestructibleParameters.flags & DestructibleParametersFlag::ACCURATE_RAYCASTS) != 0; + + if (((uint32_t)flags)&DestructibleActorRaycastFlags::ForceAccurateRaycastsOn) + { + accurateRaycasts = true; + } + + if (((uint32_t)flags)&DestructibleActorRaycastFlags::ForceAccurateRaycastsOff) + { + accurateRaycasts = false; + } + + if (!accurateRaycasts) + { + return parentChunkIndex; + } + + int32_t chunkIndex = parentChunkIndex; + + { + PX_PROFILE_ZONE("DestructibleRayCastFindDeepestChunk", GetInternalApexSDK()->getContextId()); + + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + +#if USE_DESTRUCTIBLE_RWLOCK + mLock->lockReader(); +#endif + + while (parentChunkIndex != ModuleDestructibleConst::INVALID_CHUNK_INDEX) + { + DestructibleAssetParametersNS::Chunk_Type& source = mAsset->mParams->chunks.buf[parentChunkIndex]; + float firstInTime = PX_MAX_F32; + parentChunkIndex = ModuleDestructibleConst::INVALID_CHUNK_INDEX; + const uint16_t childStop = source.numChildren; + if (childStop > 0 && mDestructibleParameters.depthParameters[source.depth + 1].ignoresRaycastCallbacks()) + { + // Children ignore raycasts. We may stop here. + break; + } + for (uint16_t childNum = 0; childNum < childStop; ++childNum) + { + const uint16_t childIndexInAsset = uint16_t(source.firstChildIndex + childNum); + DestructibleStructure::Chunk& child = mStructure->chunks[childIndexInAsset + mFirstChunkIndex]; +#if USE_CHUNK_RWLOCK + DestructibleStructure::ChunkScopedReadLock chunkReadLock(child); +#endif + if (!child.isDestroyed()) + { + for (uint32_t hullIndex = mAsset->getChunkHullIndexStart(childIndexInAsset); hullIndex < mAsset->getChunkHullIndexStop(childIndexInAsset); ++hullIndex) + { + ConvexHullImpl& childSourceConvexHull = mAsset->chunkConvexHulls[hullIndex]; + float in = minRayT; + float out = maxRayT; + PxVec3 n; + PxVec3 pxWorldBoxAxes[3]; + pxWorldBoxAxes[0] = worldBoxAxes[0]; + pxWorldBoxAxes[1] = worldBoxAxes[1]; + pxWorldBoxAxes[2] = worldBoxAxes[2]; + const bool hit = pointSweep ? (/* overlapLineSegmentAABBCached(rayorig, segmentCache, childSource.bounds) && */ + childSourceConvexHull.rayCast(in, out, rayorig, raydir, mStructure->getChunkGlobalPose(child), getScale(), &n)) : + childSourceConvexHull.obbSweep(in, out, worldBoxCenter, worldBoxExtents, pxWorldBoxAxes, pxWorldDisp, mStructure->getChunkGlobalPose(child), getScale(), &n); + if (hit) + { + if (out > minRayT && in < firstInTime) + { + firstInTime = in; + normal = n; + parentChunkIndex = childIndexInAsset != (int32_t)DestructibleAssetImpl::InvalidChunkIndex ? childIndexInAsset : (int32_t)ModuleDestructibleConst::INVALID_CHUNK_INDEX; + if (child.state & ChunkVisible) + { + chunkIndex = parentChunkIndex; + } + } + } + } + } + } + if (firstInTime != PX_MAX_F32) + { + time = firstInTime; + } + } + + } + +#if USE_DESTRUCTIBLE_RWLOCK + mLock->unlockReader(); +#endif + + return chunkIndex; +} + +int32_t DestructibleActorImpl::pointOrOBBSweepStatic(float& time, PxVec3& normal, const PxVec3& worldBoxCenter, const PxVec3& worldBoxExtents, const PxMat33& worldBoxRT, const PxVec3& pxWorldDisp, + DestructibleActorRaycastFlags::Enum flags, int32_t parentChunkIndex) const +{ + PX_PROFILE_ZONE("DestructibleActorPointOrOBBSweepStatic", GetInternalApexSDK()->getContextId()); + + PX_ASSERT((flags & DestructibleActorRaycastFlags::DynamicChunks) == 0); + + // use the scene lock to protect chunk data for + // multi-threaded obbSweep calls on destructible actors + // (different lock would be good, but mixing locks can cause deadlocks) + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + + // parentChunkIndex out of range + if (parentChunkIndex >= mAsset->mParams->chunks.arraySizes[0]) + { + return ModuleDestructibleConst::INVALID_CHUNK_INDEX; + } + + DestructibleAssetParametersNS::Chunk_Type* sourceChunks = mAsset->mParams->chunks.buf; + + // parentChunkIndex is valid, but the chunk is invisible, beyond the LOD, or ignores raycasts + if (parentChunkIndex >= 0) + { + if ((getStructure()->chunks[parentChunkIndex + getFirstChunkIndex()].state & ChunkVisible) == 0) + { + return ModuleDestructibleConst::INVALID_CHUNK_INDEX; + } + } + else + { + // From now on, we treat parentChunkIndex < 0 as parentChunkIndex = 0 and iterate + parentChunkIndex = 0; + } + + if (sourceChunks[parentChunkIndex].depth > (uint16_t)getLOD() || mDestructibleParameters.depthParameters[sourceChunks[parentChunkIndex].depth].ignoresRaycastCallbacks()) + { + return ModuleDestructibleConst::INVALID_CHUNK_INDEX; + } + + // TODO: the normal is not always output, for instance, when accurateRaycasts is false, can we generate a decent normal in this case? + const bool pointSweep = (worldBoxExtents.magnitudeSquared() == 0.0f); + + const PxVec3 worldBoxAxes[3] = { worldBoxRT.column0, worldBoxRT.column1, worldBoxRT.column2 }; + const PxVec3 worldDisp = pxWorldDisp; + + float minRayT; + float maxRayT; + if ((flags & DestructibleActorRaycastFlags::SegmentIntersect) != 0) + { + minRayT = 0.0f; + maxRayT = 1.0f; + } + else + { + minRayT = -PX_MAX_F32; + maxRayT = PX_MAX_F32; + } + + PxVec3 rayorig; + PxVec3 raydir; + if (pointSweep) + { + rayorig = worldBoxCenter; + raydir = worldDisp; + } + + // Must find an intersecting visible chunk. + + PxMat44 staticTM; + bool success = getGlobalPoseForStaticChunks(staticTM); + if (!success) + { + return ModuleDestructibleConst::INVALID_CHUNK_INDEX; + } + PxTransform chunkTM(staticTM); // We'll keep updating the position for this one + + bool accurateRaycasts = (mDestructibleParameters.flags & DestructibleParametersFlag::ACCURATE_RAYCASTS) != 0; + if (((uint32_t)flags)&DestructibleActorRaycastFlags::ForceAccurateRaycastsOn) + { + accurateRaycasts = true; + } + if (((uint32_t)flags)&DestructibleActorRaycastFlags::ForceAccurateRaycastsOff) + { + accurateRaycasts = false; + } + + int32_t chunkFoundIndex = ModuleDestructibleConst::INVALID_CHUNK_INDEX; + float minTime = PX_MAX_F32; + PxVec3 normalAtFirstHit(0.0f, 0.0f, 1.0f); + + // Start with the parentChunkIndex. This stack is a stack of chunk ranges, stored LSW = low, MSW = high + physx::Array<uint32_t> stack; + stack.pushBack(((uint32_t)parentChunkIndex+1)<<16 | (uint32_t)parentChunkIndex); + + while (stack.size() > 0) + { + const uint32_t range = stack.popBack(); + uint32_t chunkIndex = (range&0xFFFF) + getFirstChunkIndex(); + uint32_t chunkIndexStop = (range>>16) + getFirstChunkIndex(); + const uint16_t depth = sourceChunks[range&0xFFFF].depth; + const bool atLimit = depth >= getLOD() || depth >= mAsset->mParams->depthCount - 1 || mDestructibleParameters.depthParameters[depth+1].ignoresRaycastCallbacks(); + + for (; chunkIndex < chunkIndexStop; ++chunkIndex) + { + const DestructibleStructure::Chunk& chunk = getStructure()->chunks[chunkIndex]; + if ((chunk.state & ChunkDynamic) != 0) + { + continue; + } + chunkTM.p = staticTM.transform(chunk.localOffset); + const uint16_t chunkIndexInAsset = (uint16_t)(chunkIndex - getFirstChunkIndex()); + for (uint32_t hullIndex = mAsset->getChunkHullIndexStart(chunkIndexInAsset); hullIndex < mAsset->getChunkHullIndexStop(chunkIndexInAsset); ++hullIndex) + { + ConvexHullImpl& chunkSourceConvexHull = mAsset->chunkConvexHulls[hullIndex]; + float in = minRayT; + float out = maxRayT; + PxVec3 n; + bool hit; + if (pointSweep) + { + hit = chunkSourceConvexHull.rayCast(in, out, rayorig, raydir, chunkTM, getScale(), &n); + } + else + { + PxVec3 pxWorldBoxAxes[3]; + pxWorldBoxAxes[0] = worldBoxAxes[0]; + pxWorldBoxAxes[1] = worldBoxAxes[1]; + pxWorldBoxAxes[2] = worldBoxAxes[2]; + hit = chunkSourceConvexHull.obbSweep(in, out, worldBoxCenter, worldBoxExtents, pxWorldBoxAxes, pxWorldDisp, chunkTM, getScale(), &n); + } + + if (hit) + { + if (out > 0.0f && in < minTime) + { + const uint32_t firstChildIndexInAsset = (uint32_t)sourceChunks[chunkIndexInAsset].firstChildIndex; + const uint32_t childCount = (uint32_t)sourceChunks[chunkIndexInAsset].numChildren; + const bool hasChildren = !atLimit && childCount > 0; + + if (!accurateRaycasts) + { + if (chunk.state & ChunkVisible) + { + minTime = in; + normalAtFirstHit = n; + chunkFoundIndex = (int32_t)chunkIndex; + } + else + if (chunk.isDestroyed() && hasChildren) + { + stack.pushBack(((uint32_t)firstChildIndexInAsset+childCount)<<16 | (uint32_t)firstChildIndexInAsset); + } + } + else + { + if (!hasChildren) + { + minTime = in; + normalAtFirstHit = n; + chunkFoundIndex = (int32_t)chunkIndex; + } + else + { + stack.pushBack(((uint32_t)firstChildIndexInAsset+childCount)<<16 | (uint32_t)firstChildIndexInAsset); + } + } + } + } + } + } + } + + if (chunkFoundIndex == ModuleDestructibleConst::INVALID_CHUNK_INDEX || minTime == PX_MAX_F32) + { + return ModuleDestructibleConst::INVALID_CHUNK_INDEX; + } + + time = minTime; + normal = normalAtFirstHit; + + if (accurateRaycasts) + { + const DestructibleStructure::Chunk& chunkFound = getStructure()->chunks[(uint32_t)chunkFoundIndex]; + if ((chunkFound.state & ChunkVisible) == 0) + { + chunkFoundIndex = chunkFound.visibleAncestorIndex; + } + } + + return (int32_t)(chunkFoundIndex - getFirstChunkIndex()); +} + +void DestructibleActorImpl::applyDamage_immediate(DamageEvent& damageEvent) +{ + PX_PROFILE_ZONE("DestructibleApplyDamage_immediate", GetInternalApexSDK()->getContextId()); + + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + + const float paddingFactor = 0.01f; // To do - expose ? This is necessary now that we're using exact bounds testing. + const float padding = paddingFactor * (getOriginalBounds().maximum - getOriginalBounds().minimum).magnitude(); + + const uint32_t rayCastFlags = mDestructibleScene->m_damageApplicationRaycastFlags & DestructibleActorRaycastFlags::AllChunks; // Mask against chunk flags + + float time = 0; + PxVec3 fractureNormal(0.0f, 0.0f, 1.0f); + + int32_t chunkIndexInAsset = damageEvent.chunkIndexInAsset >= 0 ? damageEvent.chunkIndexInAsset : ModuleDestructibleConst::INVALID_CHUNK_INDEX; + + if (rayCastFlags != 0) + { + const PxVec3 worldRayOrig = damageEvent.position.isFinite() ? damageEvent.position : PxVec3(0.0f); + const PxVec3 worldRayDir = damageEvent.direction.isFinite() && !damageEvent.direction.isZero() ? damageEvent.direction : PxVec3(0.0f, 0.0f, 1.0f); + // TODO, even the direction isn't always normalized - PxVec3 fractureNormal(-worldRay.dir); + const int32_t actualHitChunk = rayCast(time, fractureNormal, worldRayOrig, worldRayDir, (DestructibleActorRaycastFlags::Enum)rayCastFlags, chunkIndexInAsset); + if (actualHitChunk != ModuleDestructibleConst::INVALID_CHUNK_INDEX) + { + chunkIndexInAsset = actualHitChunk; + } + } + else + if (mDestructibleParameters.fractureImpulseScale != 0.0f) + { + // Unfortunately, we need to do *some* kind of bounds check to get a good outward-pointing normal, if mDestructibleParameters.fractureImpulseScale != 0 + // We'll make this as inexpensive as possible, and raycast against the depth 0 chunk + PxTransform tm(getInitialGlobalPose()); + const PxVec3 pos = damageEvent.position.isFinite() ? damageEvent.position : PxVec3(0.0f); + const PxVec3 dir = damageEvent.direction.isFinite() ? damageEvent.direction : PxVec3(0.0f, 0.0f, 1.0f); + for (uint32_t hullIndex = mAsset->getChunkHullIndexStart(0); hullIndex < mAsset->getChunkHullIndexStop(0); ++hullIndex) + { + ConvexHullImpl& chunkSourceConvexHull = mAsset->chunkConvexHulls[hullIndex]; + float in = -PX_MAX_F32; + float out = PX_MAX_F32; + float minTime = PX_MAX_F32; + PxVec3 n; + if (chunkSourceConvexHull.rayCast(in, out, pos, dir, tm, getScale(), &n)) + { + if (in < minTime) + { + minTime = in; + fractureNormal = n; + } + } + } + } + + PX_ASSERT(fractureNormal.isNormalized()); + + if (chunkIndexInAsset == ModuleDestructibleConst::INVALID_CHUNK_INDEX) + { + PX_ASSERT(0 == (DamageEvent::UseRadius & damageEvent.flags)); + damageEvent.flags |= DamageEvent::Invalid; + return; + } + + damageEvent.chunkIndexInAsset = chunkIndexInAsset; + damageEvent.position += damageEvent.direction * time; + + float damage = damageEvent.damage; + if (mDestructibleParameters.damageCap > 0) + { + damage = PxMin(damage, mDestructibleParameters.damageCap); + } + + DestructibleStructure::Chunk& chunk = mStructure->chunks[damageEvent.chunkIndexInAsset + mFirstChunkIndex]; + if (!(chunk.state & ChunkVisible)) + { + return; + } + + // For probabilistic chunk deletion + uint32_t possibleDeleteChunks = 0; + float totalDeleteChunkRelativeDamage = 0.0f; + + uint32_t totalFractureCount = 0; + PxRigidDynamic& actor = *mStructure->getChunkActor(chunk); + for (uint32_t i = 0; i < actor.getNbShapes(); ++i) + { + PxShape* shape; + actor.getShapes(&shape, 1, i); + DestructibleStructure::Chunk* chunk = mStructure->dscene->getChunk(shape); + if (chunk != NULL && chunk->isFirstShape(shape)) // BRG OPTIMIZE + { + PX_ASSERT(mStructure->dscene->mDestructibles.direct(chunk->destructibleID)->mStructure == mStructure); + if ((chunk->state & ChunkVisible) != 0) + { + // Damage coloring: + DestructibleActorImpl* destructible = mStructure->dscene->mDestructibles.direct(chunk->destructibleID); + if (destructible->useDamageColoring()) + { + if (destructible->applyDamageColoring(chunk->indexInAsset, damageEvent.position, damage, 0.0f)) + { + destructible->collectDamageColoring(chunk->indexInAsset, damageEvent.position, damage, 0.0f); + } + } + + // specify the destructible asset because we're in a structure, it may not be this actor's asset + DestructibleAssetParametersNS::Chunk_Type& source = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk->indexInAsset]; + + const uint16_t stopDepth = destructible->getParams()->destructibleParameters.damageDepthLimit < uint16_t(UINT16_MAX - source.depth) ? + uint16_t(destructible->getParams()->destructibleParameters.damageDepthLimit + source.depth) : static_cast<uint16_t>(UINT16_MAX); + + totalFractureCount += mStructure->damageChunk(*chunk, damageEvent.position, damageEvent.direction, damageEvent.isFromImpact(), damage, 0.0f, + damageEvent.fractures, possibleDeleteChunks, totalDeleteChunkRelativeDamage, damageEvent.maxDepth, (uint32_t)source.depth, stopDepth, padding); + } + } + } + + // For probabilistic chunk deletion + float deletionFactor = getDestructibleParameters().debrisDestructionProbability; + if (totalDeleteChunkRelativeDamage > 0.0f) + { + deletionFactor *= (float)possibleDeleteChunks/totalDeleteChunkRelativeDamage; + } + + for (uint32_t depth = 0; depth <= damageEvent.maxDepth; ++depth) + { + physx::Array<FractureEvent>& fractureEventBuffer = damageEvent.fractures[depth]; + for (uint32_t i = 0; i < fractureEventBuffer.size(); ++i) + { + FractureEvent& fractureEvent = fractureEventBuffer[i]; + DestructibleActorImpl* destructible = mStructure->dscene->mDestructibles.direct(fractureEvent.destructibleID); + uint32_t affectedIndex = fractureEvent.chunkIndexInAsset + destructible->mFirstChunkIndex; + DestructibleStructure::Chunk& affectedChunk = mStructure->chunks[affectedIndex]; + if (!affectedChunk.isDestroyed()) + { + const float deletionProbability = deletionFactor*fractureEvent.deletionWeight; + if (deletionProbability > 0.0f && mStructure->dscene->mModule->mRandom.getUnit() < deletionProbability) + { + fractureEvent.flags |= FractureEvent::CrumbleChunk; + } + + // Compute impulse + fractureEvent.impulse = mStructure->getChunkWorldCentroid(affectedChunk) - damageEvent.position; + fractureEvent.impulse.normalize(); + fractureEvent.impulse *= fractureEvent.damageFraction * damageEvent.momentum; + fractureEvent.impulse += fractureNormal * mDestructibleParameters.fractureImpulseScale; + fractureEvent.position = damageEvent.position; + if (damageEvent.isFromImpact()) + { + fractureEvent.flags |= FractureEvent::DamageFromImpact; + } + if (0 != (DamageEvent::SyncDirect & damageEvent.flags)) + { + PX_ASSERT(0 == (FractureEvent::SyncDerived & fractureEvent.flags)); + fractureEvent.flags |= FractureEvent::SyncDerived; + } + } + } + } +} + +void DestructibleActorImpl::applyRadiusDamage_immediate(DamageEvent& damageEvent) +{ + PX_PROFILE_ZONE("DestructibleApplyRadiusDamage_immediate", GetInternalApexSDK()->getContextId()); + + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + + const float damageCap = mDestructibleParameters.damageCap > 0 ? mDestructibleParameters.damageCap : PX_MAX_F32; + + uint32_t totalFractureCount = 0; + + const float paddingFactor = 0.01f; // To do - expose ? This is necessary now that we're using exact bounds testing. + const float padding = paddingFactor * (getOriginalBounds().maximum - getOriginalBounds().minimum).magnitude(); + + // For probabilistic chunk deletion + uint32_t possibleDeleteChunks = 0; + float totalDeleteChunkRelativeDamage = 0.0f; + + const bool useLegacyDamageRadiusSpread = getUseLegacyDamageRadiusSpread(); + + // Should use scene query here + const uint16_t* chunkIndexPtr = mVisibleChunks.usedIndices(); + const uint16_t* chunkIndexPtrStop = chunkIndexPtr + mVisibleChunks.usedCount(); + bool needSaveDamageColor = false; + while (chunkIndexPtr < chunkIndexPtrStop) + { + uint16_t chunkIndex = *chunkIndexPtr++; + DestructibleStructure::Chunk& chunk = mStructure->chunks[chunkIndex + mFirstChunkIndex]; + + // Legacy behavior + float minRadius = 0.0f; + float maxRadius = damageEvent.radius; + float falloff = 1.0f; + const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = getBehaviorGroup(chunkIndex); + if (!useLegacyDamageRadiusSpread) + { + // New behavior + minRadius = behaviorGroup.damageSpread.minimumRadius; + maxRadius = minRadius + damageEvent.radius*behaviorGroup.damageSpread.radiusMultiplier; + falloff = behaviorGroup.damageSpread.falloffExponent; + } + + // Damage coloring: + if (useDamageColoring()) + { + if (applyDamageColoring(chunk.indexInAsset, damageEvent.position, damageEvent.damage, damageEvent.radius)) + { + needSaveDamageColor = true; + } + } + + const PxVec3 chunkCentroid = mStructure->getChunkWorldCentroid(chunk); + PxVec3 dir = chunkCentroid - damageEvent.position; + float dist = dir.normalize() - chunk.localSphereRadius; + if (dist < maxRadius) + { + float damageFraction = 1; + if (useLegacyDamageRadiusSpread) + { + dist = PxMax(dist, 0.0f); + if (falloff && damageEvent.radius > 0.0f) + { + damageFraction -= dist / damageEvent.radius; + } + } + const float effectiveDamage = PxMin(damageEvent.damage * damageFraction, damageCap); + DestructibleAssetParametersNS::Chunk_Type& source = mAsset->mParams->chunks.buf[chunk.indexInAsset]; + + const uint16_t stopDepth = getParams()->destructibleParameters.damageDepthLimit < uint16_t(UINT16_MAX - source.depth) ? + uint16_t(getParams()->destructibleParameters.damageDepthLimit + source.depth) : uint16_t(UINT16_MAX); + + totalFractureCount += mStructure->damageChunk(chunk, damageEvent.position, damageEvent.direction, damageEvent.isFromImpact(), effectiveDamage, damageEvent.radius, + damageEvent.fractures, possibleDeleteChunks, totalDeleteChunkRelativeDamage, damageEvent.maxDepth, (uint32_t)source.depth, stopDepth, padding); + } + } + + if (needSaveDamageColor) + { + collectDamageColoring(ModuleDestructibleConst::INVALID_CHUNK_INDEX, damageEvent.position, damageEvent.damage, damageEvent.radius); + } + + // For probabilistic chunk deletion + float deletionFactor = getDestructibleParameters().debrisDestructionProbability; + if (totalDeleteChunkRelativeDamage > 0.0f) + { + deletionFactor *= (float)possibleDeleteChunks/totalDeleteChunkRelativeDamage; + } + + for (uint32_t depth = 0; depth <= damageEvent.maxDepth; ++depth) + { + physx::Array<FractureEvent>& fractureEventBuffer = damageEvent.fractures[depth]; + for (uint32_t i = 0; i < fractureEventBuffer.size(); ++i) + { + FractureEvent& fractureEvent = fractureEventBuffer[i]; + DestructibleActorImpl* destructible = mStructure->dscene->mDestructibles.direct(fractureEvent.destructibleID); + uint32_t affectedIndex = fractureEvent.chunkIndexInAsset + destructible->mFirstChunkIndex; + DestructibleStructure::Chunk& affectedChunk = mStructure->chunks[affectedIndex]; + if (!affectedChunk.isDestroyed()) + { + const float deletionProbability = deletionFactor*fractureEvent.deletionWeight; + if (deletionProbability > 0.0f && mStructure->dscene->mModule->mRandom.getUnit() < deletionProbability) + { + fractureEvent.flags |= FractureEvent::CrumbleChunk; + } + + fractureEvent.impulse = mStructure->getChunkWorldCentroid(affectedChunk) - damageEvent.position; + fractureEvent.impulse.normalize(); + fractureEvent.impulse *= fractureEvent.damageFraction * damageEvent.momentum; + + // Get outward normal for fractureImpulseScale, if this chunk is part of a larger island + PxVec3 fractureNormal(0.0f); + if (!mStructure->chunkIsSolitary(affectedChunk)) + { + PxRigidDynamic& chunkActor = *mStructure->getChunkActor(affectedChunk); + // Search neighbors + DestructibleActorImpl* destructible = mStructure->dscene->mDestructibles.direct(affectedChunk.destructibleID); + const PxVec3 chunkPos = destructible->getChunkPose(affectedChunk.indexInAsset).p.multiply(destructible->getScale()); + const uint32_t indexInStructure = affectedChunk.indexInAsset + destructible->getFirstChunkIndex(); + for (uint32_t overlapN = mStructure->firstOverlapIndices[indexInStructure]; overlapN < mStructure->firstOverlapIndices[indexInStructure + 1]; ++overlapN) + { + DestructibleStructure::Chunk& overlapChunk = mStructure->chunks[mStructure->overlaps[overlapN]]; + if (!overlapChunk.isDestroyed() && mStructure->getChunkActor(overlapChunk) == &chunkActor) + { + DestructibleActorImpl* overlapDestructible = mStructure->dscene->mDestructibles.direct(overlapChunk.destructibleID); + fractureNormal += chunkPos - overlapDestructible->getChunkPose(overlapChunk.indexInAsset).p.multiply(overlapDestructible->getScale()); + } + } + if (fractureNormal.magnitudeSquared() != 0.0f) + { + fractureNormal.normalize(); + fractureEvent.impulse += fractureNormal * mDestructibleParameters.fractureImpulseScale; + } + } + + fractureEvent.position = damageEvent.position; + if (damageEvent.isFromImpact()) + { + fractureEvent.flags |= FractureEvent::DamageFromImpact; + } + if (0 != (DamageEvent::SyncDirect & damageEvent.flags)) + { + PX_ASSERT(0 == (FractureEvent::SyncDerived & fractureEvent.flags)); + fractureEvent.flags |= FractureEvent::SyncDerived; + } + } + } + } +} + +void DestructibleActorImpl::setSkinnedOverrideMaterial(uint32_t index, const char* overrideMaterialName) +{ + RenderMeshActor* rma = getRenderMeshActor(DestructibleActorMeshType::Skinned); + if (rma != NULL) + { + rma->setOverrideMaterial(index, overrideMaterialName); + } +} + +void DestructibleActorImpl::setStaticOverrideMaterial(uint32_t index, const char* overrideMaterialName) +{ + RenderMeshActor* rma = getRenderMeshActor(DestructibleActorMeshType::Static); + if (rma != NULL) + { + rma->setOverrideMaterial(index, overrideMaterialName); + } +} + +void DestructibleActorImpl::setRuntimeFracturePattern(const char* /*fracturePatternName*/) +{ + // TODO: Implement + /* + ResourceProviderIntl* nrp = GetInternalApexSDK()->getInternalResourceProvider(); + if (nrp != NULL) + { + // do create before release, so we don't release the resource if the newID is the same as the old + ResID patternNS = GetInternalApexSDK()->getPatternNamespace(); + + ResID newID = nrp->createResource(patternNS, fracturePatternName); + nrp->releaseResource(mFracturePatternID); + + mFracturePatternID = newID; + // TODO: Aquire resource for fracture pattern + } + */ +} + +void DestructibleActorImpl::updateRenderResources(bool rewriteBuffers, void* userRenderData) +{ + + PX_PROFILE_ZONE("DestructibleUpdateRenderResources", GetInternalApexSDK()->getContextId()); + + //Should not be necessary anymore + //#if APEX_RUNTIME_FRACTURE + // { + // mRTActor->updateRenderResources(rewriteBuffers, userRenderData); + // } + //#endif + + // Render non-instanced meshes if we own them + if (mRenderable != NULL && mRenderable->getReferenceCount() == 1) + { + mRenderable->updateRenderResources(rewriteBuffers, userRenderData); + } +} + +void DestructibleActorImpl::dispatchRenderResources(UserRenderer& renderer) +{ + PX_PROFILE_ZONE("DestructibleDispatchRenderResources", GetInternalApexSDK()->getContextId()); + + // Dispatch non-instanced render resources if we own them + if (mRenderable != NULL && mRenderable->getReferenceCount() == 1) + { + mRenderable->dispatchRenderResources(renderer); + } + + // Should not be necessary anymore + //#if APEX_RUNTIME_FRACTURE + // mRTActor->dispatchRenderResources(renderer); + //#endif +} + +void DestructibleActorImpl::fillInstanceBuffers() +{ + if (mAsset->mParams->chunkInstanceInfo.arraySizes[0] == 0 && mAsset->mParams->scatterMeshIndices.arraySizes[0] == 0) + { + return; // No instancing for this asset + } + + PX_PROFILE_ZONE("DestructibleActor::fillInstanceBuffers", GetInternalApexSDK()->getContextId()); + + mInstancedBounds.setEmpty(); + + DestructibleAssetParametersNS::Chunk_Type* sourceChunks = mAsset->mParams->chunks.buf; + + Mutex::ScopedLock scopeLock(mAsset->m_chunkInstanceBufferDataLock); + + const float scatterAlpha = PxClamp(2.0f-getLOD(), 0.0f, 1.0f); + const bool alwaysDrawScatterMesh = mAsset->getScatterMeshAlwaysDrawFlag(); + // Iterate over all visible chunks + const uint16_t* indexPtr = mVisibleChunks.usedIndices(); + const uint16_t* indexPtrStop = indexPtr + mVisibleChunks.usedCount(); + DestructibleAssetParametersNS::InstanceInfo_Type* instanceDataArray = mAsset->mParams->chunkInstanceInfo.buf; + while (indexPtr < indexPtrStop) + { + const uint16_t index = *indexPtr++; + if (index < mAsset->getChunkCount()) + { + DestructibleAssetParametersNS::Chunk_Type& sourceChunk = sourceChunks[index]; + PxMat44 pose(getChunkPose(index)); + const PxMat33 poseScaledRotation = PxMat33(getScale().x*pose.getBasis(0), getScale().y*pose.getBasis(1), getScale().z*pose.getBasis(2)); + + // Instanced chunks + if ((sourceChunk.flags & DestructibleAssetImpl::Instanced) != 0) + { + PX_ASSERT(sourceChunk.meshPartIndex < mAsset->mParams->chunkInstanceInfo.arraySizes[0]); + DestructibleAssetImpl::ChunkInstanceBufferDataElement instanceDataElement; + const DestructibleAssetParametersNS::InstanceInfo_Type& instanceData = instanceDataArray[sourceChunk.meshPartIndex]; + const uint16_t instancedActorIndex = mAsset->m_instancedChunkActorMap[sourceChunk.meshPartIndex]; + Array<DestructibleAssetImpl::ChunkInstanceBufferDataElement>& instanceBufferData = mAsset->m_chunkInstanceBufferData[instancedActorIndex]; + instanceDataElement.translation = pose.getPosition();// + poseScaledRotation*instanceData.chunkPositionOffset; + instanceDataElement.scaledRotation = poseScaledRotation; + instanceDataElement.uvOffset = instanceData.chunkUVOffset; + instanceDataElement.localOffset = PxVec3(getScale().x*instanceData.chunkPositionOffset.x, getScale().y*instanceData.chunkPositionOffset.y, getScale().z*instanceData.chunkPositionOffset.z); + + // there shouldn't be any allocation here because of the reserve in DestructibleAsset::resetInstanceData + PX_ASSERT(instanceBufferData.size() < instanceBufferData.capacity()); + instanceBufferData.pushBack(instanceDataElement); + + const PxBounds3& partBounds = mAsset->renderMeshAsset->getBounds(instanceData.partIndex); + // Transform bounds + PxVec3 center, extents; + center = partBounds.getCenter(); + extents = partBounds.getExtents(); + center = poseScaledRotation.transform(center) + instanceDataElement.translation; + extents = PxVec3(PxAbs(poseScaledRotation(0, 0) * extents.x) + PxAbs(poseScaledRotation(0, 1) * extents.y) + PxAbs(poseScaledRotation(0, 2) * extents.z), + PxAbs(poseScaledRotation(1, 0) * extents.x) + PxAbs(poseScaledRotation(1, 1) * extents.y) + PxAbs(poseScaledRotation(1, 2) * extents.z), + PxAbs(poseScaledRotation(2, 0) * extents.x) + PxAbs(poseScaledRotation(2, 1) * extents.y) + PxAbs(poseScaledRotation(2, 2) * extents.z)); + mInstancedBounds.include(PxBounds3::centerExtents(center, extents)); + } + + // Scatter meshes + if (scatterAlpha > 0.0f || (sourceChunk.depth == 1 || alwaysDrawScatterMesh)) + { + const uint16_t scatterMeshStop = uint16_t(sourceChunk.firstScatterMesh + sourceChunk.scatterMeshCount); + for (uint16_t scatterMeshNum = sourceChunk.firstScatterMesh; scatterMeshNum < scatterMeshStop; ++scatterMeshNum) + { + const physx::PxU8 scatterMeshIndex = mAsset->mParams->scatterMeshIndices.buf[scatterMeshNum]; + const PxMat44& scatterMeshTransform = mAsset->mParams->scatterMeshTransforms.buf[scatterMeshNum]; + DestructibleAssetImpl::ScatterMeshInstanceInfo& scatterMeshInstanceInfo = mAsset->m_scatterMeshInstanceInfo[scatterMeshIndex]; + Array<DestructibleAssetImpl::ScatterInstanceBufferDataElement>& instanceBufferData = scatterMeshInstanceInfo.m_instanceBufferData; + DestructibleAssetImpl::ScatterInstanceBufferDataElement instanceDataElement; + instanceDataElement.translation = poseScaledRotation*scatterMeshTransform.getPosition() + pose.getPosition();// + poseScaledRotation*instanceData.chunkPositionOffset; + PxMat33 smTm33(scatterMeshTransform.column0.getXYZ(), + scatterMeshTransform.column1.getXYZ(), + scatterMeshTransform.column2.getXYZ()); + instanceDataElement.scaledRotation = poseScaledRotation*smTm33; + instanceDataElement.alpha = scatterAlpha; + instanceBufferData.pushBack(instanceDataElement); + // Not updating bounds for scatter meshes + } + } + } + } + + mRenderBounds = mNonInstancedBounds; + mRenderBounds.include(mInstancedBounds); + if (mRenderable != NULL) + { + mRenderable->setBounds(mRenderBounds); + } +} + +void DestructibleActorImpl::setRelativeTMs() +{ + mRelTM = NULL != mStructure ? mTM*mStructure->getActorForStaticChunksPose().inverseRT() : PxMat44(PxIdentity); +} + +/* Called during ApexScene::fetchResults(), after PhysXScene::fetchResults(). Sends new bone poses + * to ApexRenderMeshActor, then retrieves new world AABB. + */ + +void DestructibleActorImpl::setRenderTMs(bool processChunkPoseForSyncing /*= false*/) +{ + mNonInstancedBounds.setEmpty(); + + if (mRenderable) + { + mRenderable->lockRenderResources(); + } + + RenderMeshActor* skinnedRMA = getRenderMeshActor(DestructibleActorMeshType::Skinned); + + const bool syncWriteTM = processChunkPoseForSyncing && mSyncParams.isSyncFlagSet(DestructibleActorSyncFlags::CopyChunkTransform) && (NULL != mSyncParams.getChunkSyncState()); + const bool canSyncReadTM = processChunkPoseForSyncing && mSyncParams.isSyncFlagSet(DestructibleActorSyncFlags::ReadChunkTransform); + + if (skinnedRMA != NULL || syncWriteTM || canSyncReadTM) + { + if (skinnedRMA != NULL) + { + skinnedRMA->syncVisibility(false); // Using mRenderable->mRenderable->lockRenderResources() instead + } + // PX_ASSERT(asset->getRenderMeshAsset()->getPartCount() == asset->getChunkCount()); + + DestructibleAssetParametersNS::Chunk_Type* sourceChunks = mAsset->mParams->chunks.buf; + + // Iterate over all visible chunks + const uint16_t* indexPtr = mVisibleChunks.usedIndices(); + const uint16_t* indexPtrStop = indexPtr + mVisibleChunks.usedCount(); + + // TODO: Here we update all chunks although we practically know the chunks (active transforms) that have moved. Improve. [APEX-670] + + while (indexPtr < indexPtrStop) + { + const uint16_t index = *indexPtr++; + if (index < mAsset->getChunkCount()) + { + DestructibleAssetParametersNS::Chunk_Type& sourceChunk = sourceChunks[index]; + DestructibleStructure::Chunk & chunk = mStructure->chunks[mFirstChunkIndex + index]; + if (!chunk.isDestroyed() && (sourceChunk.flags & DestructibleAssetImpl::Instanced) == 0) + { + const bool syncReadTM = canSyncReadTM && (NULL != chunk.controlledChunk); + if (syncReadTM && !getDynamic(index)) + { + setDynamic(index, true); + } + + if (getDynamic(index) || !drawStaticChunksInSeparateMesh() || initializedFromState()) + { + PxTransform chunkPose; + bool isChunkPoseInit = false; + if (processChunkPoseForSyncing) + { + if (syncWriteTM) + { + const DestructibleChunkSyncState & chunkSyncState = *(mSyncParams.getChunkSyncState()); + PX_ASSERT(NULL != &chunkSyncState); + if(!chunkSyncState.disableTransformBuffering && + (chunkSyncState.excludeSleepingChunks ? !isPxActorSleeping(*(mStructure->getChunkActor(chunk))) : true) && + (chunkSyncState.chunkTransformCopyDepth >= sourceChunk.depth)) + { + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + + const PxTransform calculatedChunkPose = getChunkPose(index); + mSyncParams.pushCachedChunkTransform(CachedChunk(index, calculatedChunkPose)); + chunkPose = calculatedChunkPose; + isChunkPoseInit = true; + } + } + if (syncReadTM) + { + const PxTransform controlledChunkPose(chunk.controlledChunk->chunkPosition, chunk.controlledChunk->chunkOrientation); + { + SCOPED_PHYSX_LOCK_WRITE(getDestructibleScene()->getApexScene()); + setChunkPose(index, controlledChunkPose); + } + chunk.controlledChunk = NULL; + chunkPose = controlledChunkPose; + isChunkPoseInit = true; + } + if (!isChunkPoseInit) + { + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + chunkPose = getChunkPose(index); + isChunkPoseInit = true; + } + } + else + { + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mApexScene); + chunkPose = getChunkPose(index); + isChunkPoseInit = true; + } + PX_ASSERT(isChunkPoseInit); + if (skinnedRMA != NULL) + { + skinnedRMA->setTM(chunkPose, getScale(), sourceChunk.meshPartIndex); + } + } + } + } + } + + + if (skinnedRMA != NULL) + { + skinnedRMA->updateBounds(); + mNonInstancedBounds.include(skinnedRMA->getBounds()); + } + } + + RenderMeshActor* staticRMA = getRenderMeshActor(DestructibleActorMeshType::Static); + + // If a static mesh exists, set its (single) tm from the destructible's tm + if (staticRMA != NULL) + { + staticRMA->syncVisibility(false); // Using mRenderable->mRenderable->lockRenderResources() instead + PxMat44 pose; + if (!getGlobalPoseForStaticChunks(pose)) + { + pose = PxMat44(PxIdentity); // Should not be rendered, but just in case we'll set pose to something sane. + } + staticRMA->setTM(pose, getScale()); + staticRMA->updateBounds(); + mNonInstancedBounds.include(staticRMA->getBounds()); + } + +#if APEX_RUNTIME_FRACTURE + if(mRenderable) + { + mRenderable->getRTrenderable().updateRenderCache(mRTActor); + } +#endif + + if (mNonInstancedBounds.isEmpty()) // This can occur if we have no renderable + { + const uint16_t* indexPtr = mVisibleChunks.usedIndices(); + const uint16_t* indexPtrStop = indexPtr + mVisibleChunks.usedCount(); + while (indexPtr < indexPtrStop) + { + const uint16_t index = *indexPtr++; + if (index < mAsset->getChunkCount()) + { + const PxMat44 pose(getChunkPose(index)); + for (uint32_t hullIndex = mAsset->getChunkHullIndexStart(index); hullIndex < mAsset->getChunkHullIndexStop(index); ++hullIndex) + { + const ConvexHullImpl& chunkSourceConvexHull = mAsset->chunkConvexHulls[hullIndex]; + PxBounds3 chunkConvexHullBounds = chunkSourceConvexHull.getBounds(); + // Apply scale + chunkConvexHullBounds.minimum = chunkConvexHullBounds.minimum.multiply(getScale()); + chunkConvexHullBounds.maximum = chunkConvexHullBounds.maximum.multiply(getScale()); + // Apply rotation and translation + const PxVec3 extent = chunkConvexHullBounds.getExtents(); + const PxVec3 newExtent( + PxAbs(pose.column0.x*extent.x) + PxAbs(pose.column1.x*extent.y) + PxAbs(pose.column2.x*extent.z), + PxAbs(pose.column0.y*extent.x) + PxAbs(pose.column1.y*extent.y) + PxAbs(pose.column2.y*extent.z), + PxAbs(pose.column0.z*extent.x) + PxAbs(pose.column1.z*extent.y) + PxAbs(pose.column2.z*extent.z)); + const PxVec3 center = pose.transform(chunkConvexHullBounds.getCenter()); + mNonInstancedBounds.include(PxBounds3(center - newExtent, center + newExtent)); + } + } + } + } + + mRenderBounds = mNonInstancedBounds; + mRenderBounds.include(mInstancedBounds); + if (mRenderable != NULL) + { + mRenderable->unlockRenderResources(); + mRenderable->setBounds(mRenderBounds); + } +} + +void DestructibleActorImpl::setActorObjDescFlags(PhysXObjectDescIntl* actorObjDesc, uint32_t depth) const +{ + const DestructibleDepthParameters& depthParameters = mDestructibleParameters.depthParameters[depth]; + actorObjDesc->setIgnoreTransform(depthParameters.ignoresPoseUpdates()); + actorObjDesc->setIgnoreRaycasts(depthParameters.ignoresRaycastCallbacks()); + actorObjDesc->setIgnoreContacts(depthParameters.ignoresContactCallbacks()); + for (uint32_t i = PhysXActorFlags::DEPTH_PARAM_USER_FLAG_0; i <= PhysXActorFlags::DEPTH_PARAM_USER_FLAG_3; ++i) + { + actorObjDesc->setUserDefinedFlag(i, depthParameters.hasUserFlagSet(i)); + } + actorObjDesc->setUserDefinedFlag(PhysXActorFlags::CREATED_THIS_FRAME, true); + actorObjDesc->setUserDefinedFlag(PhysXActorFlags::IS_SLEEPING, true); +} + +void DestructibleActorImpl::setGlobalPose(const PxMat44& pose) +{ + if (!isChunkDestroyed(0) && getDynamic(0)) + { + setChunkPose(0, PxTransform(pose)); + } + else + { + setGlobalPoseForStaticChunks(pose); + } +} + +void DestructibleActorImpl::setGlobalPoseForStaticChunks(const PxMat44& pose) +{ + if (mStructure != NULL && mStructure->actorForStaticChunks != NULL) + { + const PxMat44 actorForStaticChunkPose = mRelTM.inverseRT() * pose; + { + SCOPED_PHYSX_LOCK_WRITE(mStructure->actorForStaticChunks->getScene()); + mStructure->actorForStaticChunks->setKinematicTarget(PxTransform(actorForStaticChunkPose)); + } + for (uint32_t meshType = 0; meshType < DestructibleActorMeshType::Count; ++meshType) + { + RenderMeshActor* renderMeshActor = getRenderMeshActor((DestructibleActorMeshType::Enum)meshType); + if (renderMeshActor != NULL) + { + renderMeshActor->updateBounds(); + } + } + + } + + wakeForEvent(); +} + +bool DestructibleActorImpl::getGlobalPoseForStaticChunks(PxMat44& pose) const +{ + if (mStructure != NULL && mStructure->actorForStaticChunks != NULL) + { + if (NULL != mStructure->actorForStaticChunks) + pose = mRelTM * mStructure->getActorForStaticChunksPose(); + else + pose = mTM; + return true; + } + + return false; +} + +void DestructibleActorImpl::setChunkPose(uint32_t index, PxTransform worldPose) +{ + PX_ASSERT(mStructure != NULL); + PX_ASSERT(index + mFirstChunkIndex < mStructure->chunks.size()); + PX_ASSERT(!mStructure->chunks[index + mFirstChunkIndex].isDestroyed()); + DestructibleStructure::Chunk & chunk = mStructure->chunks[index + mFirstChunkIndex]; + PX_ASSERT(chunk.state & ChunkDynamic); + mStructure->setChunkGlobalPose(chunk, worldPose); +} + +void DestructibleActorImpl::setLinearVelocity(const PxVec3& linearVelocity) +{ + // Only dynamic actors need their velocity set, and they'll all be in the skinned mesh + const uint16_t* indexPtr = getVisibleChunks(); + const uint16_t* indexPtrStop = indexPtr + getNumVisibleChunks(); + while (indexPtr < indexPtrStop) + { + DestructibleStructure::Chunk& chunk = mStructure->chunks[mFirstChunkIndex + *indexPtr++]; + if (chunk.state & ChunkDynamic) + { + PxRigidDynamic* actor = mStructure->getChunkActor(chunk); + if (actor != NULL) + { + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + actor->setLinearVelocity(linearVelocity); + } + } + } +} + +void DestructibleActorImpl::setAngularVelocity(const PxVec3& angularVelocity) +{ + // Only dynamic actors need their velocity set, and they'll all be in the skinned mesh + const uint16_t* indexPtr = getVisibleChunks(); + const uint16_t* indexPtrStop = indexPtr + getNumVisibleChunks(); + while (indexPtr < indexPtrStop) + { + DestructibleStructure::Chunk& chunk = mStructure->chunks[mFirstChunkIndex + *indexPtr++]; + if (chunk.state & ChunkDynamic) + { + PxRigidDynamic* actor = mStructure->getChunkActor(chunk); + if (actor != NULL) + { + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + actor->setAngularVelocity(angularVelocity); + } + } + } +} + +void DestructibleActorImpl::enableHardSleeping() +{ + mParams->useHardSleeping = true; +} + +void DestructibleActorImpl::disableHardSleeping(bool wake) +{ + if (!useHardSleeping()) + { + return; // Nothing to do + } + + if (mStructure == NULL || mStructure->dscene == NULL || mStructure->dscene->mModule == NULL) + { + return; // Can't do anything + } + + mParams->useHardSleeping = false; + + Bank<DormantActorEntry, uint32_t>& dormantActors = mStructure->dscene->mDormantActors; + for (uint32_t dormantActorRank = dormantActors.usedCount(); dormantActorRank--;) + { + const uint32_t dormantActorIndex = dormantActors.usedIndices()[dormantActorRank]; + DormantActorEntry& dormantActorEntry = dormantActors.direct(dormantActorIndex); + // Look at every destructible actor which contributes to this physx actor, and see if any use hard sleeping + bool keepDormant = false; + PhysXObjectDescIntl* actorObjDesc = (PhysXObjectDescIntl*)mStructure->dscene->mModule->mSdk->getPhysXObjectInfo(dormantActorEntry.actor); + if (actorObjDesc != NULL) + { + for (uint32_t i = 0; i < actorObjDesc->mApexActors.size(); ++i) + { + const DestructibleActor* dActor = static_cast<const DestructibleActor*>(actorObjDesc->mApexActors[i]); + if (dActor != NULL) + { + if (actorObjDesc->mApexActors[i]->getOwner()->getObjTypeID() == DestructibleAssetImpl::getAssetTypeID()) + { + const DestructibleActorImpl& destructibleActor = static_cast<const DestructibleActorProxy*>(dActor)->impl; + if (destructibleActor.useHardSleeping()) + { + keepDormant = true; + break; + } + } + } + } + } + // If none use hard sleeping, we will remove the physx actor from the dormant list + if (!keepDormant) + { + PxRigidDynamic* actor = dormantActorEntry.actor; + dormantActorEntry.actor = NULL; + dormantActors.free(dormantActorIndex); + { + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, false); + } + if (actorObjDesc != NULL) + { + actorObjDesc->userData = NULL; + mStructure->dscene->addActor(*actorObjDesc, *actor, dormantActorEntry.unscaledMass, + ((dormantActorEntry.flags & ActorFIFOEntry::IsDebris) != 0)); + } + // Wake if requested + if (wake) + { + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + actor->wakeUp(); + } + } + } +} + +bool DestructibleActorImpl::setChunkPhysXActorAwakeState(uint32_t chunkIndex, bool awake) +{ + PxRigidDynamic* actor = getChunkActor(chunkIndex); + if (actor == NULL) + { + return false; + } + + PxScene* scene = actor->getScene(); + if (scene == NULL) + { + // defer + if (mDestructibleScene != NULL) + { + mDestructibleScene->addForceToAddActorsMap(actor, ActorForceAtPosition(PxVec3(0.0f), PxVec3(0.0f), physx::PxForceMode::eFORCE, awake, false)); + return true; + } + return false; + } + + // Actor has a scene, set sleep state now + if (awake) + { + actor->wakeUp(); + } + else + { + ((PxRigidDynamic*)actor)->putToSleep(); + } + + return true; +} + +bool DestructibleActorImpl::addForce(uint32_t chunkIndex, const PxVec3& force, physx::PxForceMode::Enum mode, const PxVec3* position, bool wakeup) +{ + PxRigidDynamic* actor = getChunkActor(chunkIndex); + if (actor == NULL) + { + return false; + } + + if (actor->getScene() == NULL) + { + // defer + if (mDestructibleScene != NULL) + { + if (position) + { + mDestructibleScene->addForceToAddActorsMap(actor, ActorForceAtPosition(force, *position, mode, wakeup, true)); + } + else + { + mDestructibleScene->addForceToAddActorsMap(actor, ActorForceAtPosition(force, PxVec3(0.0f), mode, wakeup, false)); + } + return true; + } + return false; + } + + // Actor has a scene, add force now + PxRigidBody* rigidBody = actor->is<PxRigidBody>(); + if (rigidBody) + { + if (position) + { + PxRigidBodyExt::addForceAtPos(*rigidBody, force, *position, mode, wakeup); + } + else + { + rigidBody->addForce(force, mode, wakeup); + } + } + + return true; +} + +void DestructibleActorImpl::getLodRange(float& min, float& max, bool& intOnly) const +{ + min = 0.0f; + max = (float)(PxMax(mAsset->getDepthCount(), (uint32_t)1) - 1); + intOnly = true; +} + +float DestructibleActorImpl::getActiveLod() const +{ + return (float)getLOD(); +} + +void DestructibleActorImpl::forceLod(float lod) +{ + if (lod < 0.0f) + { + mState->lod = PxMax(mAsset->getDepthCount(), (uint32_t)1) - 1; + mState->forceLod = false; + } + else + { + float min, max; + bool intOnly; + getLodRange(min, max, intOnly); + mState->lod = (uint32_t)PxClamp(lod, min, max); + mState->forceLod = true; + } +} + +void DestructibleActorImpl::setDynamic(int32_t chunkIndex, bool immediate) +{ + const uint16_t* indexPtr = NULL; + const uint16_t* indexPtrStop = NULL; + uint16_t index; + if (chunkIndex == ModuleDestructibleConst::INVALID_CHUNK_INDEX) + { + indexPtr = getVisibleChunks(); + indexPtrStop = indexPtr + getNumVisibleChunks(); + } + else + if (chunkIndex >= 0 && chunkIndex < mAsset->mParams->chunks.arraySizes[0]) + { + index = (uint16_t)chunkIndex; + indexPtr = &index; + indexPtrStop = indexPtr+1; + } + + while (indexPtr < indexPtrStop) + { + const uint16_t index = *indexPtr++; + DestructibleStructure::Chunk& chunk = mStructure->chunks[mFirstChunkIndex + index]; + if ((chunk.state & ChunkDynamic)==0) + { + FractureEvent stackEvent; + FractureEvent& fractureEvent = immediate ? stackEvent : mStructure->dscene->mFractureBuffer.pushBack(); + fractureEvent.chunkIndexInAsset = chunk.indexInAsset; + fractureEvent.destructibleID = mID; + fractureEvent.impulse = PxVec3(0.0f); + fractureEvent.position = PxVec3(0.0f); + fractureEvent.flags = FractureEvent::Forced | FractureEvent::Silent; + if (immediate) + { + getStructure()->fractureChunk(fractureEvent); + } + } + } +} + +void DestructibleActorImpl::getChunkVisibilities(uint8_t* visibilityArray, uint32_t visibilityArraySize) const +{ + if (visibilityArray == NULL || visibilityArraySize == 0) + { + return; + } + + memset(visibilityArray, 0, visibilityArraySize); + + const uint32_t visiblePartCount = mVisibleChunks.usedCount(); + const uint16_t* visiblePartIndices = mVisibleChunks.usedIndices(); + for (uint32_t i = 0; i < visiblePartCount; ++i) + { + const uint32_t index = visiblePartIndices[i]; + if (index < visibilityArraySize) + { + visibilityArray[index] = 1; + } + } +} + +bool DestructibleActorImpl::acquireChunkEventBuffer(const DestructibleChunkEvent*& buffer, uint32_t& bufferSize) +{ + mChunkEventBufferLock.lock(); + + buffer = mChunkEventBuffer.begin(); + bufferSize = mChunkEventBuffer.size(); + return true; +} + +bool DestructibleActorImpl::releaseChunkEventBuffer(bool clearBuffer /* = true */) +{ + if (clearBuffer) + { + mChunkEventBuffer.reset(); + // potentially O(n), but is O(1) (empty list) if chunk event callbacks aren't enabled. The chunk event callbacks + // and aquireChunkEventBuffer/releaseChunkEventBuffer mechanisms probably won't be used together. + mDestructibleScene->mActorsWithChunkStateEvents.findAndReplaceWithLast(this); + } + + mChunkEventBufferLock.unlock(); + return true; +} + +// PhysX actor buffer API +bool DestructibleActorImpl::acquirePhysXActorBuffer(physx::PxRigidDynamic**& buffer, uint32_t& bufferSize, uint32_t flags) +{ + mPhysXActorBufferLock.lock(); + + mPhysXActorBufferAcquired = true; + // Clear buffer, just in case + mPhysXActorBuffer.reset(); + + const bool eliminateRedundantActors = (flags & DestructiblePhysXActorQueryFlags::AllowRedundancy) == 0; + + const bool onlyAllowActorsInScene = (flags & DestructiblePhysXActorQueryFlags::AllowActorsNotInScenes) == 0; + + SCOPED_PHYSX_LOCK_READ(mDestructibleScene->mPhysXScene); + + // Fill the actor buffer + for (uint32_t actorNum = 0; actorNum < mReferencingActors.size(); ++actorNum) + { + PxRigidDynamic* actor = mReferencingActors[actorNum]; + if (actor == NULL || actor->getNbShapes() == 0 + // don't return actors that have not yet been added to the scene + // to prevent errors in actor functions that require a scene + || ((actor->getScene() == NULL) && onlyAllowActorsInScene) + ) + { + continue; + } + + PxShape* firstShape; + actor->getShapes(&firstShape, 1, 0); + PhysXObjectDescIntl* objDesc = mStructure->dscene->mModule->mSdk->getGenericPhysXObjectInfo(firstShape); + if (objDesc == NULL) + { + continue; + } + const DestructibleStructure::Chunk& chunk = *(DestructibleStructure::Chunk*)objDesc->userData; + const uint32_t actorState = !(actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC) ? DestructiblePhysXActorQueryFlags::Dynamic : + ((chunk.state & ChunkDynamic) == 0 ? DestructiblePhysXActorQueryFlags::Static : DestructiblePhysXActorQueryFlags::Dormant); + if ((actorState & flags) == 0) + { + continue; // Not a type of actor requested + } + if (eliminateRedundantActors && chunk.destructibleID != mID) + { + continue; // If eliminateRedundantActors is set, only take actors whose first shape belongs to a chunk from this destructible + } + mPhysXActorBuffer.pushBack((physx::PxRigidDynamic*)actor); + } + + // Return buffer + buffer = mPhysXActorBuffer.begin(); + bufferSize = mPhysXActorBuffer.size(); + return true; +} + +bool DestructibleActorImpl::releasePhysXActorBuffer() +{ + if(mPhysXActorBufferAcquired) + { + mPhysXActorBuffer.reset(); + mPhysXActorBufferAcquired = false; + mPhysXActorBufferLock.unlock(); + return true; + } + else + { + return false; + } +} + +bool DestructibleActorImpl::recreateApexEmitter(DestructibleEmitterType::Enum type) +{ + bool ret = false; + + switch (type) + { + case DestructibleEmitterType::Crumble: + if (getCrumbleEmitterName()) + { + ret = initCrumbleSystem(getCrumbleEmitterName()); + } + break; + case DestructibleEmitterType::Dust: + if (getDustEmitterName()) + { + ret = initDustSystem(getDustEmitterName()); + } + break; + default: + break; + } + return ret; +} + +bool DestructibleActorImpl::initDustSystem(const char* name) +{ +#if APEX_USE_PARTICLES + + if (mDustEmitter) + { + return true; + } + + // Set up dust system + if (name) + { + setDustEmitterName(name); + /* This destructible actor will hold a reference to its MeshParticleFactoryAsset */ + Asset* tmpAsset = mAsset->mDustAssetTracker.getAssetFromName(name); + EmitterAsset* fasset = static_cast<EmitterAsset*>(tmpAsset); + if (fasset) + { + NvParameterized::Interface* descParams = fasset->getDefaultActorDesc(); + PX_ASSERT(descParams); + if (descParams) + { + mDustEmitter = static_cast<EmitterActor*>(fasset->createApexActor(*descParams, *mDestructibleScene->mApexScene)); + if (mDustEmitter) + { + ApexActor* aa = mAsset->module->mSdk->getApexActor(mDustEmitter); + if (aa) + { + aa->addSelfToContext(*this); + } + if (!mDustEmitter->isExplicitGeom()) + { + APEX_INTERNAL_ERROR("Destructible actors need EmitterGeomExplicit emitters."); + } + if (mDustRenderVolume) + { + mDustEmitter->setPreferredRenderVolume(mDustRenderVolume); + } + mDustEmitter->startEmit(true); + } + } + } + } + else + { + mState->enableDustEmitter = false; + } +#else + PX_UNUSED(name); +#endif // APEX_USE_PARTICLES + + return mDustEmitter ? true : false; +} + +bool DestructibleActorImpl::initCrumbleSystem(const char* name) +{ +#if APEX_USE_PARTICLES + // Set up crumble system + if (mCrumbleEmitter) + { + return true; + } + if (name) + { + setCrumbleEmitterName(name); + Asset* tmpAsset = mAsset->mCrumbleAssetTracker.getAssetFromName(name); + EmitterAsset* fasset = static_cast<EmitterAsset*>(tmpAsset); + if (fasset) + { + NvParameterized::Interface* descParams = fasset->getDefaultActorDesc(); + PX_ASSERT(descParams); + if (descParams) + { + mCrumbleEmitter = static_cast<EmitterActor*>(fasset->createApexActor(*descParams, *mDestructibleScene->mApexScene)); + if (mCrumbleEmitter) + { + ApexActor* aa = mAsset->module->mSdk->getApexActor(mCrumbleEmitter); + if (aa) + { + aa->addSelfToContext(*this); + } + if (!mCrumbleEmitter->isExplicitGeom()) + { + APEX_INTERNAL_ERROR("Destructible actors need EmitterGeomExplicit emitters."); + } + if (mCrumbleRenderVolume) + { + mCrumbleEmitter->setPreferredRenderVolume(mCrumbleRenderVolume); + } + mCrumbleEmitter->startEmit(true); + } + } + } + } + else + { + mState->enableCrumbleEmitter = false; + } +#else + PX_UNUSED(name); +#endif // APEX_USE_PARTICLES + + return mCrumbleEmitter ? true : false; +} + +void DestructibleActorImpl::setCrumbleEmitterName(const char* name) +{ + // Avoid self-assignment + if (name == getCrumbleEmitterName()) + return; + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("crumbleEmitterName", handle); + mParams->setParamString(handle, name ? name : ""); +} + +const char* DestructibleActorImpl::getCrumbleEmitterName() const +{ + const char* name = (const char*)mParams->crumbleEmitterName; + return (name && *name) ? name : NULL; +} + +void DestructibleActorImpl::setDustEmitterName(const char* name) +{ + // Avoid self-assignment + if (name == getDustEmitterName()) + return; + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("dustEmitterName", handle); + mParams->setParamString(handle, name ? name : ""); +} + +const char* DestructibleActorImpl::getDustEmitterName() const +{ + const char* name = (const char*)mParams->dustEmitterName; + return (name && *name) ? name : NULL; +} + + +void DestructibleActorImpl::setPreferredRenderVolume(RenderVolume* volume, DestructibleEmitterType::Enum type) +{ +#if APEX_USE_PARTICLES + switch (type) + { + case DestructibleEmitterType::Crumble: + mCrumbleRenderVolume = volume; + if (mCrumbleEmitter) + { + mCrumbleEmitter->setPreferredRenderVolume(volume); + } + break; + case DestructibleEmitterType::Dust: + mDustRenderVolume = volume; + if (mDustEmitter) + { + mDustEmitter->setPreferredRenderVolume(volume); + } + break; + default: + break; + } +#else + PX_UNUSED(volume); + PX_UNUSED(type); +#endif // APEX_USE_PARTICLES +} + +EmitterActor* DestructibleActorImpl::getApexEmitter(DestructibleEmitterType::Enum type) +{ + EmitterActor* ret = NULL; + +#if APEX_USE_PARTICLES + switch (type) + { + case DestructibleEmitterType::Crumble: + ret = mCrumbleEmitter; + break; + case DestructibleEmitterType::Dust: + ret = mDustEmitter; + break; + default: + break; + } +#else + PX_UNUSED(type); +#endif // APEX_USE_PARTICLES + + return ret; +} + +void DestructibleActorImpl::preSerialize(void* nvParameterizedType) +{ + DestructibleParameterizedType::Enum nxType = (DestructibleParameterizedType::Enum)((intptr_t)nvParameterizedType); + switch (nxType) + { + case DestructibleParameterizedType::State: + { + PX_ASSERT(mState->actorChunks); + serialize(*this, &getStructure()->chunks[0] + mFirstChunkIndex, getDestructibleAsset()->getChunkCount(), *mChunks); + break; + } + case DestructibleParameterizedType::Params: + { + PX_ASSERT(mParams); + PxMat44 globalPoseForStaticChunks; + if (!getGlobalPoseForStaticChunks(globalPoseForStaticChunks)) + { + globalPoseForStaticChunks = getInitialGlobalPose(); // This will occur if there are no static chunks + } + PxTransform globalPose(globalPoseForStaticChunks); + globalPose.q.normalize(); + mParams->globalPose = globalPose; + PX_ASSERT(mState->actorParameters); + serialize(mDestructibleParameters, *mState->actorParameters); + break; + } + default: + PX_ASSERT(0 && "Invalid destructible parameterized type"); + break; + } +} + +bool DestructibleActorImpl::applyDamageColoring(uint16_t indexInAsset, const PxVec3& position, float damage, float damageRadius) +{ + bool bRet = applyDamageColoringRecursive(indexInAsset, position, damage, damageRadius); + + RenderMeshAsset* rma = mAsset->getRenderMeshAsset(); + for (uint32_t submeshIndex = 0; submeshIndex < rma->getSubmeshCount(); ++submeshIndex) + { + physx::Array<ColorRGBA>& damageColorArray = mDamageColorArrays[submeshIndex]; + // fix asset on &damageColorArray[0] + if (damageColorArray.size() != 0) + { + for (uint32_t typeN = 0; typeN < DestructibleActorMeshType::Count; ++typeN) + { + RenderMeshActorIntl* renderMeshActor = (RenderMeshActorIntl*)getRenderMeshActor((DestructibleActorMeshType::Enum)typeN); + if (renderMeshActor != NULL) + { + renderMeshActor->setStaticColorReplacement(submeshIndex, &damageColorArray[0]); + } + } + } + } + + return bRet; +} + +bool DestructibleActorImpl::applyDamageColoringRecursive(uint16_t indexInAsset, const PxVec3& position, float damage, float damageRadius) +{ + RenderMeshAsset* rma = mAsset->getRenderMeshAsset(); + if (mDamageColorArrays.size() != rma->getSubmeshCount()) + { + return false; + } + + // Get behavior group + const DestructibleAssetParametersNS::Chunk_Type& source = getDestructibleAsset()->mParams->chunks.buf[indexInAsset]; + const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = getBehaviorGroupImp(source.behaviorGroupIndex); + + const float maxRadius = behaviorGroup.damageColorSpread.minimumRadius + damageRadius*behaviorGroup.damageColorSpread.radiusMultiplier; + + const DestructibleStructure::Chunk& chunk = mStructure->chunks[indexInAsset + mFirstChunkIndex]; + const PxVec3 disp = mStructure->getChunkWorldCentroid(chunk) - position; + const float dist = disp.magnitude(); + if (dist > maxRadius + chunk.localSphereRadius) + { + return false; // Outside of max radius + } + + bool bRet = false; + +// const float recipRadiusRange = maxRadius > behaviorGroup.damageColorSpread.minimumRadius ? 1.0f/(maxRadius - behaviorGroup.damageColorSpread.minimumRadius) : 0.0f; + const float recipRadiusRange = maxRadius > damageRadius ? 1.0f/(maxRadius - damageRadius) : 0.0f; + + // Color scale multiplier based upon damage + const float colorScale = behaviorGroup.damageThreshold > 0.0f ? PxMin(1.0f, damage/behaviorGroup.damageThreshold) : 1.0f; + + const uint32_t partIndex = mAsset->getPartIndex(indexInAsset); + +// const float minRadiusSquared = behaviorGroup.damageColorSpread.minimumRadius*behaviorGroup.damageColorSpread.minimumRadius; + const float minRadiusSquared = damageRadius*damageRadius; + const float maxRadiusSquared = maxRadius*maxRadius; + + PxMat44 chunkGlobalPose(getChunkPose(indexInAsset)); + chunkGlobalPose.scale(PxVec4(getScale(), 1.0f)); + + // Find all vertices and modify color + for (uint32_t submeshIndex = 0; submeshIndex < rma->getSubmeshCount(); ++submeshIndex) + { + const RenderSubmesh& submesh = rma->getSubmesh(submeshIndex); + physx::Array<ColorRGBA>& damageColorArray = mDamageColorArrays[submeshIndex]; + const VertexBuffer& vb = submesh.getVertexBuffer(); + PX_ASSERT(damageColorArray.size() == vb.getVertexCount()); + if (damageColorArray.size() != vb.getVertexCount()) // Make sure we have the correct size color array + { + continue; + } + const VertexFormat& vf = vb.getFormat(); + const int32_t positionBufferIndex = vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::POSITION)); + if (positionBufferIndex >= 0) // Make sure we have a position buffer + { + RenderDataFormat::Enum positionBufferFormat = vf.getBufferFormat((uint32_t)positionBufferIndex); + PX_ASSERT(positionBufferFormat == RenderDataFormat::FLOAT3); + if (positionBufferFormat != RenderDataFormat::FLOAT3) + { + continue; + } + const PxVec3* positions = (const PxVec3*)vb.getBuffer((uint32_t)positionBufferIndex); + // Get the vertex range for the part associated with this chunk (note: this will _not_ work with instancing) + const uint32_t firstVertexIndex = submesh.getFirstVertexIndex(partIndex); + const uint32_t stopVertexIndex = firstVertexIndex + submesh.getVertexCount(partIndex); + for (uint32_t vertexIndex = firstVertexIndex; vertexIndex < stopVertexIndex; ++vertexIndex) + { + // Adjust the color scale based upon the envelope function + float colorChangeMultiplier = colorScale; + // Get the world vertex position + const PxVec3 worldVertexPosition = chunkGlobalPose.transform(positions[vertexIndex]); + const float radiusSquared = (position - worldVertexPosition).magnitudeSquared(); + if (radiusSquared > maxRadiusSquared) + { + continue; + } + if (radiusSquared > minRadiusSquared) + { + colorChangeMultiplier *= PxPow((maxRadius - PxSqrt(radiusSquared))*recipRadiusRange, behaviorGroup.damageColorSpread.falloffExponent); + } + // Get the color, add the scaled color values, clamp, and set the new color + ColorRGBA& color = damageColorArray[vertexIndex]; + PxVec4 newColor = PxVec4((float)color.r, (float)color.g, (float)color.b, (float)color.a) + colorChangeMultiplier*behaviorGroup.damageColorChange; + newColor = newColor.maximum(PxVec4(0.0f)); + newColor = newColor.minimum(PxVec4(255.0f)); + // save previous color + ColorRGBA preColor = color; + color.r = (uint8_t)(newColor[0] + 0.5f); + color.g = (uint8_t)(newColor[1] + 0.5f); + color.b = (uint8_t)(newColor[2] + 0.5f); + color.a = (uint8_t)(newColor[3] + 0.5f); + + // Only save the static chunk now. + if ((chunk.state & ChunkDynamic) == 0) + { + // compare the previous color with the new color + bRet = preColor.r != color.r || preColor.g != color.g || preColor.b != color.b || preColor.a != color.a; + } + } + } + } + + // Recurse to children + const uint32_t stopIndex = uint32_t(source.firstChildIndex + source.numChildren); + for (uint32_t childIndex = source.firstChildIndex; childIndex < stopIndex; ++childIndex) + { + bRet |= applyDamageColoringRecursive((uint16_t)childIndex, position, damage, damageRadius); + } + + return bRet; +} + +void DestructibleActorImpl::fillBehaviorGroupDesc(DestructibleBehaviorGroupDesc& behaviorGroupDesc, const DestructibleActorParamNS::BehaviorGroup_Type behaviorGroup) const +{ + behaviorGroupDesc.name = behaviorGroup.name; + behaviorGroupDesc.damageThreshold = behaviorGroup.damageThreshold; + behaviorGroupDesc.damageToRadius = behaviorGroup.damageToRadius; + behaviorGroupDesc.damageSpread.minimumRadius = behaviorGroup.damageSpread.minimumRadius; + behaviorGroupDesc.damageSpread.radiusMultiplier = behaviorGroup.damageSpread.radiusMultiplier; + behaviorGroupDesc.damageSpread.falloffExponent = behaviorGroup.damageSpread.falloffExponent; + behaviorGroupDesc.damageColorSpread.minimumRadius = behaviorGroup.damageColorSpread.minimumRadius; + behaviorGroupDesc.damageColorSpread.radiusMultiplier = behaviorGroup.damageColorSpread.radiusMultiplier; + behaviorGroupDesc.damageColorSpread.falloffExponent = behaviorGroup.damageColorSpread.falloffExponent; + behaviorGroupDesc.damageColorChange = behaviorGroup.damageColorChange; + behaviorGroupDesc.materialStrength = behaviorGroup.materialStrength; + behaviorGroupDesc.density = behaviorGroup.density; + behaviorGroupDesc.fadeOut = behaviorGroup.fadeOut; + behaviorGroupDesc.maxDepenetrationVelocity = behaviorGroup.maxDepenetrationVelocity; + behaviorGroupDesc.userData = behaviorGroup.userData; +} + +void DestructibleActorImpl::spawnParticles(EmitterActor* emitter, UserChunkParticleReport* report, DestructibleStructure::Chunk& chunk, physx::Array<PxVec3>& positions, bool deriveVelocitiesFromChunk, const PxVec3* overrideVelocity) +{ +#if APEX_USE_PARTICLES + uint32_t numParticles = positions.size(); + if (numParticles == 0) + { + return; + } + + EmitterGeomExplicit* geom = emitter != NULL ? emitter->isExplicitGeom() : NULL; // emitter may be NULL, since we may have a particle callback + + if (geom == NULL && report == NULL) + { + APEX_INTERNAL_ERROR("DestructibleActor::spawnParticles requires an EmitterGeomExplicit emitter or a UserChunkParticleReport, or both."); + return; + } + + if (overrideVelocity == NULL && deriveVelocitiesFromChunk) + { + physx::Array<PxVec3> volumeFillVel; + volumeFillVel.resize(numParticles); + + // Use dynamic actor's current velocity + PxVec3 angVel; + PxVec3 linVel; + PxVec3 COM; + PxRigidDynamic* actor = mStructure->getChunkActor(chunk); + { + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + angVel = actor->getAngularVelocity(); + linVel = actor->getLinearVelocity(); + COM = actor->getGlobalPose().p; + } + + for (uint32_t i = 0; i < numParticles; ++i) + { + volumeFillVel[i] = linVel + angVel.cross(positions[i] - COM); + PX_ASSERT(PxIsFinite(volumeFillVel[i].magnitude())); + } + + if (geom != NULL) + { + geom->addParticleList(numParticles, &positions.front(), &volumeFillVel.front()); + //emitter->emit(false); + } + + if (report != NULL) + { + ChunkParticleReportData reportData; + reportData.positions = &positions.front(); + reportData.positionCount = numParticles; + reportData.velocities = &volumeFillVel.front(); + reportData.velocityCount = numParticles; + report->onParticleEmission(reportData); + } + } + else + { + PX_ASSERT(overrideVelocity == NULL || PxIsFinite(overrideVelocity->magnitude())); + + if (geom != NULL) + { + const PxVec3 velocity = overrideVelocity != NULL ? *overrideVelocity : PxVec3(0.0f); + emitter->setVelocityLow(velocity); + emitter->setVelocityHigh(velocity); + geom->addParticleList(numParticles, &positions.front()); + } + + if (report != NULL) + { + ChunkParticleReportData reportData; + reportData.positions = &positions.front(); + reportData.positionCount = numParticles; + reportData.velocities = overrideVelocity; + reportData.velocityCount = overrideVelocity != NULL ? 1u : 0u; + report->onParticleEmission(reportData); + } + } +#else + PX_UNUSED(emitter); + PX_UNUSED(report); + PX_UNUSED(chunk); + PX_UNUSED(positions); + PX_UNUSED(deriveVelocitiesFromChunk); + PX_UNUSED(overrideVelocity); +#endif // APEX_USE_PARTICLES +} + +void DestructibleActorImpl::setDeleteFracturedChunks(bool inDeleteChunkMode) +{ + mInDeleteChunkMode = inDeleteChunkMode; +} + +bool DestructibleActorImpl::setHitChunkTrackingParams(bool flushHistory, bool startTracking, uint32_t trackingDepth, bool trackAllChunks) +{ + bool validOperation = false; + if(getDestructibleAsset()->getDepthCount() >= trackingDepth) + { + hitChunkParams.cacheChunkHits = startTracking; + hitChunkParams.cacheAllChunks = trackAllChunks; + if(flushHistory && !hitChunkParams.hitChunkContainer.empty()) + { + hitChunkParams.hitChunkContainer.clear(); + damageColoringParams.damageEventCoreDataContainer.clear(); + } + hitChunkParams.trackingDepth = trackingDepth; + validOperation = true; + } + return validOperation; +} + +bool DestructibleActorImpl::getHitChunkHistory(const DestructibleHitChunk *& hitChunkContainer, uint32_t & hitChunkCount) const +{ + bool validOperation = false; + { + hitChunkContainer = !hitChunkParams.hitChunkContainer.empty() ? static_cast<const DestructibleHitChunk*>(&hitChunkParams.hitChunkContainer[0]) : NULL; + hitChunkCount = hitChunkParams.hitChunkContainer.size(); + validOperation = true; + } + return validOperation; +} + +bool DestructibleActorImpl::forceChunkHits(const DestructibleHitChunk * hitChunkContainer, uint32_t hitChunkCount, bool removeChunks /*= true*/, bool deferredEvent /*= false*/, PxVec3 damagePosition /*= PxVec3(0.0f)*/, PxVec3 damageDirection /*= PxVec3(0.0f)*/) +{ + bool validOperation = false; + PX_ASSERT(!((NULL == hitChunkContainer) ^ (0 == hitChunkCount))); + if(NULL != hitChunkContainer && 0 != hitChunkCount) + { + uint32_t manualFractureCount = 0; + for(uint32_t index = 0; index < hitChunkCount; ++index) + { + if(mStructure->chunks.size() > (hitChunkContainer[index].chunkIndex + mFirstChunkIndex)) + { + hitChunkParams.manualFractureEventInstance.chunkIndexInAsset = hitChunkContainer[index].chunkIndex; + hitChunkParams.manualFractureEventInstance.destructibleID = mID; + hitChunkParams.manualFractureEventInstance.position = damagePosition; + hitChunkParams.manualFractureEventInstance.hitDirection = damageDirection; + hitChunkParams.manualFractureEventInstance.flags = (hitChunkContainer[index].hitChunkFlags | static_cast<uint32_t>(FractureEvent::Manual) | (removeChunks ? static_cast<uint32_t>(FractureEvent::DeleteChunk) : 0)); + if(deferredEvent) + { + mDestructibleScene->mDeferredFractureBuffer.pushBack() = hitChunkParams.manualFractureEventInstance; + } + else + { + mDestructibleScene->mDeprioritisedFractureBuffer.pushBack() = hitChunkParams.manualFractureEventInstance; + } + ++manualFractureCount; + } + } + validOperation = (manualFractureCount == hitChunkCount); + } + return validOperation; +} + +void DestructibleActorImpl::evaluateForHitChunkList(const FractureEvent & fractureEvent) +{ + PX_ASSERT(NULL != &fractureEvent); + + // cache hit chunks for non-manual fractureEvents, if user set so + if(hitChunkParams.cacheChunkHits && (0 == (fractureEvent.flags & FractureEvent::Manual))) + { + // walk up the depth until we reach the user-specified tracking depth + int32_t chunkToUseIndexInAsset = static_cast<int32_t>(fractureEvent.chunkIndexInAsset); + PX_ASSERT(chunkToUseIndexInAsset >= 0); + while(ModuleDestructibleConst::INVALID_CHUNK_INDEX != chunkToUseIndexInAsset) + { + PX_ASSERT(chunkToUseIndexInAsset < static_cast<int32_t>(getDestructibleAsset()->getChunkCount())); + const DestructibleAssetParametersNS::Chunk_Type & source = getDestructibleAsset()->mParams->chunks.buf[chunkToUseIndexInAsset]; + if(source.depth <= hitChunkParams.trackingDepth) + { + break; + } + chunkToUseIndexInAsset = static_cast<int32_t>(source.parentIndex); + } + + // cache the chunk index at the user-specified tracking depth + if(ModuleDestructibleConst::INVALID_CHUNK_INDEX != chunkToUseIndexInAsset) + { + PX_ASSERT(chunkToUseIndexInAsset + getFirstChunkIndex() < getStructure()->chunks.size()); + const DestructibleStructure::Chunk & chunkToUse = getStructure()->chunks[chunkToUseIndexInAsset + getFirstChunkIndex()]; + if((!chunkToUse.isDestroyed()) && (0 == (FractureEvent::DamageFromImpact & fractureEvent.flags)) && (!hitChunkParams.cacheAllChunks ? ((chunkToUse.state & ChunkDynamic) == 0) : true)) + { + // these flags are only used internally for fracture events coming in from the sync buffer, so we should exclude them + uint32_t hitChunkFlags = fractureEvent.flags; + hitChunkFlags &= ~FractureEvent::SyncDirect; + hitChunkFlags &= ~FractureEvent::SyncDerived; + hitChunkFlags &= ~FractureEvent::Manual; + + // disallow crumbling and snapping as well + hitChunkFlags &= ~FractureEvent::CrumbleChunk; + hitChunkFlags &= ~FractureEvent::Snap; + + // cache the chunk index + hitChunkParams.hitChunkContainer.pushBack(DestructibleActorImpl::CachedHitChunk(static_cast<uint32_t>(chunkToUseIndexInAsset), hitChunkFlags)); + } + } + } +} + +bool DestructibleActorImpl::getDamageColoringHistory(const DamageEventCoreData *& damageEventCoreDataContainer, uint32_t & damageEventCoreDataCount) const +{ + bool validOperation = false; + { + damageEventCoreDataContainer = !damageColoringParams.damageEventCoreDataContainer.empty() ? static_cast<const DamageEventCoreData*>(&damageColoringParams.damageEventCoreDataContainer[0]) : NULL; + damageEventCoreDataCount = damageColoringParams.damageEventCoreDataContainer.size(); + validOperation = true; + } + return validOperation; + +} + +bool DestructibleActorImpl::forceDamageColoring(const DamageEventCoreData * damageEventCoreDataContainer, uint32_t damageEventCoreDataCount) +{ + bool validOperation = false; + PX_ASSERT(!((NULL == damageEventCoreDataContainer) ^ (0 == damageEventCoreDataCount))); + if (NULL != damageEventCoreDataContainer && 0 != damageEventCoreDataCount) + { + uint32_t manualDamageColorCount = 0; + for (uint32_t index = 0; index < damageEventCoreDataCount; ++index) + { + if (mStructure->chunks.size() > (damageEventCoreDataContainer[index].chunkIndexInAsset + mFirstChunkIndex)) + { + damageColoringParams.damageEventCoreDataInstance.destructibleID = mID; + damageColoringParams.damageEventCoreDataInstance.chunkIndexInAsset = damageEventCoreDataContainer[index].chunkIndexInAsset; + damageColoringParams.damageEventCoreDataInstance.position = damageEventCoreDataContainer[index].position; + damageColoringParams.damageEventCoreDataInstance.damage = damageEventCoreDataContainer[index].damage; + damageColoringParams.damageEventCoreDataInstance.radius = damageEventCoreDataContainer[index].radius; + + mDestructibleScene->mSyncDamageEventCoreDataBuffer.pushBack() = damageColoringParams.damageEventCoreDataInstance; + + ++manualDamageColorCount; + } + } + validOperation = (manualDamageColorCount == damageEventCoreDataCount); + } + return validOperation; + +} + +void DestructibleActorImpl::collectDamageColoring(const int32_t indexInAsset, const PxVec3& position, const float damage, const float damageRadius) +{ + // only start cached the damage coloring when the flag set. see setHitChunkTrackingParams() + if (hitChunkParams.cacheChunkHits) + { + damageColoringParams.damageEventCoreDataContainer.pushBack(DestructibleActorImpl::CachedDamageEventCoreData(indexInAsset, position, damage, damageRadius)); + } +} + +void DestructibleActorImpl::applyDamageColoring_immediate(const int32_t indexInAsset, const PxVec3& position, const float damage, const float damageRadius) +{ + // Damage coloring: + if (useDamageColoring()) + { + if (indexInAsset != ModuleDestructibleConst::INVALID_CHUNK_INDEX) + { + // Normal Damage - apply damage coloring directly + applyDamageColoring(static_cast<uint16_t>(indexInAsset), position, damage, damageRadius); + } + else + { + // Radius Damage - need to traverse all the visible chunks + const uint16_t* chunkIndexPtr = mVisibleChunks.usedIndices(); + const uint16_t* chunkIndexPtrStop = chunkIndexPtr + mVisibleChunks.usedCount(); + + while (chunkIndexPtr < chunkIndexPtrStop) + { + uint16_t chunkIndex = *chunkIndexPtr++; + DestructibleStructure::Chunk& chunk = mStructure->chunks[chunkIndex + mFirstChunkIndex]; + + applyDamageColoring(chunk.indexInAsset, position, damage, damageRadius); + } + } + } +} + +bool DestructibleActorImpl::getUseLegacyChunkBoundsTesting() const +{ + const int8_t setting = mParams->destructibleParameters.legacyChunkBoundsTestSetting; + if (setting < 0) + { + return mDestructibleScene->getModuleDestructible()->getUseLegacyChunkBoundsTesting(); + } + return setting > 0; +} + +bool DestructibleActorImpl::getUseLegacyDamageRadiusSpread() const +{ + const int8_t setting = mParams->destructibleParameters.legacyDamageRadiusSpreadSetting; + if (setting < 0) + { + return mDestructibleScene->getModuleDestructible()->getUseLegacyDamageRadiusSpread(); + } + return setting > 0; +} + +/*** DestructibleActor::SyncParams ***/ +bool DestructibleActorImpl::setSyncParams(uint32_t userActorID, uint32_t actorSyncFlags, const DestructibleActorSyncState * actorSyncState, const DestructibleChunkSyncState * chunkSyncState) +{ + bool validEntry = false; + PX_ASSERT(!mDestructibleScene->getSyncParams().lockSyncParams && "if this happens, theres more work to do!"); + if(!mDestructibleScene->getSyncParams().lockSyncParams) + { + const bool validActorSyncFlags = static_cast<uint32_t>(DestructibleActorSyncFlags::Last) > actorSyncFlags; + const bool validActorSyncState = (NULL != actorSyncState) ? (mAsset->getDepthCount() >= actorSyncState->damageEventFilterDepth) && (mAsset->getDepthCount() >= actorSyncState->fractureEventFilterDepth) : true; + const bool validChunkSyncState = (NULL != chunkSyncState) ? (mAsset->getDepthCount() >= chunkSyncState->chunkTransformCopyDepth) : true; +#if 0 + //const bool validDepth = (mAsset->getDepthCount() >= chunkPositionCopyDepth) ? (chunkPositionCopyDepth >= chunkTransformCopyDepth) : false; +#endif + if(validActorSyncFlags && validActorSyncState && validChunkSyncState) + { + //determine type of operation + const uint32_t presentUserActorID = mSyncParams.getUserActorID(); + const bool addEntry = (0 != userActorID) && (0 == presentUserActorID); + const bool removeEntry = (0 == userActorID) && (0 != presentUserActorID); + const bool relocateEntry = (0 != userActorID) && (0 != presentUserActorID) && (userActorID != presentUserActorID); + const bool editEntry = (0 != userActorID) && (0 != presentUserActorID) && (userActorID == presentUserActorID); + const bool invalidEntry = (0 == userActorID) && (0 == presentUserActorID); + PX_ASSERT(addEntry ? (!removeEntry && !relocateEntry && !editEntry && !invalidEntry) : removeEntry ? (!relocateEntry && !editEntry && !invalidEntry) : relocateEntry ? (!editEntry && !invalidEntry) : editEntry? (!invalidEntry) : invalidEntry); + + //attempt update scene and actor params + if(addEntry || removeEntry || relocateEntry || editEntry) + { + bool validUserActorID = false; + bool useUserArguments = false; + DestructibleScene::SyncParams & sceneParams = mDestructibleScene->getSyncParamsMutable(); + DestructibleActorImpl * erasedEntry = NULL; + if(addEntry) + { + validUserActorID = sceneParams.setSyncActor(userActorID, this, erasedEntry); + PX_ASSERT(this != erasedEntry); + if(validUserActorID) + { + useUserArguments = true; + if(NULL != erasedEntry) + { + erasedEntry->getSyncParamsMutable().onReset(); + erasedEntry = NULL; + } + } + } + else if(removeEntry) + { + validUserActorID = sceneParams.setSyncActor(presentUserActorID, NULL, erasedEntry); + PX_ASSERT((NULL != erasedEntry) && (this == erasedEntry)); + if(validUserActorID) + { + mSyncParams.onReset(); + } + } + else if(relocateEntry) + { + validUserActorID = sceneParams.setSyncActor(presentUserActorID, NULL, erasedEntry); + PX_ASSERT((NULL != erasedEntry) && (this == erasedEntry)); + if(validUserActorID) + { + validUserActorID = sceneParams.setSyncActor(userActorID, this, erasedEntry); + PX_ASSERT(this != erasedEntry); + if(validUserActorID) + { + useUserArguments = true; + if(NULL != erasedEntry) + { + erasedEntry->getSyncParamsMutable().onReset(); + erasedEntry = NULL; + } + } + } + } + else if(editEntry) + { + validUserActorID = true; + useUserArguments = true; + } + else + { + PX_ASSERT(!"!"); + } + validEntry = validUserActorID && validActorSyncFlags && validActorSyncState && validChunkSyncState; + if(useUserArguments) + { + PX_ASSERT(validEntry); + mSyncParams.userActorID = userActorID; + mSyncParams.actorSyncFlags = actorSyncFlags; + if (actorSyncState) + { + mSyncParams.useActorSyncState = true; + mSyncParams.actorSyncState = *actorSyncState; + } + if (chunkSyncState) + { + mSyncParams.useChunkSyncState = true; + mSyncParams.chunkSyncState = *chunkSyncState; + } + } + } + else + { + PX_ASSERT(invalidEntry); + PX_UNUSED(invalidEntry); + PX_ASSERT(!"invalid use of function!"); + } + } + } + return validEntry; +} + +typedef DestructibleActorImpl::SyncParams SyncParams; + +SyncParams::SyncParams() + :userActorID(0) + ,actorSyncFlags(0) + ,useActorSyncState(false) + ,useChunkSyncState(false) +{ + PX_ASSERT(damageBufferIndices.empty()); + PX_ASSERT(fractureBufferIndices.empty()); + PX_ASSERT(cachedChunkTransforms.empty()); +} + +SyncParams::~SyncParams() +{ + PX_ASSERT(cachedChunkTransforms.empty()); + PX_ASSERT(fractureBufferIndices.empty()); + PX_ASSERT(damageBufferIndices.empty()); + PX_ASSERT(!useChunkSyncState); + PX_ASSERT(!useActorSyncState); + PX_ASSERT(0 == actorSyncFlags); + PX_ASSERT(0 == userActorID); +} + +uint32_t SyncParams::getUserActorID() const +{ + return userActorID; +} + +bool SyncParams::isSyncFlagSet(DestructibleActorSyncFlags::Enum flag) const +{ + PX_ASSERT(0 != userActorID); + return (0 != (actorSyncFlags & static_cast<uint32_t>(flag))); +} + +const DestructibleActorSyncState * SyncParams::getActorSyncState() const +{ + PX_ASSERT(useActorSyncState ? (isSyncFlagSet(DestructibleActorSyncFlags::CopyDamageEvents) || isSyncFlagSet(DestructibleActorSyncFlags::CopyFractureEvents)) : true); + return useActorSyncState ? &actorSyncState : NULL; +} + +const DestructibleChunkSyncState * SyncParams::getChunkSyncState() const +{ + PX_ASSERT(useChunkSyncState ? isSyncFlagSet(DestructibleActorSyncFlags::CopyChunkTransform) : true); + return useChunkSyncState ? &chunkSyncState : NULL; +} + +void SyncParams::pushDamageBufferIndex(uint32_t index) +{ + PX_ASSERT(isSyncFlagSet(DestructibleActorSyncFlags::CopyDamageEvents)); + damageBufferIndices.pushBack(index); +} + +void SyncParams::pushFractureBufferIndex(uint32_t index) +{ + PX_ASSERT(isSyncFlagSet(DestructibleActorSyncFlags::CopyFractureEvents)); + fractureBufferIndices.pushBack(index); +} + +void SyncParams::pushCachedChunkTransform(const CachedChunk & cachedChunk) +{ + PX_ASSERT(isSyncFlagSet(DestructibleActorSyncFlags::CopyChunkTransform)); + cachedChunkTransforms.pushBack(cachedChunk); +} + +const physx::Array<uint32_t> & SyncParams::getDamageBufferIndices() const +{ + return damageBufferIndices; +} + +const physx::Array<uint32_t> & SyncParams::getFractureBufferIndices() const +{ + return fractureBufferIndices; +} + +const physx::Array<CachedChunk> & SyncParams::getCachedChunkTransforms() const +{ + return cachedChunkTransforms; +} + +template<> void SyncParams::clear<DamageEventUnit>() +{ + PX_ASSERT(!damageBufferIndices.empty() ? isSyncFlagSet(DestructibleActorSyncFlags::CopyDamageEvents) : true); + if(!damageBufferIndices.empty()) damageBufferIndices.clear(); +} + +template<> void SyncParams::clear<FractureEventUnit>() +{ + PX_ASSERT(!fractureBufferIndices.empty() ? isSyncFlagSet(DestructibleActorSyncFlags::CopyFractureEvents) : true); + if(!fractureBufferIndices.empty()) fractureBufferIndices.clear(); +} + +template<> void SyncParams::clear<ChunkTransformUnit>() +{ + PX_ASSERT(!cachedChunkTransforms.empty() ? isSyncFlagSet(DestructibleActorSyncFlags::CopyChunkTransform) : true); + if(!cachedChunkTransforms.empty()) cachedChunkTransforms.clear(); +} + +template<> uint32_t SyncParams::getCount<DamageEventUnit>() const +{ + PX_ASSERT(!damageBufferIndices.empty() ? isSyncFlagSet(DestructibleActorSyncFlags::CopyDamageEvents) : true); + return damageBufferIndices.size(); +} + +template<> uint32_t SyncParams::getCount<FractureEventUnit>() const +{ + PX_ASSERT(!fractureBufferIndices.empty() ? isSyncFlagSet(DestructibleActorSyncFlags::CopyFractureEvents) : true); + return fractureBufferIndices.size(); +} + +template<> uint32_t SyncParams::getCount<ChunkTransformUnit>() const +{ + PX_ASSERT(!cachedChunkTransforms.empty() ? isSyncFlagSet(DestructibleActorSyncFlags::CopyChunkTransform) : true); + return cachedChunkTransforms.size(); +} + +void SyncParams::onReset() +{ + userActorID = 0; + actorSyncFlags = 0; + useActorSyncState = false; + useChunkSyncState = false; + damageBufferIndices.clear(); + fractureBufferIndices.clear(); + cachedChunkTransforms.clear(); +} + +const SyncParams & DestructibleActorImpl::getSyncParams() const +{ + return mSyncParams; +} + +SyncParams & DestructibleActorImpl::getSyncParamsMutable() +{ + return const_cast<SyncParams&>(getSyncParams()); +} + +// Renderable support: + +DestructibleRenderable* DestructibleActorImpl::acquireRenderableReference() +{ + return mRenderable ? mRenderable->incrementReferenceCount() : NULL; +} + +RenderMeshActor* DestructibleActorImpl::getRenderMeshActor(DestructibleActorMeshType::Enum type) const +{ + return mRenderable ? mRenderable->getRenderMeshActor(type) : NULL; +} + +} +} // end namespace nvidia + + diff --git a/APEX_1.4/module/destructible/src/DestructibleActorJointImpl.cpp b/APEX_1.4/module/destructible/src/DestructibleActorJointImpl.cpp new file mode 100644 index 00000000..958d3111 --- /dev/null +++ b/APEX_1.4/module/destructible/src/DestructibleActorJointImpl.cpp @@ -0,0 +1,257 @@ +/* + * 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. + */ + + +#include "ApexDefs.h" + +#include "Apex.h" +#include "ModuleDestructibleImpl.h" +#include "DestructibleActorJointImpl.h" +#include "DestructibleScene.h" +#include "DestructibleActorJoint.h" +#include "DestructibleActorProxy.h" + +#include <PxScene.h> +#include <PxJoint.h> +#include <PxD6Joint.h> +#include <PxDistanceJoint.h> +#include <PxFixedJoint.h> +#include <PxPrismaticJoint.h> +#include <PxRevoluteJoint.h> +#include <PxSphericalJoint.h> + +namespace nvidia +{ +namespace destructible +{ +using namespace physx; + +DestructibleActorJointImpl::DestructibleActorJointImpl(const DestructibleActorJointDesc& desc, DestructibleScene& dscene) : + joint(NULL) +{ + if (desc.destructible[0] == NULL && desc.destructible[1] == NULL) + { + APEX_DEBUG_WARNING("Both destructible actors in DestructibleActorJoint are NULL."); + return; + } + + PxRigidActor* actor[2] = {desc.actor[0], desc.actor[1]}; + PxVec3 localAxis[2] = {desc.localAxis[0], desc.localAxis[1]}; + PxVec3 localAnchor[2] = {desc.localAnchor[0], desc.localAnchor[1]}; + PxVec3 localNormal[2] = {desc.localNormal[0], desc.localNormal[1]}; + + PxTransform localFrame[2]; + + for (int i = 0; i < 2; ++i) + { + if (desc.destructible[i] == NULL) + { + structure[i] = NULL; + attachmentChunkIndex[i] = ModuleDestructibleConst::INVALID_CHUNK_INDEX; + + if(NULL == actor[i]) + { + // World constrained + PxMat33 rot(desc.globalAxis[i],desc.globalNormal[i],desc.globalAxis[i].cross(desc.globalNormal[i])); + + localFrame[i].p = desc.globalAnchor[i]; + localFrame[i].q = PxQuat(rot); + localFrame[i].q.normalize(); + } + else + { + // Constrained to physics object + PxMat33 rot(localAxis[i], localNormal[i], localAxis[i].cross(localNormal[i])); + + localFrame[i].p = localAnchor[i]; + localFrame[i].q = PxQuat(rot); + localFrame[i].q.normalize(); + } + continue; + } + + PxRigidDynamic* attachActor = NULL; + DestructibleActorImpl& destructible = ((DestructibleActorProxy*)desc.destructible[i])->impl; + structure[i] = destructible.getStructure(); + + attachmentChunkIndex[i] = desc.attachmentChunkIndex[i]; + + if (attachmentChunkIndex[i] >= 0 && attachmentChunkIndex[i] < (int32_t)destructible.getDestructibleAsset()->getChunkCount()) + { + DestructibleStructure::Chunk& chunk = structure[i]->chunks[destructible.getFirstChunkIndex() + attachmentChunkIndex[i]]; + attachActor = structure[i]->dscene->chunkIntact(chunk); + } + + SCOPED_PHYSX_LOCK_READ(dscene.getModulePhysXScene()); + + if (attachActor == NULL) + { + float minDistance = PX_MAX_F32; + for (uint32_t j = 0; j < destructible.getDestructibleAsset()->getChunkCount(); ++j) + { + DestructibleAssetParametersNS::Chunk_Type& source = destructible.getDestructibleAsset()->mParams->chunks.buf[j]; + const bool hasChildren = source.numChildren != 0; + if (!hasChildren) // Only attaching to lowest-level chunks, initially + { + DestructibleStructure::Chunk& chunk = structure[i]->chunks[destructible.getFirstChunkIndex() + j]; + PxRigidDynamic* actor = structure[i]->dscene->chunkIntact(chunk); + if (actor) + { + const float distance = (actor->getGlobalPose().transform(chunk.localSphereCenter) - desc.globalAnchor[i]).magnitude(); + if (distance < minDistance) + { + attachActor = actor; + attachmentChunkIndex[i] = (int32_t)(destructible.getFirstChunkIndex() + j); + minDistance = distance; + } + } + } + } + } + + if (attachActor == NULL) + { + APEX_DEBUG_WARNING("No physx actor could be found in destructible actor %p to attach the joint.", desc.destructible[i]); + return; + } + + actor[i] = (PxRigidActor*)attachActor; + + if (attachActor->getScene() != NULL && dscene.getModulePhysXScene() != attachActor->getScene()) + { + APEX_DEBUG_WARNING("Trying to joint actors from a scene different from the joint scene."); + return; + } + + localAnchor[i] = attachActor->getGlobalPose().transformInv(desc.globalAnchor[i]); + localAxis[i] = attachActor->getGlobalPose().rotateInv(desc.globalAxis[i]); + localNormal[i] = attachActor->getGlobalPose().rotateInv(desc.globalNormal[i]); + + PxMat33 rot(localAxis[i], localNormal[i], localAxis[i].cross(localNormal[i])); + + localFrame[i].p = localAnchor[i]; + localFrame[i].q = PxQuat(rot); + localFrame[i].q.normalize(); + } + + dscene.getModulePhysXScene()->lockRead(); + switch (desc.type) + { + case PxJointConcreteType::eD6: + joint = PxD6JointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]); + break; + case PxJointConcreteType::eDISTANCE: + joint = PxDistanceJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]); + break; + case PxJointConcreteType::eFIXED: + joint = PxFixedJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]); + break; + case PxJointConcreteType::ePRISMATIC: + joint = PxPrismaticJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]); + break; + case PxJointConcreteType::eREVOLUTE: + joint = PxRevoluteJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]); + break; + case PxJointConcreteType::eSPHERICAL: + joint = PxSphericalJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]); + break; + default: + PX_ALWAYS_ASSERT(); + break; + } + dscene.getModulePhysXScene()->unlockRead(); + + PX_ASSERT(joint != NULL); +} + +DestructibleActorJointImpl::~DestructibleActorJointImpl() +{ + if (joint) + { + joint->release(); + } +} + +bool DestructibleActorJointImpl::updateJoint() +{ + if (!joint) + { + return false; + } + + PxRigidActor* actors[2]; + joint->getActors(actors[0], actors[1]); + + bool needsReattachment = false; + for (uint32_t i = 0; i < 2; ++i) + { + if (structure[i] == NULL) + { + continue; + } + if (attachmentChunkIndex[i] < 0 || attachmentChunkIndex[i] >= (int32_t)structure[i]->chunks.size()) + { + return false; + } + DestructibleStructure::Chunk& chunk = structure[i]->chunks[(uint32_t)attachmentChunkIndex[i]]; + PxRigidDynamic* actor = structure[i]->dscene->chunkIntact(chunk); + if (actor == NULL) + { + return false; + } + if ((PxRigidDynamic*)actors[i] != actor) + { + needsReattachment = true; + actors[i] = (PxRigidDynamic*)actor; + } + + } + + if (!needsReattachment) + { + return true; + } + +#define JOINT_SET_ACTORS_WORKAROUND 1 +#if JOINT_SET_ACTORS_WORKAROUND + PxScene* pxScenes[2] = { NULL, NULL }; + for (uint32_t i = 0; i < 2; ++i) + { + if (actors[i] != NULL) + { + pxScenes[i] = actors[i]->getScene(); + if (actors[i]->getScene() != NULL) + { + pxScenes[i]->lockWrite(); + pxScenes[i]->removeActor(*actors[i], false); + pxScenes[i]->unlockWrite(); + } + } + } +#endif + joint->setActors(actors[0], actors[1]); +#if JOINT_SET_ACTORS_WORKAROUND + for (uint32_t i = 0; i < 2; ++i) + { + if (actors[i] != NULL && pxScenes[i] != NULL) + { + pxScenes[i]->lockWrite(); + pxScenes[i]->addActor(*actors[i]); + pxScenes[i]->unlockWrite(); + } + } +#endif + return joint != NULL; +} + +} +} // end namespace nvidia + + diff --git a/APEX_1.4/module/destructible/src/DestructibleAssetImpl.cpp b/APEX_1.4/module/destructible/src/DestructibleAssetImpl.cpp new file mode 100644 index 00000000..5939a084 --- /dev/null +++ b/APEX_1.4/module/destructible/src/DestructibleAssetImpl.cpp @@ -0,0 +1,3780 @@ +/* + * 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. + */ + + +#include "ApexDefs.h" +#include "Apex.h" +#include "DestructibleAssetImpl.h" +#include "DestructibleActorProxy.h" +#include "DestructiblePreviewProxy.h" +#include "ModuleDestructibleImpl.h" +#include "PxCooking.h" +#include "PxPhysics.h" +#include <PxScene.h> +#include "ModulePerfScope.h" +#include "ApexUsingNamespace.h" +#include "RenderMeshAssetIntl.h" +#include "Cof44.h" +#include "nvparameterized/NvParamUtils.h" +#include "PsMemoryBuffer.h" +#if APEX_USE_PARTICLES +#include "EmitterAsset.h" +#else +static const char* EMITTER_AUTHORING_TYPE_NAME = "ApexEmitterAsset"; +#endif + +#include "../../../framework/include/autogen/RenderMeshAssetParameters.h" +#include "../../../framework/include/ApexRenderMeshAsset.h" + + +#include "ApexSharedSerialization.h" +#include "ApexRand.h" + +#include "ApexMerge.h" +#include "ApexFind.h" + +namespace nvidia +{ +namespace destructible +{ +using namespace physx; + +struct ChunkSortElement +{ + int32_t index; + int32_t parentIndex; + int32_t depth; +}; + +struct IndexSortedEdge +{ + IndexSortedEdge() {} + IndexSortedEdge(uint32_t _i0, uint32_t _i1, uint32_t _submeshIndex, const PxVec3& _triangleNormal) + { + if (_i0 <= _i1) + { + i0 = _i0; + i1 = _i1; + } + else + { + i0 = _i1; + i1 = _i0; + } + submeshIndex = _submeshIndex; + triangleNormal = _triangleNormal; + } + + uint32_t i0; + uint32_t i1; + uint32_t submeshIndex; + PxVec3 triangleNormal; +}; + +// We'll use this struct to store trim planes for each hull in each part +struct TrimPlane +{ + uint32_t partIndex; + uint32_t hullIndex; + PxPlane plane; + + struct LessThan + { + PX_INLINE bool operator()(const TrimPlane& x, const TrimPlane& y) const + { + return x.partIndex != y.partIndex ? (x.partIndex < y.partIndex) : (x.hullIndex < y.hullIndex); + } + }; +}; + +#ifndef WITHOUT_APEX_AUTHORING +static int compareChunkParents( + const void* A, + const void* B) +{ + ChunkSortElement& eA = *(ChunkSortElement*)A; + ChunkSortElement& eB = *(ChunkSortElement*)B; + + const int32_t depthDiff = eA.depth - eB.depth; + if (depthDiff) + { + return depthDiff; + } + + const int32_t parentDiff = eA.parentIndex - eB.parentIndex; + if (parentDiff) + { + return parentDiff; + } + + return eA.index - eB.index; // Keeps sort stable +} +#endif + +void DestructibleAssetImpl::setParameters(const DestructibleParameters& parameters) +{ + setParameters(parameters, mParams->destructibleParameters); + + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("depthParameters", handle); + mParams->resizeArray(handle, (int32_t)parameters.depthParametersCount); + for (uint32_t i = 0; i < parameters.depthParametersCount; ++i) + { + DestructibleAssetParametersNS::DestructibleDepthParameters_Type& d = mParams->depthParameters.buf[i]; + const DestructibleDepthParameters& dparm = parameters.depthParameters[i]; + d.OVERRIDE_IMPACT_DAMAGE = (dparm.flags & DestructibleDepthParametersFlag::OVERRIDE_IMPACT_DAMAGE) ? true : false; + d.OVERRIDE_IMPACT_DAMAGE_VALUE = (dparm.flags & DestructibleDepthParametersFlag::OVERRIDE_IMPACT_DAMAGE_VALUE) ? true : false; + d.IGNORE_POSE_UPDATES = (dparm.flags & DestructibleDepthParametersFlag::IGNORE_POSE_UPDATES) ? true : false; + d.IGNORE_RAYCAST_CALLBACKS = (dparm.flags & DestructibleDepthParametersFlag::IGNORE_RAYCAST_CALLBACKS) ? true : false; + d.IGNORE_CONTACT_CALLBACKS = (dparm.flags & DestructibleDepthParametersFlag::IGNORE_CONTACT_CALLBACKS) ? true : false; + d.USER_FLAG_0 = (dparm.flags & DestructibleDepthParametersFlag::USER_FLAG_0) ? true : false; + d.USER_FLAG_1 = (dparm.flags & DestructibleDepthParametersFlag::USER_FLAG_1) ? true : false; + d.USER_FLAG_2 = (dparm.flags & DestructibleDepthParametersFlag::USER_FLAG_2) ? true : false; + d.USER_FLAG_3 = (dparm.flags & DestructibleDepthParametersFlag::USER_FLAG_3) ? true : false; + } +} + +void DestructibleAssetImpl::setParameters(const DestructibleParameters& parameters, DestructibleAssetParametersNS::DestructibleParameters_Type& destructibleParameters) +{ + destructibleParameters.damageCap = parameters.damageCap; + destructibleParameters.debrisDepth = parameters.debrisDepth; + destructibleParameters.debrisLifetimeMax = parameters.debrisLifetimeMax; + destructibleParameters.debrisLifetimeMin = parameters.debrisLifetimeMin; + destructibleParameters.debrisMaxSeparationMax = parameters.debrisMaxSeparationMax; + destructibleParameters.debrisMaxSeparationMin = parameters.debrisMaxSeparationMin; + destructibleParameters.debrisDestructionProbability = parameters.debrisDestructionProbability; + destructibleParameters.dynamicChunkDominanceGroup = parameters.dynamicChunksDominanceGroup; + destructibleParameters.dynamicChunksGroupsMask.useGroupsMask = parameters.useDynamicChunksGroupsMask; + destructibleParameters.dynamicChunksGroupsMask.bits0 = parameters.dynamicChunksFilterData.word0; + destructibleParameters.dynamicChunksGroupsMask.bits1 = parameters.dynamicChunksFilterData.word1; + destructibleParameters.dynamicChunksGroupsMask.bits2 = parameters.dynamicChunksFilterData.word2; + destructibleParameters.dynamicChunksGroupsMask.bits3 = parameters.dynamicChunksFilterData.word3; + destructibleParameters.supportStrength = parameters.supportStrength; + destructibleParameters.legacyChunkBoundsTestSetting = parameters.legacyChunkBoundsTestSetting; + destructibleParameters.legacyDamageRadiusSpreadSetting = parameters.legacyDamageRadiusSpreadSetting; + destructibleParameters.alwaysDrawScatterMesh = parameters.alwaysDrawScatterMesh; + + destructibleParameters.essentialDepth = parameters.essentialDepth; + destructibleParameters.flags.ACCUMULATE_DAMAGE = (parameters.flags & DestructibleParametersFlag::ACCUMULATE_DAMAGE) ? true : false; + destructibleParameters.flags.DEBRIS_TIMEOUT = (parameters.flags & DestructibleParametersFlag::DEBRIS_TIMEOUT) ? true : false; + destructibleParameters.flags.DEBRIS_MAX_SEPARATION = (parameters.flags & DestructibleParametersFlag::DEBRIS_MAX_SEPARATION) ? true : false; + destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS = (parameters.flags & DestructibleParametersFlag::CRUMBLE_SMALLEST_CHUNKS) ? true : false; + destructibleParameters.flags.ACCURATE_RAYCASTS = (parameters.flags & DestructibleParametersFlag::ACCURATE_RAYCASTS) ? true : false; + destructibleParameters.flags.USE_VALID_BOUNDS = (parameters.flags & DestructibleParametersFlag::USE_VALID_BOUNDS) ? true : false; + destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE = (parameters.flags & DestructibleParametersFlag::CRUMBLE_VIA_RUNTIME_FRACTURE) ? true : false; + destructibleParameters.forceToDamage = parameters.forceToDamage; + destructibleParameters.fractureImpulseScale = parameters.fractureImpulseScale; + destructibleParameters.damageDepthLimit = parameters.damageDepthLimit; + destructibleParameters.impactVelocityThreshold = parameters.impactVelocityThreshold; + destructibleParameters.maxChunkSpeed = parameters.maxChunkSpeed; + destructibleParameters.minimumFractureDepth = parameters.minimumFractureDepth; + destructibleParameters.impactDamageDefaultDepth = parameters.impactDamageDefaultDepth; + destructibleParameters.debrisDestructionProbability = parameters.debrisDestructionProbability; + destructibleParameters.validBounds = parameters.validBounds; + + // RT Fracture Parameters + destructibleParameters.runtimeFracture.sheetFracture = parameters.rtFractureParameters.sheetFracture; + destructibleParameters.runtimeFracture.depthLimit = parameters.rtFractureParameters.depthLimit; + destructibleParameters.runtimeFracture.destroyIfAtDepthLimit = parameters.rtFractureParameters.destroyIfAtDepthLimit; + destructibleParameters.runtimeFracture.minConvexSize = parameters.rtFractureParameters.minConvexSize; + destructibleParameters.runtimeFracture.impulseScale = parameters.rtFractureParameters.impulseScale; + destructibleParameters.runtimeFracture.glass.numSectors = parameters.rtFractureParameters.glass.numSectors; + destructibleParameters.runtimeFracture.glass.sectorRand = parameters.rtFractureParameters.glass.sectorRand; + destructibleParameters.runtimeFracture.glass.firstSegmentSize = parameters.rtFractureParameters.glass.firstSegmentSize; + destructibleParameters.runtimeFracture.glass.segmentScale = parameters.rtFractureParameters.glass.segmentScale; + destructibleParameters.runtimeFracture.glass.segmentRand = parameters.rtFractureParameters.glass.segmentRand; + destructibleParameters.runtimeFracture.attachment.posX = parameters.rtFractureParameters.attachment.posX; + destructibleParameters.runtimeFracture.attachment.negX = parameters.rtFractureParameters.attachment.negX; + destructibleParameters.runtimeFracture.attachment.posY = parameters.rtFractureParameters.attachment.posY; + destructibleParameters.runtimeFracture.attachment.negY = parameters.rtFractureParameters.attachment.negY; + destructibleParameters.runtimeFracture.attachment.posZ = parameters.rtFractureParameters.attachment.posZ; + destructibleParameters.runtimeFracture.attachment.negZ = parameters.rtFractureParameters.attachment.negZ; +} + +void DestructibleAssetImpl::setInitParameters(const DestructibleInitParameters& parameters) +{ + mParams->supportDepth = parameters.supportDepth; + mParams->formExtendedStructures = (parameters.flags & DestructibleInitParametersFlag::FORM_EXTENDED_STRUCTURES) ? true : false; + mParams->useAssetDefinedSupport = (parameters.flags & DestructibleInitParametersFlag::ASSET_DEFINED_SUPPORT) ? true : false; + mParams->useWorldSupport = (parameters.flags & DestructibleInitParametersFlag::WORLD_SUPPORT) ? true : false; +} + +DestructibleParameters DestructibleAssetImpl::getParameters() const +{ + return getParameters(mParams->destructibleParameters, &mParams->depthParameters); +} + +DestructibleParameters DestructibleAssetImpl::getParameters(const DestructibleAssetParametersNS::DestructibleParameters_Type& destructibleParameters, + const DestructibleAssetParametersNS::DestructibleDepthParameters_DynamicArray1D_Type* destructibleDepthParameters) +{ + DestructibleParameters parameters; + + parameters.damageCap = destructibleParameters.damageCap; + parameters.debrisDepth = destructibleParameters.debrisDepth; + parameters.debrisLifetimeMax = destructibleParameters.debrisLifetimeMax; + parameters.debrisLifetimeMin = destructibleParameters.debrisLifetimeMin; + parameters.debrisMaxSeparationMax = destructibleParameters.debrisMaxSeparationMax; + parameters.debrisMaxSeparationMin = destructibleParameters.debrisMaxSeparationMin; + parameters.dynamicChunksDominanceGroup = (uint8_t)destructibleParameters.dynamicChunkDominanceGroup; + parameters.useDynamicChunksGroupsMask = destructibleParameters.dynamicChunksGroupsMask.useGroupsMask; + parameters.dynamicChunksFilterData.word0 = destructibleParameters.dynamicChunksGroupsMask.bits0; + parameters.dynamicChunksFilterData.word1 = destructibleParameters.dynamicChunksGroupsMask.bits1; + parameters.dynamicChunksFilterData.word2 = destructibleParameters.dynamicChunksGroupsMask.bits2; + parameters.dynamicChunksFilterData.word3 = destructibleParameters.dynamicChunksGroupsMask.bits3; + parameters.essentialDepth = destructibleParameters.essentialDepth; + parameters.flags = 0; + parameters.alwaysDrawScatterMesh = destructibleParameters.alwaysDrawScatterMesh; + if (destructibleParameters.flags.ACCUMULATE_DAMAGE) + { + parameters.flags |= DestructibleParametersFlag::ACCUMULATE_DAMAGE; + } + if (destructibleParameters.flags.DEBRIS_TIMEOUT) + { + parameters.flags |= DestructibleParametersFlag::DEBRIS_TIMEOUT; + } + if (destructibleParameters.flags.DEBRIS_MAX_SEPARATION) + { + parameters.flags |= DestructibleParametersFlag::DEBRIS_MAX_SEPARATION; + } + if (destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS) + { + parameters.flags |= DestructibleParametersFlag::CRUMBLE_SMALLEST_CHUNKS; + } + if (destructibleParameters.flags.ACCURATE_RAYCASTS) + { + parameters.flags |= DestructibleParametersFlag::ACCURATE_RAYCASTS; + } + if (destructibleParameters.flags.USE_VALID_BOUNDS) + { + parameters.flags |= DestructibleParametersFlag::USE_VALID_BOUNDS; + } + if (destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE) + { + parameters.flags |= DestructibleParametersFlag::CRUMBLE_VIA_RUNTIME_FRACTURE; + } + parameters.forceToDamage = destructibleParameters.forceToDamage; + parameters.fractureImpulseScale = destructibleParameters.fractureImpulseScale; + parameters.damageDepthLimit = destructibleParameters.damageDepthLimit; + parameters.impactVelocityThreshold = destructibleParameters.impactVelocityThreshold; + parameters.maxChunkSpeed = destructibleParameters.maxChunkSpeed; + parameters.minimumFractureDepth = destructibleParameters.minimumFractureDepth; + parameters.impactDamageDefaultDepth = destructibleParameters.impactDamageDefaultDepth; + parameters.debrisDestructionProbability = destructibleParameters.debrisDestructionProbability; + parameters.validBounds = destructibleParameters.validBounds; + + if (destructibleDepthParameters) + { + //NvParameterized::Handle handle(*mParams); + //mParams->getParameterHandle("depthParameters", handle); + parameters.depthParametersCount = PxMin((uint32_t)DestructibleParameters::kDepthParametersCountMax, + (uint32_t)destructibleDepthParameters->arraySizes[0]); + for (int i = 0; i < (int)parameters.depthParametersCount; ++i) + { + DestructibleAssetParametersNS::DestructibleDepthParameters_Type& d = destructibleDepthParameters->buf[i]; + DestructibleDepthParameters& dparm = parameters.depthParameters[i]; + dparm.flags = 0; + if (d.OVERRIDE_IMPACT_DAMAGE) + { + dparm.flags |= DestructibleDepthParametersFlag::OVERRIDE_IMPACT_DAMAGE; + } + if (d.OVERRIDE_IMPACT_DAMAGE_VALUE) + { + dparm.flags |= DestructibleDepthParametersFlag::OVERRIDE_IMPACT_DAMAGE_VALUE; + } + if (d.IGNORE_POSE_UPDATES) + { + dparm.flags |= DestructibleDepthParametersFlag::IGNORE_POSE_UPDATES; + } + if (d.IGNORE_RAYCAST_CALLBACKS) + { + dparm.flags |= DestructibleDepthParametersFlag::IGNORE_RAYCAST_CALLBACKS; + } + if (d.IGNORE_CONTACT_CALLBACKS) + { + dparm.flags |= DestructibleDepthParametersFlag::IGNORE_CONTACT_CALLBACKS; + } + if (d.USER_FLAG_0) + { + dparm.flags |= DestructibleDepthParametersFlag::USER_FLAG_0; + } + if (d.USER_FLAG_1) + { + dparm.flags |= DestructibleDepthParametersFlag::USER_FLAG_1; + } + if (d.USER_FLAG_2) + { + dparm.flags |= DestructibleDepthParametersFlag::USER_FLAG_2; + } + if (d.USER_FLAG_3) + { + dparm.flags |= DestructibleDepthParametersFlag::USER_FLAG_3; + } + } + } + + // RT Fracture Parameters + parameters.rtFractureParameters.sheetFracture = destructibleParameters.runtimeFracture.sheetFracture; + parameters.rtFractureParameters.depthLimit = destructibleParameters.runtimeFracture.depthLimit; + parameters.rtFractureParameters.destroyIfAtDepthLimit = destructibleParameters.runtimeFracture.destroyIfAtDepthLimit; + parameters.rtFractureParameters.minConvexSize = destructibleParameters.runtimeFracture.minConvexSize; + parameters.rtFractureParameters.impulseScale = destructibleParameters.runtimeFracture.impulseScale; + parameters.rtFractureParameters.glass.numSectors = destructibleParameters.runtimeFracture.glass.numSectors; + parameters.rtFractureParameters.glass.sectorRand = destructibleParameters.runtimeFracture.glass.sectorRand; + parameters.rtFractureParameters.glass.firstSegmentSize = destructibleParameters.runtimeFracture.glass.firstSegmentSize; + parameters.rtFractureParameters.glass.segmentScale = destructibleParameters.runtimeFracture.glass.segmentScale; + parameters.rtFractureParameters.glass.segmentRand = destructibleParameters.runtimeFracture.glass.segmentRand; + parameters.rtFractureParameters.attachment.posX = destructibleParameters.runtimeFracture.attachment.posX; + parameters.rtFractureParameters.attachment.negX = destructibleParameters.runtimeFracture.attachment.negX; + parameters.rtFractureParameters.attachment.posY = destructibleParameters.runtimeFracture.attachment.posY; + parameters.rtFractureParameters.attachment.negY = destructibleParameters.runtimeFracture.attachment.negY; + parameters.rtFractureParameters.attachment.posZ = destructibleParameters.runtimeFracture.attachment.posZ; + parameters.rtFractureParameters.attachment.negZ = destructibleParameters.runtimeFracture.attachment.negZ; + parameters.supportStrength = destructibleParameters.supportStrength; + parameters.legacyChunkBoundsTestSetting = destructibleParameters.legacyChunkBoundsTestSetting; + parameters.legacyDamageRadiusSpreadSetting = destructibleParameters.legacyDamageRadiusSpreadSetting; + + return parameters; +} + +DestructibleInitParameters DestructibleAssetImpl::getInitParameters() const +{ + DestructibleInitParameters parameters; + + parameters.supportDepth = mParams->supportDepth; + parameters.flags = 0; + if (mParams->formExtendedStructures) + { + parameters.flags |= DestructibleInitParametersFlag::FORM_EXTENDED_STRUCTURES; + } + if (mParams->useAssetDefinedSupport) + { + parameters.flags |= DestructibleInitParametersFlag::ASSET_DEFINED_SUPPORT; + } + if (mParams->useWorldSupport) + { + parameters.flags |= DestructibleInitParametersFlag::WORLD_SUPPORT; + } + + return parameters; +} + +void DestructibleAssetImpl::setCrumbleEmitterName(const char* name) +{ + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("crumbleEmitterName", handle); + mParams->setParamString(handle, name ? name : ""); +} + +const char* DestructibleAssetImpl::getCrumbleEmitterName() const +{ + const char* name = mParams->crumbleEmitterName; + return (name && *name) ? name : NULL; +} + +void DestructibleAssetImpl::setDustEmitterName(const char* name) +{ + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("dustEmitterName", handle); + mParams->setParamString(handle, name ? name : ""); +} + +const char* DestructibleAssetImpl::getDustEmitterName() const +{ + const char* name = mParams->dustEmitterName; + return (name && *name) ? name : NULL; +} + +void DestructibleAssetImpl::setFracturePatternName(const char* name) +{ + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("fracturePatternName", handle); + mParams->setParamString(handle, name ? name : ""); +} + +const char* DestructibleAssetImpl::getFracturePatternName() const +{ + // TODO: Add to asset params + const char* name = "";//mParams->fracturePatternName; + return (name && *name) ? name : NULL; +} + +void DestructibleAssetImpl::setChunkOverlapsCacheDepth(int32_t depth) +{ + chunkOverlapCacheDepth = depth; +} + +void DestructibleAssetImpl::calculateChunkDepthStarts() +{ + const uint32_t chunkCount = (uint32_t)mParams->chunks.arraySizes[0]; + + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("firstChunkAtDepth", handle); + mParams->resizeArray(handle, (int32_t)mParams->depthCount + 1); + mParams->firstChunkAtDepth.buf[mParams->depthCount] = chunkCount; + + uint32_t stopIndex = 0; + for (uint32_t depth = 0; depth < mParams->depthCount; ++depth) + { + mParams->firstChunkAtDepth.buf[depth] = stopIndex; + while (stopIndex < chunkCount) + { + if (mParams->chunks.buf[stopIndex].depth != depth) + { + break; + } + ++stopIndex; + } + } +} + +CachedOverlapsNS::IntPair_DynamicArray1D_Type* DestructibleAssetImpl::getOverlapsAtDepth(uint32_t depth, bool create) const +{ + if (depth >= mParams->depthCount) + { + return NULL; + } + + int size = mParams->overlapsAtDepth.arraySizes[0]; + if (size <= (int)depth && !create) + { + return NULL; + } + + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("overlapsAtDepth", handle); + + if (create) + { + mParams->resizeArray(handle, (int32_t)mParams->depthCount); + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + while (size < (int)mParams->depthCount) + { + CachedOverlaps* cachedOverlaps = DYNAMIC_CAST(CachedOverlaps*)(traits->createNvParameterized(CachedOverlaps::staticClassName())); + mParams->overlapsAtDepth.buf[size++] = cachedOverlaps; + cachedOverlaps->isCached = false; + } + } + + CachedOverlaps* cachedOverlapsAtDepth = DYNAMIC_CAST(CachedOverlaps*)(mParams->overlapsAtDepth.buf[depth]); + if (!cachedOverlapsAtDepth->isCached) + { + if (!create) + { + return NULL; + } + physx::Array<IntPair> overlaps; + calculateChunkOverlaps(overlaps, depth); + NvParameterized::Handle overlapsHandle(*cachedOverlapsAtDepth); + cachedOverlapsAtDepth->getParameterHandle("overlaps", overlapsHandle); + overlapsHandle.resizeArray(2*(int32_t)overlaps.size()); + for (uint32_t i = 0; i < overlaps.size(); ++i) + { + IntPair& pair = overlaps[i]; + + CachedOverlapsNS::IntPair_Type& ppair = cachedOverlapsAtDepth->overlaps.buf[2*i]; + ppair.i0 = pair.i0; + ppair.i1 = pair.i1; + + CachedOverlapsNS::IntPair_Type& ppairSymmetric = cachedOverlapsAtDepth->overlaps.buf[2*i+1]; + ppairSymmetric.i0 = pair.i1; + ppairSymmetric.i1 = pair.i0; + } + qsort(cachedOverlapsAtDepth->overlaps.buf, (uint32_t)cachedOverlapsAtDepth->overlaps.arraySizes[0], sizeof(IntPair), IntPair::compare); + + cachedOverlapsAtDepth->isCached = 1; + } + + return &cachedOverlapsAtDepth->overlaps; +} + +void DestructibleAssetImpl::calculateChunkOverlaps(physx::Array<IntPair>& overlaps, uint32_t depth) const +{ + const float padding = mParams->neighborPadding * (mParams->bounds.maximum - mParams->bounds.minimum).magnitude(); + + const PxTransform identityTM(PxIdentity); + const PxVec3 identityScale(1.0f); + + const uint32_t startIndex = mParams->firstChunkAtDepth.buf[depth]; + const uint32_t stopIndex = mParams->firstChunkAtDepth.buf[depth + 1]; + const uint32_t chunksAtDepth = stopIndex - startIndex; + + // Find AABB overlaps + physx::Array<BoundsRep> chunkBoundsReps; + chunkBoundsReps.reserve(chunksAtDepth); + for (uint32_t chunkIndex = startIndex; chunkIndex < stopIndex; ++chunkIndex) + { + BoundsRep& chunkBoundsRep = chunkBoundsReps.insert(); + chunkBoundsRep.aabb = getChunkActorLocalBounds(chunkIndex); + PX_ASSERT(!chunkBoundsRep.aabb.isEmpty()); + chunkBoundsRep.aabb.fattenFast(padding); + } + if (chunkBoundsReps.size() > 0) + { + boundsCalculateOverlaps(overlaps, Bounds3XYZ, &chunkBoundsReps[0], chunkBoundsReps.size(), sizeof(chunkBoundsReps[0])); + } + + // Now do detailed overlap test + uint32_t overlapCount = 0; + for (uint32_t overlapIndex = 0; overlapIndex < overlaps.size(); ++overlapIndex) + { + IntPair& AABBOverlap = overlaps[overlapIndex]; + AABBOverlap.i0 += startIndex; + AABBOverlap.i1 += startIndex; + if (chunksInProximity(*this, (uint16_t)AABBOverlap.i0, identityTM, identityScale, *this, (uint16_t)AABBOverlap.i1, identityTM, identityScale, 2 * padding)) + { + overlaps[overlapCount++] = AABBOverlap; + } + } + + overlaps.resize(overlapCount); +} + +void DestructibleAssetImpl::cacheChunkOverlapsUpToDepth(int32_t depth) +{ + if (mParams->depthCount < 1) + { + return; + } + + if (depth < 0) + { + depth = (int32_t)mParams->supportDepth; + } + + depth = PxMin(depth, (int32_t)mParams->depthCount - 1); + + for (uint32_t d = 0; d <= (uint32_t)depth; ++d) + { + getOverlapsAtDepth(d); + } + + for (uint32_t d = (uint32_t)depth + 1; d < (uint32_t)mParams->overlapsAtDepth.arraySizes[0]; ++d) + { + CachedOverlaps* cachedOverlaps = DYNAMIC_CAST(CachedOverlaps*)(mParams->overlapsAtDepth.buf[d]); + NvParameterized::Handle handle(*cachedOverlaps); + cachedOverlaps->getParameterHandle("overlaps", handle); + cachedOverlaps->resizeArray(handle, 0); + } +} + + +void DestructibleAssetImpl::clearChunkOverlaps(int32_t depth, bool keepCachedFlag) +{ + int32_t depthStart = (depth < 0) ? 0 : depth; + int32_t depthEnd = (depth < 0) ? mParams->overlapsAtDepth.arraySizes[0] : PxMin(depth+1, mParams->overlapsAtDepth.arraySizes[0]); + for (int32_t d = depthStart; d < depthEnd; ++d) + { + CachedOverlaps* cachedOverlaps = DYNAMIC_CAST(CachedOverlaps*)(mParams->overlapsAtDepth.buf[d]); + NvParameterized::Handle handle(*cachedOverlaps); + cachedOverlaps->getParameterHandle("overlaps", handle); + cachedOverlaps->resizeArray(handle, 0); + if (!keepCachedFlag) + { + cachedOverlaps->isCached = false; + } + } +} + + +void DestructibleAssetImpl::addChunkOverlaps(IntPair* supportGraphEdges, uint32_t supportGraphEdgeCount) +{ + if (supportGraphEdgeCount == 0) + return; + + uint32_t numChunks = (uint32_t)mParams->chunks.arraySizes[0]; + + Array< Array<IntPair> > overlapsAtDepth(mParams->depthCount); + + // store symmetric pairs at corresponding depth + for (uint32_t i = 0; i < supportGraphEdgeCount; ++i) + { + uint32_t chunkIndex0 = (uint32_t)supportGraphEdges[i].i0; + uint32_t chunkIndex1 = (uint32_t)supportGraphEdges[i].i1; + + if (chunkIndex0 >= numChunks || chunkIndex1 >= numChunks) + { + APEX_DEBUG_WARNING("Edge %i supportGraphEdges has indices (%i,%i), but only a total of %i chunks are provided. supportEdges will be ignored.", i, chunkIndex0, chunkIndex1, numChunks); + overlapsAtDepth.clear(); + break; + } + + const DestructibleAssetParametersNS::Chunk_Type& chunk0 = mParams->chunks.buf[chunkIndex0]; + const DestructibleAssetParametersNS::Chunk_Type& chunk1 = mParams->chunks.buf[chunkIndex1]; + + if (chunk0.depth != chunk1.depth) + { + APEX_DEBUG_WARNING("Support graph can only have edges between sibling chunks. supportEdges will be ignored."); + overlapsAtDepth.clear(); + break; + } + + PX_ASSERT(chunk0.depth < mParams->depthCount); + + IntPair pair; + pair.i0 = (int32_t)chunkIndex0; + pair.i1 = (int32_t)chunkIndex1; + overlapsAtDepth[chunk0.depth].pushBack(pair); + + pair.i0 = (int32_t)chunkIndex1; + pair.i1 = (int32_t)chunkIndex0; + overlapsAtDepth[chunk0.depth].pushBack(pair); + } + + if (overlapsAtDepth.size() == 0) + return; + + + // for each depth + for (uint32_t depth = 0; depth < overlapsAtDepth.size(); ++depth) + { + if (overlapsAtDepth[depth].size() > 0) + { + // sort overlaps pairs + qsort(&overlapsAtDepth[depth][0], overlapsAtDepth[depth].size(), sizeof(IntPair), IntPair::compare); + } + + if (overlapsAtDepth[depth].size() == 0) + continue; + + // resize parameterized array + uint32_t numCachedDepths = (uint32_t)mParams->overlapsAtDepth.arraySizes[0]; + if (depth >= numCachedDepths) + { + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("overlapsAtDepth", handle); + mParams->resizeArray(handle, (int32_t)depth+1); + + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + for (uint32_t d = numCachedDepths; d < depth+1; ++d) + { + CachedOverlaps* cachedOverlaps = DYNAMIC_CAST(CachedOverlaps*)(traits->createNvParameterized(CachedOverlaps::staticClassName())); + mParams->overlapsAtDepth.buf[d] = cachedOverlaps; + cachedOverlaps->isCached = false; + } + } + + CachedOverlaps* cachedOverlapsAtDepth = DYNAMIC_CAST(CachedOverlaps*)(mParams->overlapsAtDepth.buf[depth]); + NvParameterized::Handle overlapsHandle(*cachedOverlapsAtDepth); + cachedOverlapsAtDepth->getParameterHandle("overlaps", overlapsHandle); + int32_t oldSize = cachedOverlapsAtDepth->overlaps.arraySizes[0]; + overlapsHandle.resizeArray(cachedOverlapsAtDepth->overlaps.arraySizes[0] + (int32_t)overlapsAtDepth[depth].size()); + + // merge new pairs into existing graph + bool ok = ApexMerge<IntPair>( (IntPair*)cachedOverlapsAtDepth->overlaps.buf, (uint32_t)oldSize, + &overlapsAtDepth[depth][0], overlapsAtDepth[depth].size(), + (IntPair*)cachedOverlapsAtDepth->overlaps.buf, (uint32_t)cachedOverlapsAtDepth->overlaps.arraySizes[0], + IntPair::compare); + + PX_UNUSED(ok); + PX_ASSERT(ok); + + // check for duplicates + if (cachedOverlapsAtDepth->overlaps.arraySizes[0] > 1) + { + Array<uint32_t> toRemove; + for (uint32_t j = 1; j < (uint32_t)cachedOverlapsAtDepth->overlaps.arraySizes[0]; ++j) + { + if (cachedOverlapsAtDepth->overlaps.buf[j].i1 == cachedOverlapsAtDepth->overlaps.buf[j-1].i1 && + cachedOverlapsAtDepth->overlaps.buf[j].i0 == cachedOverlapsAtDepth->overlaps.buf[j-1].i0) + { + toRemove.pushBack(j); + } + } + + // remove duplicates + toRemove.pushBack((uint32_t)cachedOverlapsAtDepth->overlaps.arraySizes[0]); // add guard + uint32_t shift = 0; + for (uint32_t j = 0; j < toRemove.size()-1; ++j) + { + ++shift; + for (uint32_t index = toRemove[j]+1; index < toRemove[j+1]; ++index) + { + cachedOverlapsAtDepth->overlaps.buf[index - shift] = cachedOverlapsAtDepth->overlaps.buf[index]; + } + } + NvParameterized::Handle overlapsHandle(*cachedOverlapsAtDepth); + cachedOverlapsAtDepth->getParameterHandle("overlaps", overlapsHandle); + overlapsHandle.resizeArray(cachedOverlapsAtDepth->overlaps.arraySizes[0] - (int32_t)shift); + } + + cachedOverlapsAtDepth->isCached = cachedOverlapsAtDepth->overlaps.arraySizes[0] > 0; + } +} + + +void DestructibleAssetImpl::removeChunkOverlaps(IntPair* supportGraphEdges, uint32_t numSupportGraphEdges, bool keepCachedFlagIfEmpty) +{ + Array< Array<uint32_t> > toRemoveAtDepth(mParams->depthCount); + for (uint32_t i = 0; i < numSupportGraphEdges; ++i) + { + CachedOverlapsNS::IntPair_Type& pair = (CachedOverlapsNS::IntPair_Type&)supportGraphEdges[i]; + + if (pair.i0 >= mParams->chunks.arraySizes[0] || pair.i1 >= mParams->chunks.arraySizes[0]) + continue; + + const DestructibleAssetParametersNS::Chunk_Type& chunk0 = mParams->chunks.buf[pair.i0]; + const DestructibleAssetParametersNS::Chunk_Type& chunk1 = mParams->chunks.buf[pair.i1]; + + if (chunk0.depth != chunk1.depth) + continue; + + if (chunk0.depth >= mParams->overlapsAtDepth.arraySizes[0]) + continue; + + if (chunk0.depth >= mParams->depthCount) + continue; + + CachedOverlaps* cachedOverlapsAtDepth = DYNAMIC_CAST(CachedOverlaps*)(mParams->overlapsAtDepth.buf[chunk0.depth]); + + // binary search for pair and add add to index to removal list + int32_t index = ApexFind(cachedOverlapsAtDepth->overlaps.buf, (uint32_t)cachedOverlapsAtDepth->overlaps.arraySizes[0], pair, IntPair::compare); + if (index != -1) + { + toRemoveAtDepth[chunk0.depth].pushBack((uint32_t)index); + } + + CachedOverlapsNS::IntPair_Type symmetricPair; + symmetricPair.i0 = pair.i1; + symmetricPair.i1 = pair.i0; + index = ApexFind(cachedOverlapsAtDepth->overlaps.buf, (uint32_t)cachedOverlapsAtDepth->overlaps.arraySizes[0], symmetricPair, IntPair::compare); + if (index != -1) + { + toRemoveAtDepth[chunk0.depth].pushBack((uint32_t)index); + } + } + + // go through removal list of each depth and shift remaining entries to overwrite the removed ones + for (uint32_t depth = 0; depth < toRemoveAtDepth.size(); ++depth) + { + CachedOverlaps* cachedOverlapsAtDepth = DYNAMIC_CAST(CachedOverlaps*)(mParams->overlapsAtDepth.buf[depth]); + toRemoveAtDepth[depth].pushBack((uint32_t)cachedOverlapsAtDepth->overlaps.arraySizes[0]); // add guard + uint32_t shift = 0; + for (uint32_t j = 1; j < toRemoveAtDepth[depth].size(); ++j) + { + ++shift; + for (uint32_t index = toRemoveAtDepth[depth][j-1]+1; index < toRemoveAtDepth[depth][j]; ++index) + { + cachedOverlapsAtDepth->overlaps.buf[index - shift] = cachedOverlapsAtDepth->overlaps.buf[index]; + } + } + + NvParameterized::Handle overlapsHandle(*cachedOverlapsAtDepth); + cachedOverlapsAtDepth->getParameterHandle("overlaps", overlapsHandle); + overlapsHandle.resizeArray(cachedOverlapsAtDepth->overlaps.arraySizes[0] - (int32_t)shift); + + if (!keepCachedFlagIfEmpty) + { + cachedOverlapsAtDepth->isCached = cachedOverlapsAtDepth->overlaps.arraySizes[0] > 0; + } + } +} + + +DestructibleAssetImpl::DestructibleAssetImpl(ModuleDestructibleImpl* inModule, DestructibleAsset* api, const char* name) : + mCrumbleAssetTracker(inModule->mSdk, EMITTER_AUTHORING_TYPE_NAME), + mDustAssetTracker(inModule->mSdk, EMITTER_AUTHORING_TYPE_NAME), + m_instancedChunkMeshCount(0) +{ + mApexDestructibleActorParams = 0; + init(); + + module = inModule; + mNxAssetApi = api; + mName = name; + + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + mParams = DYNAMIC_CAST(DestructibleAssetParameters*)(traits->createNvParameterized(DestructibleAssetParameters::staticClassName())); + mOwnsParams = mParams != NULL; + PX_ASSERT(mOwnsParams); +} + +DestructibleAssetImpl::DestructibleAssetImpl(ModuleDestructibleImpl* inModule, DestructibleAsset* api, NvParameterized::Interface* params, const char* name) + : mCrumbleAssetTracker(inModule->mSdk, EMITTER_AUTHORING_TYPE_NAME) + , mDustAssetTracker(inModule->mSdk, EMITTER_AUTHORING_TYPE_NAME) + , mRuntimeCookedConvexCount(0) + , m_instancedChunkMeshCount(0) +{ + mApexDestructibleActorParams = 0; + init(); + + module = inModule; + mNxAssetApi = api; + mName = name; + + mParams = DYNAMIC_CAST(DestructibleAssetParameters*)(params); + + // The pattern for NvParameterized assets is that the params pointer now belongs to the asset + mOwnsParams = true; + + // there's no deserialize, so init the ARMs + if (mParams->renderMeshAsset) + { + ApexSimpleString meshName = mName + ApexSimpleString("RenderMesh"); + module->mSdk->getInternalResourceProvider()->generateUniqueName(module->mSdk->getApexMeshNameSpace(), meshName); + + setRenderMeshAsset(static_cast<RenderMeshAsset*>(module->mSdk->createAsset(mParams->renderMeshAsset, meshName.c_str()))); + } + + // scatter meshes + bool scatterMeshAssetsValid = true; + physx::Array<RenderMeshAsset*> scatterMeshAssetArray((uint32_t)mParams->scatterMeshAssets.arraySizes[0]); + for (uint32_t i = 0; i < (uint32_t)mParams->scatterMeshAssets.arraySizes[0]; ++i) + { + if (i > 65535 || mParams->scatterMeshAssets.buf[i] == NULL) + { + scatterMeshAssetsValid = false; + break; + } + char suffix[20]; + sprintf(suffix, "ScatterMesh%d", i); + ApexSimpleString meshName = mName + ApexSimpleString(suffix); + module->mSdk->getInternalResourceProvider()->generateUniqueName(module->mSdk->getApexMeshNameSpace(), meshName); + scatterMeshAssetArray[i] = static_cast<RenderMeshAsset*>(module->mSdk->createAsset(mParams->scatterMeshAssets.buf[i], meshName.c_str())); + } + + bool success = false; + if (scatterMeshAssetsValid && mParams->scatterMeshAssets.arraySizes[0] > 0) + { + success = setScatterMeshAssets(&scatterMeshAssetArray[0], (uint32_t)mParams->scatterMeshAssets.arraySizes[0]); + } + if (!success) + { + for (uint32_t i = 0; i < scatterMeshAssetArray.size(); ++i) + { + if (scatterMeshAssetArray[i] != NULL) + { + scatterMeshAssetArray[i]->release(); + } + } + } + + bool hullWarningGiven = false; + + // Connect contained classes to referenced parameters + chunkConvexHulls.resize((uint32_t)mParams->chunkConvexHulls.arraySizes[0]); + for (uint32_t i = 0; i < chunkConvexHulls.size(); ++i) + { + chunkConvexHulls[i].init(mParams->chunkConvexHulls.buf[i]); + + // Fix convex hulls to account for adjacentFaces bug + if (chunkConvexHulls[i].mParams->adjacentFaces.arraySizes[0] != chunkConvexHulls[i].mParams->edges.arraySizes[0]) + { + chunkConvexHulls[i].buildFromPoints(chunkConvexHulls[i].mParams->vertices.buf, (uint32_t)chunkConvexHulls[i].mParams->vertices.arraySizes[0], + (uint32_t)chunkConvexHulls[i].mParams->vertices.elementSize); + if (!hullWarningGiven) + { + GetInternalApexSDK()->reportError(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, __FUNCTION__, + "Chunk convex hull data bad in asset %s, rebuilding. Asset should be re-exported.", name); + hullWarningGiven = true; + } + } + } + + m_currentInstanceBufferActorAllowance = mParams->initialDestructibleActorAllowanceForInstancing; + + physx::Array<uint16_t> tempPartToActorMap; + tempPartToActorMap.resize(renderMeshAsset->getPartCount(), 0xFFFF); + + m_instancedChunkMeshCount = 0; + + m_instancedChunkActorMap.resize((uint32_t)mParams->chunkInstanceInfo.arraySizes[0]); + for (uint32_t i = 0; i < (uint32_t)mParams->chunkInstanceInfo.arraySizes[0]; ++i) + { + uint16_t partIndex = mParams->chunkInstanceInfo.buf[i].partIndex; + if (tempPartToActorMap[partIndex] == 0xFFFF) + { + tempPartToActorMap[partIndex] = m_instancedChunkMeshCount++; + } + m_instancedChunkActorMap[i] = tempPartToActorMap[partIndex]; + } + + m_instancedChunkActorVisiblePart.resize(m_instancedChunkMeshCount); + for (uint32_t i = 0; i < (uint32_t)mParams->chunks.arraySizes[0]; ++i) + { + DestructibleAssetParametersNS::Chunk_Type& chunk = mParams->chunks.buf[i]; + if ((chunk.flags & DestructibleAssetImpl::Instanced) != 0) + { + uint16_t partIndex = mParams->chunkInstanceInfo.buf[chunk.meshPartIndex].partIndex; + m_instancedChunkActorVisiblePart[m_instancedChunkActorMap[chunk.meshPartIndex]] = partIndex; + } + } + + m_instancingRepresentativeActorIndex = -1; // not set + + reduceAccordingToLOD(); + + initializeAssetNameTable(); + + mStaticMaterialIDs.resize((uint32_t)mParams->staticMaterialNames.arraySizes[0]); + ResourceProviderIntl* resourceProvider = GetInternalApexSDK()->getInternalResourceProvider(); + ResID materialNS = GetInternalApexSDK()->getMaterialNameSpace(); + // Resolve material names using the NRP... + for (uint32_t i = 0; i < (uint32_t)mParams->staticMaterialNames.arraySizes[0]; ++i) + { + if (resourceProvider) + { + mStaticMaterialIDs[i] = resourceProvider->createResource(materialNS, mParams->staticMaterialNames.buf[i]); + } + else + { + mStaticMaterialIDs[i] = INVALID_RESOURCE_ID; + } + } +} + +DestructibleAssetImpl::~DestructibleAssetImpl() +{ + // Release named resources + ResourceProviderIntl* resourceProvider = GetInternalApexSDK()->getInternalResourceProvider(); + for (uint32_t i = 0 ; i < mStaticMaterialIDs.size() ; i++) + { + resourceProvider->releaseResource(mStaticMaterialIDs[i]); + } + + if (mParams != NULL && mOwnsParams) + { + mParams->destroy(); + } + mParams = NULL; + mOwnsParams = false; + + if (mApexDestructibleActorParams) + { + mApexDestructibleActorParams->destroy(); + mApexDestructibleActorParams = 0; + } + /* Assets that were forceloaded or loaded by actors will be automatically + * released by the ApexAssetTracker member destructors. + */ +} + +void DestructibleAssetImpl::init() +{ + module = NULL; + chunkOverlapCacheDepth = -1; + renderMeshAsset = NULL; + runtimeRenderMeshAsset = NULL; + mCollisionMeshes = NULL; + m_currentInstanceBufferActorAllowance = 0; + m_needsInstanceBufferDataResize = false; + m_needsInstanceBufferResize = false; + m_needsScatterMeshInstanceInfoCreation = false; +} + +uint32_t DestructibleAssetImpl::forceLoadAssets() +{ + uint32_t assetLoadedCount = 0; + + assetLoadedCount += mCrumbleAssetTracker.forceLoadAssets(); + assetLoadedCount += mDustAssetTracker.forceLoadAssets(); + + if (renderMeshAsset != NULL) + { + assetLoadedCount += renderMeshAsset->forceLoadAssets(); + } + + ResourceProviderIntl* nrp = GetInternalApexSDK()->getInternalResourceProvider(); + ResID materialNS = GetInternalApexSDK()->getMaterialNameSpace(); + for (uint32_t i = 0; i < mStaticMaterialIDs.size(); i++) + { + if (!nrp->checkResource(materialNS, mParams->staticMaterialNames.buf[i])) + { + /* we know for SURE that createResource() has already been called, so just getResource() */ + nrp->getResource(mStaticMaterialIDs[i]); + assetLoadedCount++; + } + } + + return assetLoadedCount; +} + +void DestructibleAssetImpl::initializeAssetNameTable() +{ + if (mParams->dustEmitterName && *mParams->dustEmitterName) + { + mDustAssetTracker.addAssetName(mParams->dustEmitterName, false); + } + + if (mParams->crumbleEmitterName && *mParams->crumbleEmitterName) + { + mCrumbleAssetTracker.addAssetName(mParams->crumbleEmitterName, false); + } +} + +void DestructibleAssetImpl::cleanup() +{ + // Release internal RenderMesh, preview instances, and authoring instance + + while (m_previewList.getSize()) + { + DestructiblePreviewProxy* proxy = DYNAMIC_CAST(DestructiblePreviewProxy*)(m_previewList.getResource(m_previewList.getSize() - 1)); + PX_ASSERT(proxy != NULL); + if (proxy == NULL) + { + m_previewList.remove(m_previewList.getSize() - 1); // To avoid an infinite loop + } + else + { + proxy->release(); + } + } + + m_previewList.clear(); + m_destructibleList.clear(); + + setRenderMeshAsset(NULL); + + // release chunk instance render resources + m_chunkInstanceBufferDataLock.lock(); + m_needsInstanceBufferResize = false; + m_chunkInstanceBufferData.clear(); + updateChunkInstanceRenderResources(false, NULL); + m_chunkInstanceBufferDataLock.unlock(); + + setScatterMeshAssets(NULL, 0); + + m_instancedChunkActorMap.resize(0); + m_instancedChunkActorVisiblePart.resize(0); + + if (module->mCachedData != NULL) + { + module->mCachedData->clearAssetCollisionSet(*this); + } +} + +void DestructibleAssetImpl::prepareForNewInstance() +{ + if (m_currentInstanceBufferActorAllowance < m_destructibleList.getSize() + 1) // Add 1 to predict new actor + { + // This loop should only be hit once + do + { + m_currentInstanceBufferActorAllowance = m_currentInstanceBufferActorAllowance > 0 ? 2*m_currentInstanceBufferActorAllowance : 1; + m_needsInstanceBufferDataResize = true; + } + while (m_currentInstanceBufferActorAllowance < m_destructibleList.getSize()); // Add 1 to predict new actor + } +} + + + +void DestructibleAssetImpl::resetInstanceData() +{ + PX_PROFILE_ZONE("DestructibleAsset::resetInstanceData", GetInternalApexSDK()->getContextId()); + + m_chunkInstanceBufferDataLock.lock(); + m_chunkInstanceBufferData.resize(m_instancedChunkMeshCount); + if (m_needsInstanceBufferDataResize) + { + // + // reserve the right amount of memory in the per chunk mesh arrays + // + for (uint32_t index = 0; index < m_instancedChunkMeshCount; ++index) + { + if (m_currentInstanceBufferActorAllowance > 0) + { + // Find out how many potential instances there are + uint32_t maxInstanceCount = 0; + for (int32_t i = 0; i < mParams->chunkInstanceInfo.arraySizes[0]; ++i) + { + if (mParams->chunkInstanceInfo.buf[i].partIndex == m_instancedChunkActorVisiblePart[index]) + { + maxInstanceCount += m_currentInstanceBufferActorAllowance; + } + } + + // Instance buffer data + m_chunkInstanceBufferData[index].reserve(maxInstanceCount); + } + + m_chunkInstanceBufferData[index].resize(0); + } + + m_needsInstanceBufferDataResize = false; + m_needsInstanceBufferResize = true; + } + else + { + for (uint32_t j = 0; j < m_chunkInstanceBufferData.size(); ++j) + { + m_chunkInstanceBufferData[j].resize(0); + } + } + m_chunkInstanceBufferDataLock.unlock(); + + + for (uint32_t j = 0; j < m_scatterMeshInstanceInfo.size(); ++j) + { + m_scatterMeshInstanceInfo[j].m_instanceBufferData.resize(0); + } + m_instancingRepresentativeActorIndex = -1; // not set +} + + +template <class ParamType> +DestructibleActor* createDestructibleActorImpl(ParamType& params, + DestructibleAssetImpl& destructibleAsset, + ResourceList& destructibleList, + DestructibleScene* destructibleScene) +{ + if (NULL == destructibleScene) + return NULL; + + destructibleAsset.prepareForNewInstance(); + + return PX_NEW(DestructibleActorProxy)(params, destructibleAsset, destructibleList, *destructibleScene); +} + +DestructibleActor* DestructibleAssetImpl::createDestructibleActorFromDeserializedState(NvParameterized::Interface* params, Scene& scene) +{ + PX_PROFILE_ZONE("DestructibleCreateActor", GetInternalApexSDK()->getContextId()); + + if (NULL == params || !isValidForActorCreation(*params, scene)) + return NULL; + + return createDestructibleActorImpl(params, *this, m_destructibleList, module->getDestructibleScene(scene)); +} + +DestructibleActor* DestructibleAssetImpl::createDestructibleActor(const NvParameterized::Interface& params, Scene& scene) +{ + PX_PROFILE_ZONE("DestructibleCreateActor", GetInternalApexSDK()->getContextId()); + + return createDestructibleActorImpl(params, *this, m_destructibleList, module->getDestructibleScene(scene)); +} + +void DestructibleAssetImpl::releaseDestructibleActor(DestructibleActor& nxactor) +{ + DestructibleActorProxy* proxy = DYNAMIC_CAST(DestructibleActorProxy*)(&nxactor); + proxy->destroy(); +} + +bool DestructibleAssetImpl::setRenderMeshAsset(RenderMeshAsset* newRenderMeshAsset) +{ + if (newRenderMeshAsset == renderMeshAsset) + { + return false; + } + + for (uint32_t i = 0; i < m_instancedChunkRenderMeshActors.size(); ++i) + { + if (m_instancedChunkRenderMeshActors[i] != NULL) + { + m_instancedChunkRenderMeshActors[i]->release(); + m_instancedChunkRenderMeshActors[i] = NULL; + } + } + + if (renderMeshAsset != NULL) + { + if(mOwnsParams && mParams != NULL) + { + // set isReferenced to false, so that the parameterized object + // for the render mesh asset is destroyed in renderMeshAsset->release + NvParameterized::ErrorType e; + if (mParams->renderMeshAsset != NULL) + { + NvParameterized::Handle h(*mParams->renderMeshAsset); + e = mParams->renderMeshAsset->getParameterHandle("isReferenced", h); + PX_ASSERT(e == NvParameterized::ERROR_NONE); + if (e == NvParameterized::ERROR_NONE) + { + h.setParamBool(false); + } + mParams->renderMeshAsset = NULL; + } + } + renderMeshAsset->release(); + } + + renderMeshAsset = newRenderMeshAsset; + if (renderMeshAsset != NULL) + { + mParams->renderMeshAsset = (NvParameterized::Interface*)renderMeshAsset->getAssetNvParameterized(); + NvParameterized::ErrorType e; + NvParameterized::Handle h(*mParams->renderMeshAsset); + e = mParams->renderMeshAsset->getParameterHandle("isReferenced", h); + PX_ASSERT(e == NvParameterized::ERROR_NONE); + if (e == NvParameterized::ERROR_NONE) + { + h.setParamBool(true); + } + + for (uint32_t i = 0; i < m_instancedChunkRenderMeshActors.size(); ++i) + { + // Create actor + RenderMeshActorDesc renderableMeshDesc; + renderableMeshDesc.maxInstanceCount = m_chunkInstanceBufferData[i].capacity(); + renderableMeshDesc.renderWithoutSkinning = true; + renderableMeshDesc.visible = false; + m_instancedChunkRenderMeshActors[i] = newRenderMeshAsset->createActor(renderableMeshDesc); + m_instancedChunkRenderMeshActors[i]->setInstanceBuffer(m_chunkInstanceBuffers[i]); + m_instancedChunkRenderMeshActors[i]->setVisibility(true, m_instancedChunkActorVisiblePart[i]); + m_instancedChunkRenderMeshActors[i]->setReleaseResourcesIfNothingToRender(false); + } + } + + return true; +} + +bool DestructibleAssetImpl::setScatterMeshAssets(RenderMeshAsset** scatterMeshAssetArray, uint32_t scatterMeshAssetArraySize) +{ + if (scatterMeshAssetArray == NULL && scatterMeshAssetArraySize > 0) + { + return false; + } + + for (uint32_t i = 0; i < scatterMeshAssetArraySize; ++i) + { + if (scatterMeshAssetArray[i] == NULL) + { + return false; + } + } + + // First clear instance information + m_scatterMeshInstanceInfo.resize(0); // Ensure we delete all instanced actors + m_scatterMeshInstanceInfo.resize(scatterMeshAssetArraySize); + + // Clear out scatter mesh assets, including parameterized data + for (int32_t i = 0; mParams && (i < mParams->scatterMeshAssets.arraySizes[0]); ++i) + { + if (mParams->scatterMeshAssets.buf[i] != NULL) + { + NvParameterized::ErrorType e; + NvParameterized::Handle h(*mParams->scatterMeshAssets.buf[i]); + e = mParams->scatterMeshAssets.buf[i]->getParameterHandle("isReferenced", h); + PX_ASSERT(e == NvParameterized::ERROR_NONE); + if (e == NvParameterized::ERROR_NONE) + { + h.setParamBool(false); + } + mParams->scatterMeshAssets.buf[i] = NULL; + } + } + + for (uint32_t i = 0; i < scatterMeshAssets.size(); ++i) + { + if (scatterMeshAssets[i] != NULL) + { + scatterMeshAssets[i]->release(); + scatterMeshAssets[i] = NULL; + } + } + + if (mParams != NULL) + { + scatterMeshAssets.resize(scatterMeshAssetArraySize, NULL); + NvParameterized::Handle h(*mParams, "scatterMeshAssets"); + h.resizeArray((int32_t)scatterMeshAssetArraySize); + + for (uint32_t i = 0; i < scatterMeshAssetArraySize; ++i) + { + // Create new asset + scatterMeshAssets[i] = scatterMeshAssetArray[i]; + mParams->scatterMeshAssets.buf[i] = (NvParameterized::Interface*)scatterMeshAssets[i]->getAssetNvParameterized(); + NvParameterized::ErrorType e; + NvParameterized::Handle h(*mParams->scatterMeshAssets.buf[i]); + e = mParams->scatterMeshAssets.buf[i]->getParameterHandle("isReferenced", h); + PX_ASSERT(e == NvParameterized::ERROR_NONE); + if (e == NvParameterized::ERROR_NONE) + { + h.setParamBool(true); + } + } + + m_needsScatterMeshInstanceInfoCreation = true; + } + + + return true; +} + +void DestructibleAssetImpl::createScatterMeshInstanceInfo() +{ + if (!m_needsScatterMeshInstanceInfoCreation) + return; + + m_needsScatterMeshInstanceInfoCreation = false; + + UserRenderResourceManager* rrm = GetInternalApexSDK()->getUserRenderResourceManager(); + + physx::Array<uint32_t> totalInstanceCounts(scatterMeshAssets.size(), 0); + for (int32_t i = 0; i < mParams->scatterMeshIndices.arraySizes[0]; ++i) + { + const uint8_t scatterMeshIndex = mParams->scatterMeshIndices.buf[i]; + if (scatterMeshIndex < scatterMeshAssets.size()) + { + ++totalInstanceCounts[scatterMeshIndex]; + } + } + + for (uint32_t i = 0; i < scatterMeshAssets.size(); ++i) + { + // Create instanced info + ScatterMeshInstanceInfo& info = m_scatterMeshInstanceInfo[i]; + RenderMeshActorDesc renderableMeshDesc; + renderableMeshDesc.maxInstanceCount = totalInstanceCounts[i]; + renderableMeshDesc.renderWithoutSkinning = true; + renderableMeshDesc.visible = true; + info.m_actor = scatterMeshAssets[i]->createActor(renderableMeshDesc); + + // Create instance buffer + info.m_instanceBuffer = NULL; + info.m_IBSize = totalInstanceCounts[i]; + if (totalInstanceCounts[i] > 0) + { + UserRenderInstanceBufferDesc instanceBufferDesc = getScatterMeshInstanceBufferDesc(); + instanceBufferDesc.maxInstances = totalInstanceCounts[i]; + info.m_instanceBuffer = rrm->createInstanceBuffer(instanceBufferDesc); + } + + // Instance buffer data + info.m_instanceBufferData.reset(); + info.m_instanceBufferData.reserve(totalInstanceCounts[i]); + + info.m_actor->setInstanceBuffer(info.m_instanceBuffer); + info.m_actor->setReleaseResourcesIfNothingToRender(false); + } +} + +UserRenderInstanceBufferDesc DestructibleAssetImpl::getScatterMeshInstanceBufferDesc() +{ + UserRenderInstanceBufferDesc instanceBufferDesc; + instanceBufferDesc.hint = RenderBufferHint::DYNAMIC; + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::POSITION_FLOAT3] = ScatterInstanceBufferDataElement::translationOffset(); + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::ROTATION_SCALE_FLOAT3x3] = ScatterInstanceBufferDataElement::scaledRotationOffset(); + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::DENSITY_FLOAT1] = ScatterInstanceBufferDataElement::alphaOffset(); + instanceBufferDesc.stride = sizeof(ScatterInstanceBufferDataElement); + + return instanceBufferDesc; +} + +void DestructibleAssetImpl::updateChunkInstanceRenderResources(bool rewriteBuffers, void* userRenderData) +{ + PX_PROFILE_ZONE("DestructibleAsset::updateChunkInstanceRenderResources", GetInternalApexSDK()->getContextId()); + + UserRenderResourceManager* rrm = GetInternalApexSDK()->getUserRenderResourceManager(); + + Mutex::ScopedLock scopeLock(m_chunkInstanceBufferDataLock); + + uint32_t oldCount = m_chunkInstanceBuffers.size(); + uint32_t count = m_chunkInstanceBufferData.size(); + + // + // release resources + // + // release all on resize for recreation lateron + uint32_t startIndexForRelease = m_needsInstanceBufferResize ? 0 : count; + for (uint32_t i = startIndexForRelease; i < oldCount; ++i) + { + if (m_instancedChunkRenderMeshActors[i] != NULL) + { + m_instancedChunkRenderMeshActors[i]->release(); + m_instancedChunkRenderMeshActors[i] = NULL; + } + if (m_chunkInstanceBuffers[i] != NULL) + { + rrm->releaseInstanceBuffer(*m_chunkInstanceBuffers[i]); + m_chunkInstanceBuffers[i] = NULL; + } + } + + // resize and init arrays + m_chunkInstanceBuffers.resize(count); + m_instancedChunkRenderMeshActors.resize(count); + for (uint32_t index = oldCount; index < count; ++index) + { + m_instancedChunkRenderMeshActors[index] = NULL; + m_chunkInstanceBuffers[index] = NULL; + } + + + // + // create resources when needed + // + + for (uint32_t index = 0; index < count; ++index) + { + // if m_chunkInstanceBufferData[index] contains any data there's an instance to render + if (m_chunkInstanceBuffers[index] == NULL && m_chunkInstanceBufferData[index].size() > 0) + { + // Find out how many potential instances there are + uint32_t maxInstanceCount = 0; + for (int32_t i = 0; i < mParams->chunkInstanceInfo.arraySizes[0]; ++i) + { + if (mParams->chunkInstanceInfo.buf[i].partIndex == m_instancedChunkActorVisiblePart[index]) + { + maxInstanceCount += m_currentInstanceBufferActorAllowance; + } + } + + // Create instance buffer + UserRenderInstanceBufferDesc instanceBufferDesc; + instanceBufferDesc.maxInstances = maxInstanceCount; + instanceBufferDesc.hint = RenderBufferHint::DYNAMIC; + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::POSITION_FLOAT3] = ChunkInstanceBufferDataElement::translationOffset(); + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::ROTATION_SCALE_FLOAT3x3] = ChunkInstanceBufferDataElement::scaledRotationOffset(); + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::UV_OFFSET_FLOAT2] = ChunkInstanceBufferDataElement::uvOffsetOffset(); + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::LOCAL_OFFSET_FLOAT3] = ChunkInstanceBufferDataElement::localOffsetOffset(); + instanceBufferDesc.stride = sizeof(ChunkInstanceBufferDataElement); + m_chunkInstanceBuffers[index] = rrm->createInstanceBuffer(instanceBufferDesc); + + // Create actor + if (renderMeshAsset != NULL) + { + PX_ASSERT(m_instancedChunkRenderMeshActors[index] == NULL); + + RenderMeshActorDesc renderableMeshDesc; + renderableMeshDesc.maxInstanceCount = maxInstanceCount; + renderableMeshDesc.renderWithoutSkinning = true; + renderableMeshDesc.visible = false; + m_instancedChunkRenderMeshActors[index] = renderMeshAsset->createActor(renderableMeshDesc); + m_instancedChunkRenderMeshActors[index]->setInstanceBuffer(m_chunkInstanceBuffers[index]); + m_instancedChunkRenderMeshActors[index]->setVisibility(true, m_instancedChunkActorVisiblePart[index]); + m_instancedChunkRenderMeshActors[index]->setReleaseResourcesIfNothingToRender(false); + } + } + + // + // update with new data + // + PX_ASSERT(index < m_chunkInstanceBufferData.size()); + RenderMeshActorIntl* renderMeshActor = (RenderMeshActorIntl*)m_instancedChunkRenderMeshActors[index]; + if (renderMeshActor != NULL) + { + RenderInstanceBufferData data; + const uint32_t instanceBufferSize = m_chunkInstanceBufferData[index].size(); + + if (instanceBufferSize > 0) + { + m_chunkInstanceBuffers[index]->writeBuffer(&m_chunkInstanceBufferData[index][0], 0, instanceBufferSize); + } + + renderMeshActor->setInstanceBufferRange(0, instanceBufferSize); + renderMeshActor->updateRenderResources(false, rewriteBuffers, userRenderData); + } + } + + m_needsInstanceBufferResize = false; +} + +bool DestructibleAssetImpl::setPlatformMaxDepth(PlatformTag platform, uint32_t maxDepth) +{ + bool isExistingPlatform = false; + for (Array<PlatformKeyValuePair>::Iterator iter = m_platformFractureDepthMap.begin(); iter != m_platformFractureDepthMap.end(); ++iter) + { + if (nvidia::strcmp(iter->key, platform) == 0) + { + isExistingPlatform = true; + iter->val = maxDepth; //overwrite if existing + break; + } + } + if (!isExistingPlatform) + { + m_platformFractureDepthMap.pushBack(PlatformKeyValuePair(platform, maxDepth)); + } + return maxDepth < mParams->depthCount - 1; //depthCount == 1 => unfractured mesh +} + +bool DestructibleAssetImpl::removePlatformMaxDepth(PlatformTag platform) +{ + bool isExistingPlatform = false; + for (uint32_t index = 0; index < m_platformFractureDepthMap.size(); ++index) + { + if (nvidia::strcmp(m_platformFractureDepthMap[index].key, platform) == 0) + { + isExistingPlatform = true; + m_platformFractureDepthMap.remove(index); //yikes! for lack of a map... + break; + } + } + return isExistingPlatform; +} + +bool DestructibleAssetImpl::setDepthCount(uint32_t targetDepthCount) const +{ + if (mParams->depthCount <= targetDepthCount) + { + return false; + } + + int newChunkCount = mParams->chunks.arraySizes[0]; + for (int i = newChunkCount; i--;) + { + if (mParams->chunks.buf[i].depth >= targetDepthCount) + { + newChunkCount = i; + } + else if (mParams->chunks.buf[i].depth == targetDepthCount - 1) + { + // These chunks must have no children + DestructibleAssetParametersNS::Chunk_Type& chunk = mParams->chunks.buf[i]; + chunk.numChildren = 0; + chunk.firstChildIndex = DestructibleAssetImpl::InvalidChunkIndex; + chunk.flags &= ~(uint16_t)DescendantUnfractureable; + } + else + { + break; + } + } + + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("chunks", handle); + mParams->resizeArray(handle, newChunkCount); + + mParams->getParameterHandle("overlapsAtDepth", handle); + int size; + mParams->getArraySize(handle, size); + if ((int)targetDepthCount < size) + { + mParams->resizeArray(handle, (int32_t)targetDepthCount); + } + mParams->getParameterHandle("firstChunkAtDepth", handle); + mParams->resizeArray(handle, (int32_t)targetDepthCount + 1); + + mParams->depthCount = targetDepthCount; + + return true; +} + +bool DestructibleAssetImpl::prepareForPlatform(nvidia::apex::PlatformTag platform) const +{ + bool isExistingPlatform = false; + bool isDepthLimitChanged = false; + for (Array<PlatformKeyValuePair>::ConstIterator kIter = m_platformFractureDepthMap.begin(); kIter != m_platformFractureDepthMap.end(); ++kIter) + { + if (nvidia::strcmp(kIter->key, platform) == 0) + { + isExistingPlatform = true; + isDepthLimitChanged = setDepthCount(kIter->val + 1); //targetDepthCount == 1 => unfractured mesh + break; + } + } + //if (!isExistingPlatform) {/*keep all depths, behaviour by default*/} + return (isExistingPlatform & isDepthLimitChanged); +} + +void DestructibleAssetImpl::reduceAccordingToLOD() +{ + if (module == NULL) + { + return; + } + + const uint32_t targetDepthCount = mParams->originalDepthCount > module->m_maxChunkDepthOffset ? mParams->originalDepthCount - module->m_maxChunkDepthOffset : 1; + + setDepthCount(targetDepthCount); +} + +void DestructibleAssetImpl::getStats(DestructibleAssetStats& stats) const +{ + memset(&stats, 0, sizeof(DestructibleAssetStats)); + + if (renderMeshAsset) + { + renderMeshAsset->getStats(stats.renderMeshAssetStats); + } + + // BRG - to do - need a way of getting the serialized size + stats.totalBytes = 0; + + stats.chunkCount = (uint32_t)mParams->chunks.arraySizes[0]; + stats.chunkBytes = mParams->chunks.arraySizes[0] * sizeof(DestructibleAssetParametersNS::Chunk_Type); + + uint32_t maxEdgeCount = 0; + + for (uint16_t chunkIndex = 0; chunkIndex < getChunkCount(); ++chunkIndex) + { + for (uint32_t hullIndex = getChunkHullIndexStart(chunkIndex); hullIndex < getChunkHullIndexStop(chunkIndex); ++hullIndex) + { + const ConvexHullImpl& hullData = chunkConvexHulls[hullIndex]; + const uint32_t hullDataBytes = hullData.getVertexCount() * sizeof(PxVec3) + + hullData.getUniquePlaneNormalCount() * 4 * sizeof(float) + + hullData.getUniquePlaneNormalCount() * sizeof(float) + + hullData.getEdgeCount() * sizeof(uint32_t); + stats.chunkHullDataBytes += hullDataBytes; + stats.chunkBytes += hullDataBytes; + + // Get cooked convex mesh stats + uint32_t numVerts = 0; + uint32_t numPolys = 0; + const uint32_t cookedHullDataBytes = hullData.calculateCookedSizes(numVerts, numPolys, true); + stats.maxHullVertexCount = PxMax(stats.maxHullVertexCount, numVerts); + stats.maxHullFaceCount = PxMax(stats.maxHullFaceCount, numPolys); + const uint32_t numEdges = numVerts + numPolys - 2; + if (numEdges > maxEdgeCount) + { + maxEdgeCount = numEdges; + stats.chunkWithMaxEdgeCount = chunkIndex; + } + + stats.chunkBytes += cookedHullDataBytes; + } + } + + stats.runtimeCookedConvexCount = mRuntimeCookedConvexCount; + /* To do - count collision data in ApexScene! */ +} + +void DestructibleAssetImpl::applyTransformation(const PxMat44& transformation, float scale) +{ + /* For now, we'll just clear the current cached streams at scale. */ + /* transform and scale the PxConvexMesh(es) */ + if (mParams->collisionData) + { + APEX_DEBUG_WARNING("Cached collision data is already present, removing"); + mParams->collisionData->destroy(); + mParams->collisionData = NULL; +#if 0 + DestructibleAssetCollisionDataSet* cds = + DYNAMIC_CAST(DestructibleAssetCollisionDataSet*)(mParams->collisionData); + + for (int i = 0; i < cds->meshCookedCollisionStreamsAtScale.arraySizes[0]; ++i) + { + PX_ASSERT(cds->meshCookedCollisionStreamsAtScale.buf[i]); + + MeshCookedCollisionStreamsAtScale* meshStreamsAtScale = + DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(cds->meshCookedCollisionStreamsAtScale.buf[i]); + for (int j = 0; j < meshStreamsAtScale->meshCookedCollisionStreams.arraySizes[0]; ++j) + { + PX_ASSERT(meshStreamsAtScale->meshCookedCollisionStreams.buf[i]); + + MeshCookedCollisionStream* meshStreamParams = + DYNAMIC_CAST(MeshCookedCollisionStream*)(meshStreamsAtScale->meshCookedCollisionStreams.buf[i]); + + /* stream it into the physx sdk */ + nvidia::PsMemoryBuffer memStream(meshStreamParams->bytes.buf, meshStreamParams->bytes.arraySizes[0]); + memStream.setEndianMode(PxFileBuf::ENDIAN_NONE); + PxStreamFromFileBuf nvs(memStream); + PxConvexMesh* convexMesh = GetApexSDK()->getPhysXSDK()->createConvexMesh(nxs); + + PxConvexMeshDesc meshDesc; + convexMesh->saveToDesc(meshDesc); + meshDesc. + + uint32_t submeshCount = convexMesh->getSubmeshCount(); + (void)submeshCount; + } + } +#endif + } + + /* chunk surface normal */ + for (int i = 0; i < mParams->chunks.arraySizes[0]; ++i) + { + PX_ASSERT(mParams->chunks.buf); + + DestructibleAssetParametersNS::Chunk_Type* chunk = &(mParams->chunks.buf[i]); + + chunk->surfaceNormal = transformation.rotate(chunk->surfaceNormal); + } + + /* bounds */ + PX_ASSERT(!mParams->bounds.isEmpty()); + mParams->bounds.minimum *= scale; + mParams->bounds.maximum *= scale; + if (scale < 0.0f) + { + nvidia::swap(mParams->bounds.minimum, mParams->bounds.maximum); + } + mParams->bounds = PxBounds3::transformSafe(PxTransform(transformation), mParams->bounds); + + /* chunk convex hulls */ + for (int i = 0; i < mParams->chunkConvexHulls.arraySizes[0]; ++i) + { + PX_ASSERT(mParams->chunkConvexHulls.buf[i]); + ConvexHullImpl chunkHull; + chunkHull.mParams = DYNAMIC_CAST(ConvexHullParameters*)(mParams->chunkConvexHulls.buf[i]); + chunkHull.mOwnsParams = false; + chunkHull.applyTransformation(transformation, scale); + } + + /* render mesh (just apply to both the asset and author if they both exist) */ + if (renderMeshAsset) + { + reinterpret_cast<RenderMeshAssetIntl*>(renderMeshAsset)->applyTransformation(transformation, scale); + } + + /* scatter meshes */ + const PxMat33 m33(transformation.column0.getXYZ(), transformation.column1.getXYZ(), transformation.column2.getXYZ()); + for (int i = 0; i < mParams->scatterMeshTransforms.arraySizes[0]; ++i) + { + PxMat44& tm = mParams->scatterMeshTransforms.buf[i]; + PxMat33 tm33(tm.column0.getXYZ(), tm.column1.getXYZ(), tm.column2.getXYZ()); + + tm33 = m33*tm33; + tm33 *= scale; + const PxVec3 pos = transformation.getPosition() + scale*(m33*tm.getPosition()); + tm.column0 = PxVec4(tm33.column0, 0); + tm.column1 = PxVec4(tm33.column1, 0); + tm.column2 = PxVec4(tm33.column2, 0); + tm.setPosition(pos); + } + if (m33.getDeterminant() * scale < 0.0f) + { + for (uint32_t i = 0; i < scatterMeshAssets.size(); ++i) + { + RenderMeshAsset* scatterMesh = scatterMeshAssets[i]; + if (scatterMesh != NULL) + { + reinterpret_cast<RenderMeshAssetIntl*>(scatterMesh)->reverseWinding(); + } + } + } +} + +void DestructibleAssetImpl::applyTransformation(const PxMat44& transformation) +{ + /* For now, we'll just clear the current cached streams at scale. */ + /* transform and scale the PxConvexMesh(es) */ + if (mParams->collisionData) + { + APEX_DEBUG_WARNING("Cached collision data is already present, removing"); + mParams->collisionData->destroy(); + mParams->collisionData = NULL; + } + + Cof44 cofTM(transformation); + + /* chunk surface normal */ + for (int i = 0; i < mParams->chunks.arraySizes[0]; ++i) + { + PX_ASSERT(mParams->chunks.buf); + + DestructibleAssetParametersNS::Chunk_Type* chunk = &(mParams->chunks.buf[i]); + + chunk->surfaceNormal = cofTM.getBlock33().transform(chunk->surfaceNormal); + chunk->surfaceNormal.normalize(); + } + + /* bounds */ + PX_ASSERT(!mParams->bounds.isEmpty()); + mParams->bounds = PxBounds3::transformSafe(PxTransform(transformation), mParams->bounds); + + /* chunk convex hulls */ + for (int i = 0; i < mParams->chunkConvexHulls.arraySizes[0]; ++i) + { + PX_ASSERT(mParams->chunkConvexHulls.buf[i]); + ConvexHullImpl chunkHull; + chunkHull.mParams = DYNAMIC_CAST(ConvexHullParameters*)(mParams->chunkConvexHulls.buf[i]); + chunkHull.mOwnsParams = false; + chunkHull.applyTransformation(transformation); + } + + /* render mesh (just apply to both the asset and author if they both exist) */ + if (renderMeshAsset) + { + reinterpret_cast<RenderMeshAssetIntl*>(renderMeshAsset)->applyTransformation(transformation, 1.0f); // This transformation function properly handles non-uniform scales + } +} + +void DestructibleAssetImpl::traceSurfaceBoundary(physx::Array<PxVec3>& outPoints, uint16_t chunkIndex, const PxTransform& localToWorldRT, const PxVec3& scale, + float spacing, float jitter, float surfaceDistance, uint32_t maxPoints) +{ + outPoints.resize(0); + + // Removing this function's implementation for now + + PX_UNUSED(chunkIndex); + PX_UNUSED(localToWorldRT); + PX_UNUSED(scale); + PX_UNUSED(spacing); + PX_UNUSED(jitter); + PX_UNUSED(surfaceDistance); + PX_UNUSED(maxPoints); +} + + +bool DestructibleAssetImpl::rebuildCollisionGeometry(uint32_t partIndex, const DestructibleGeometryDesc& geometryDesc) +{ +#ifdef WITHOUT_APEX_AUTHORING + PX_UNUSED(partIndex); + PX_UNUSED(geometryDesc); + APEX_DEBUG_WARNING("DestructibleAsset::rebuildCollisionGeometry is not available in release builds."); + return false; +#else + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("chunkConvexHulls", handle); + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + + const uint32_t startHullIndex = mParams->chunkConvexHullStartIndices.buf[partIndex]; + uint32_t hullCount = geometryDesc.convexHullCount; + const nvidia::ExplicitHierarchicalMesh::ConvexHull** convexHulls = geometryDesc.convexHulls; + physx::Array<PartConvexHullProxy*> collision; + if (hullCount == 0 && geometryDesc.collisionVolumeDesc != NULL) + { + physx::Array<PxVec3> vertices; + physx::Array<uint32_t> indices; + gatherPartMesh(vertices, indices, renderMeshAsset, partIndex); + buildCollisionGeometry(collision, *geometryDesc.collisionVolumeDesc, vertices.begin(), vertices.size(), sizeof(PxVec3), indices.begin(), indices.size()); + convexHulls = (const nvidia::ExplicitHierarchicalMesh::ConvexHull**)collision.begin(); + hullCount = collision.size(); + } + const uint32_t oldStopHullIndex = mParams->chunkConvexHullStartIndices.buf[partIndex + 1]; + const uint32_t oldHullCount = oldStopHullIndex - startHullIndex; + const uint32_t stopHullIndex = startHullIndex + hullCount; + const int32_t hullCountDelta = (int32_t)(hullCount - oldHullCount); + + // Adjust start indices + for (uint32_t i = partIndex+1; i < (uint32_t)mParams->chunkConvexHullStartIndices.arraySizes[0]; ++i) + { + mParams->chunkConvexHullStartIndices.buf[i] += hullCountDelta; + } + const uint32_t totalHullCount = (uint32_t)mParams->chunkConvexHullStartIndices.buf[mParams->chunkConvexHullStartIndices.arraySizes[0]-1]; + + // Eliminate hulls if the count has decreased + if (hullCountDelta < 0) + { + for (uint32_t index = stopHullIndex; index < totalHullCount; ++index) + { + chunkConvexHulls[index].mParams->copy( *chunkConvexHulls[index-hullCountDelta].mParams ); + } + } + + // Resize the hull arrays + if (hullCountDelta != 0) + { + mParams->resizeArray(handle, (int32_t)totalHullCount); + chunkConvexHulls.resize(totalHullCount); + } + + // Insert hulls if the count has increased + if (hullCountDelta > 0) + { + for (uint32_t index = totalHullCount; index-- > stopHullIndex;) + { + mParams->chunkConvexHulls.buf[index] = mParams->chunkConvexHulls.buf[index-hullCountDelta]; + chunkConvexHulls[index].init(mParams->chunkConvexHulls.buf[index]); + } + for (uint32_t index = oldStopHullIndex; index < stopHullIndex; ++index) + { + mParams->chunkConvexHulls.buf[index] = traits->createNvParameterized(ConvexHullParameters::staticClassName()); + chunkConvexHulls[index].init(mParams->chunkConvexHulls.buf[index]); + } + } + + if (hullCount > 0) + { + for (uint32_t hullNum = 0; hullNum < hullCount; ++hullNum) + { + ConvexHullImpl& chunkHullData = chunkConvexHulls[startHullIndex + hullNum]; + PartConvexHullProxy* convexHullProxy = (PartConvexHullProxy*)convexHulls[hullNum]; + chunkHullData.mParams->copy(*convexHullProxy->impl.mParams); + if (chunkHullData.isEmpty()) + { + chunkHullData.buildFromAABB(renderMeshAsset->getBounds(partIndex)); // \todo: need better way of simplifying + } + } + } + + return hullCount > 0; +#endif +} + + +// DestructibleAssetAuthoring +#ifndef WITHOUT_APEX_AUTHORING + + + +void gatherPartMesh(physx::Array<PxVec3>& vertices, + physx::Array<uint32_t>& indices, + const RenderMeshAsset* renderMeshAsset, + uint32_t partIndex) +{ + if (renderMeshAsset == NULL || partIndex >= renderMeshAsset->getPartCount()) + { + vertices.resize(0); + indices.resize(0); + return; + } + + + // Pre-count vertices and indices so we can allocate once + uint32_t vertexCount = 0; + uint32_t indexCount = 0; + for (uint32_t submeshIndex = 0; submeshIndex < renderMeshAsset->getSubmeshCount(); ++submeshIndex) + { + const RenderSubmesh& submesh = renderMeshAsset->getSubmesh(submeshIndex); + vertexCount += submesh.getVertexCount(partIndex); + indexCount += submesh.getIndexCount(partIndex); + } + + vertices.resize(vertexCount); + indices.resize(indexCount); + + vertexCount = 0; + indexCount = 0; + for (uint32_t submeshIndex = 0; submeshIndex < renderMeshAsset->getSubmeshCount(); ++submeshIndex) + { + const RenderSubmesh& submesh = renderMeshAsset->getSubmesh(submeshIndex); + if (submesh.getVertexCount(partIndex) > 0) + { + const VertexBuffer& vertexBuffer = submesh.getVertexBuffer(); + const VertexFormat& vertexFormat = vertexBuffer.getFormat(); + const int32_t bufferIndex = vertexFormat.getBufferIndexFromID(vertexFormat.getSemanticID(nvidia::RenderVertexSemantic::POSITION)); + if (bufferIndex >= 0) + { + vertexBuffer.getBufferData(&vertices[vertexCount], nvidia::RenderDataFormat::FLOAT3, sizeof(PxVec3), (uint32_t)bufferIndex, + submesh.getFirstVertexIndex(partIndex), submesh.getVertexCount(partIndex)); + } + else + { + memset(&vertices[vertexCount], 0, submesh.getVertexCount(partIndex)*sizeof(PxVec3)); + } + const uint32_t* partIndexBuffer = submesh.getIndexBuffer(partIndex); + const uint32_t partIndexCount = submesh.getIndexCount(partIndex); + for (uint32_t indexNum = 0; indexNum < partIndexCount; ++indexNum) + { + indices[indexCount++] = partIndexBuffer[indexNum] + vertexCount - submesh.getFirstVertexIndex(partIndex); + } + vertexCount += submesh.getVertexCount(partIndex); + } + } +} + + +/** + Private function - it's way too finicky and really only meant to serve the (public) trimCollisionVolumes function. + The chunkIndices array is expected to contain every member of an instanced set. That is, if a chunk indexed by some element of chunkIndices + references partIndex, then *every* chunk that references partIndex should be in the chunkIndices array. + Also, all chunks in chunkIndices are expected to be at the same depth. +*/ +void DestructibleAssetAuthoringImpl::trimCollisionGeometryInternal(const uint32_t* chunkIndices, uint32_t chunkIndexCount, const physx::Array<IntPair>& parentDepthOverlaps, uint32_t depth, float maxTrimFraction) +{ + /* + 1) Find overlaps between each chunk (hull to hull). + 2) For each overlap: + a) Create a trim plane for the overlapping hulls (one for each). Adjust the trim planes to respect maxTrimFraction. + 3) For each chunk: + a) For each hull in the chunk: + i) Add additional trim planes from all parent chunks' neighbors' hulls, and sibling's hulls. Adjust trim planes to respect maxTrimFraction. + 4) Intersect the trimmed hull(s) from (2) and (3) with the trim planes. This may cause some hulls to disappear. + 5) Recurse to children + */ + + // Create an epslion + PxBounds3 bounds = renderMeshAsset->getBounds(); + const float sizeScale = (bounds.minimum - bounds.maximum).magnitude(); + const float eps = 0.0001f * sizeScale; // \todo - expose? + + // 1) Find overlaps between each chunk (hull to hull). + const PxMat44 identityTM(PxVec4(1.0f)); + const PxVec3 identityScale(1.0f); + + // Find AABB overlaps + physx::Array<BoundsRep> chunkBoundsReps; + chunkBoundsReps.reserve(chunkIndexCount); + for (uint32_t chunkNum = 0; chunkNum < chunkIndexCount; ++chunkNum) + { + const uint32_t chunkIndex = chunkIndices[chunkNum]; + BoundsRep& chunkBoundsRep = chunkBoundsReps.insert(); + chunkBoundsRep.aabb = getChunkActorLocalBounds(chunkIndex); + } + physx::Array<IntPair> overlaps; + if (chunkBoundsReps.size() > 0) + { + boundsCalculateOverlaps(overlaps, Bounds3XYZ, &chunkBoundsReps[0], chunkBoundsReps.size(), sizeof(chunkBoundsReps[0])); + } + + // We'll store the trim planes here + physx::Array<TrimPlane> trimPlanes; + + // Now do detailed overlap test + for (uint32_t overlapIndex = 0; overlapIndex < overlaps.size(); ++overlapIndex) + { + IntPair& AABBOverlap = overlaps[overlapIndex]; + const uint32_t chunkIndex0 = chunkIndices[AABBOverlap.i0]; + const uint32_t chunkIndex1 = chunkIndices[AABBOverlap.i1]; + + // Offset chunks (in case they are instanced) + const PxTransform tm0(getChunkPositionOffset(chunkIndex0)); + const PxTransform tm1(getChunkPositionOffset(chunkIndex1)); + for (uint32_t hullIndex0 = getChunkHullIndexStart(chunkIndex0); hullIndex0 < getChunkHullIndexStop(chunkIndex0); ++hullIndex0) + { + TrimPlane trimPlane0; + trimPlane0.hullIndex = hullIndex0; + trimPlane0.partIndex = getPartIndex(chunkIndex0); + for (uint32_t hullIndex1 = getChunkHullIndexStart(chunkIndex1); hullIndex1 < getChunkHullIndexStop(chunkIndex1); ++hullIndex1) + { + TrimPlane trimPlane1; + trimPlane1.hullIndex = hullIndex1; + trimPlane1.partIndex = getPartIndex(chunkIndex1); + ConvexHullImpl::Separation separation; + if (ConvexHullImpl::hullsInProximity(chunkConvexHulls[hullIndex0], tm0, identityScale, chunkConvexHulls[hullIndex1], tm1, identityScale, 0.0f, &separation)) + { + // 2) For each overlap: + // a) Create a trim plane for the overlapping hulls (one for each). Adjust the trim planes to respect maxTrimFraction. + trimPlane0.plane = separation.plane; + trimPlane0.plane.d = PxMin(trimPlane0.plane.d, maxTrimFraction*(separation.max0-separation.min0) - separation.max0); // Bound clip distance + trimPlane0.plane.d += trimPlane0.plane.n.dot(tm0.p); // Transform back into part local space + trimPlanes.pushBack(trimPlane0); + trimPlane1.plane = PxPlane(-separation.plane.n, -separation.plane.d); + trimPlane1.plane.d = PxMin(trimPlane1.plane.d, maxTrimFraction*(separation.max1-separation.min1) + separation.min1); // Bound clip distance + trimPlane1.plane.d += trimPlane1.plane.n.dot(tm1.p); // Transform back into part local space + trimPlanes.pushBack(trimPlane1); + } + } + } + } + + // Get overlaps for this depth + physx::Array<IntPair> overlapsAtDepth; + calculateChunkOverlaps(overlapsAtDepth, depth); + + // 3) For each chunk: + for (uint32_t chunkNum = 0; chunkNum < chunkIndexCount; ++chunkNum) + { + const uint32_t chunkIndex = chunkIndices[chunkNum]; + const PxTransform tm0(getChunkPositionOffset(chunkIndex)); + const int32_t chunkParentIndex = mParams->chunks.buf[chunkIndex].parentIndex; + + for (int ancestorLevel = 0; ancestorLevel < 2; ++ancestorLevel) // First time iterate through uncles, second time through siblings + { + // Optimization opportunity: symmetrize, sort and index the overlap list + uint32_t overlapCount; + const IntPair* overlapArray; + if (ancestorLevel == 0) + { + overlapCount = parentDepthOverlaps.size(); + overlapArray = parentDepthOverlaps.begin(); + } + else + { + overlapCount = overlapsAtDepth.size(); + overlapArray = overlapsAtDepth.begin(); + } + for (uint32_t overlapNum = 0; overlapNum < overlapCount; ++overlapNum) + { + const IntPair& overlap = overlapArray[overlapNum]; + uint32_t otherChunkIndex; + const int32_t ignoreChunkIndex = ancestorLevel == 0 ? chunkParentIndex : (int32_t)chunkIndex; + if (overlap.i0 == ignoreChunkIndex) + { + otherChunkIndex = (uint32_t)overlap.i1; + } + else + if (overlap.i1 == ignoreChunkIndex) + { + otherChunkIndex = (uint32_t)overlap.i0; + } + else + { + continue; + } + // Make sure we're not trimming from a chunk already in our chunk list (we've handled that already) + bool alreadyConsidered = false; + if (ancestorLevel == 1) + { + for (uint32_t checkNum = 0; checkNum < chunkIndexCount; ++checkNum) + { + if (chunkIndices[checkNum] == otherChunkIndex) + { + alreadyConsidered = true; + break; + } + } + } + if (alreadyConsidered) + { + continue; + } + // Check other Chunk + const PxTransform tm1(getChunkPositionOffset(otherChunkIndex)); + // a) For each hull in the chunk: + for (uint32_t hullIndex0 = getChunkHullIndexStart(chunkIndex); hullIndex0 < getChunkHullIndexStop(chunkIndex); ++hullIndex0) + { + TrimPlane trimPlane; + trimPlane.hullIndex = hullIndex0; + trimPlane.partIndex = getPartIndex(chunkIndex); + for (uint32_t hullIndex1 = getChunkHullIndexStart(otherChunkIndex); hullIndex1 < getChunkHullIndexStop(otherChunkIndex); ++hullIndex1) + { + ConvexHullImpl::Separation separation; + if (ConvexHullImpl::hullsInProximity(chunkConvexHulls[hullIndex0], tm0, identityScale, chunkConvexHulls[hullIndex1], tm1, identityScale, 0.0f, &separation)) + { + if (PxMax(separation.min0 - separation.max1, separation.min1 - separation.max0) < -eps) + { + trimPlane.plane = separation.plane; + trimPlane.plane.d = -separation.min1; // Allow for other hull to intrude completely + trimPlane.plane.d = PxMin(trimPlane.plane.d, maxTrimFraction*(separation.max0-separation.min0) - separation.max0); // Bound clip distance + trimPlane.plane.d += trimPlane.plane.n.dot(tm0.p); // Transform back into part local space + trimPlanes.pushBack(trimPlane); + } + } + } + } + } + } + } + + // 4) Intersect the trimmed hull(s) from (2) and (3) with the trim planes. This may cause some hulls to disappear. + + // Sort by part, then by hull. We're going to get a little rough with these parts. + nvidia::sort<TrimPlane, TrimPlane::LessThan>(trimPlanes.begin(), trimPlanes.size(), TrimPlane::LessThan()); + + // Create a lookup into the array + physx::Array<uint32_t> trimPlaneLookup; + createIndexStartLookup(trimPlaneLookup, 0, renderMeshAsset->getPartCount(), trimPlanes.size() > 0 ? (int32_t*)&trimPlanes[0].partIndex : NULL, trimPlanes.size(), sizeof(TrimPlane)); + + // Trim + for (uint32_t partIndex = 0; partIndex < renderMeshAsset->getPartCount(); ++partIndex) + { + bool hullCountChanged = false; + for (uint32_t partTrimPlaneIndex = trimPlaneLookup[partIndex]; partTrimPlaneIndex < trimPlaneLookup[partIndex+1]; ++partTrimPlaneIndex) + { + TrimPlane& trimPlane = trimPlanes[partTrimPlaneIndex]; + ConvexHullImpl& hull = chunkConvexHulls[trimPlane.hullIndex]; + hull.intersectPlaneSide(trimPlane.plane); + if (hull.isEmpty()) + { + hullCountChanged = true; + } + } + if (hullCountChanged) + { + // Re-apply hulls that haven't disappeared + physx::Array<PartConvexHullProxy*> newHulls; + for (uint32_t hullIndex = mParams->chunkConvexHullStartIndices.buf[partIndex]; hullIndex < mParams->chunkConvexHullStartIndices.buf[partIndex+1]; ++hullIndex) + { + ConvexHullImpl& hull = chunkConvexHulls[hullIndex]; + if (!hull.isEmpty()) + { + PartConvexHullProxy* newHull = PX_NEW(PartConvexHullProxy); + newHulls.pushBack(newHull); + newHull->impl.init(hull.mParams); + } + } + DestructibleGeometryDesc geometryDesc; + CollisionVolumeDesc collisionVolumeDesc; + if (newHulls.size() > 0) + { + geometryDesc.convexHulls = (const nvidia::ExplicitHierarchicalMesh::ConvexHull**)newHulls.begin(); + geometryDesc.convexHullCount = newHulls.size(); + } + else + { + // We've lost all of the collision volume! Quite a shame... create a hull to replace it. + geometryDesc.collisionVolumeDesc = &collisionVolumeDesc; + collisionVolumeDesc.mHullMethod = ConvexHullMethod::WRAP_GRAPHICS_MESH; + } + rebuildCollisionGeometry(partIndex, geometryDesc); + for (uint32_t hullN = 0; hullN < newHulls.size(); ++hullN) + { + PX_DELETE(newHulls[hullN]); + } + } + } + + // 5) Recurse to children + + // Iterate through chunks and collect children + physx::Array<uint32_t> childChunkIndices; + for (uint32_t chunkNum = 0; chunkNum < chunkIndexCount; ++chunkNum) + { + const uint32_t chunkIndex = chunkIndices[chunkNum]; + const uint16_t firstChildIndex = mParams->chunks.buf[chunkIndex].firstChildIndex; + for (uint16_t childNum = 0; childNum < mParams->chunks.buf[chunkIndex].numChildren; ++childNum) + { + childChunkIndices.pushBack((uint32_t)(firstChildIndex + childNum)); + } + } + + // Recurse + if (childChunkIndices.size()) + { + trimCollisionGeometryInternal(childChunkIndices.begin(), childChunkIndices.size(), overlapsAtDepth, depth+1, maxTrimFraction); + } +} + +struct PartAndChunk +{ + uint32_t chunkIndex; + int32_t partIndex; + + struct LessThan + { + PX_INLINE bool operator()(const PartAndChunk& x, const PartAndChunk& y) const + { + return x.partIndex != y.partIndex ? (x.partIndex < y.partIndex) : (x.chunkIndex < y.chunkIndex); + } + }; +}; + +// Here's our chunk list element, with depth (for sorting) +struct ChunkAndDepth +{ + uint32_t chunkIndex; + int32_t depth; + + struct LessThan + { + PX_INLINE bool operator()(const ChunkAndDepth& x, const ChunkAndDepth& y) const + { + return x.depth != y.depth ? (x.depth < y.depth) : (x.chunkIndex < y.chunkIndex); + } + }; +}; + +void DestructibleAssetAuthoringImpl::trimCollisionGeometry(const uint32_t* partIndices, uint32_t partIndexCount, float maxTrimFraction) +{ + /* + 1) Create a list of chunks which reference each partIndex. (If there is instancing, there may be more than one chunk per part.) + 2) Sort by depth (stable sort) + 3) For each depth: + a) Collect a list of chunks at that depth, and call trimCollisionVolumesInternal. + */ + + // 1) Create a list of chunks which reference each partIndex. (If there is instancing, there may be more than one chunk per part.) + + // Fill array and sort + physx::Array<PartAndChunk> partAndChunkList; + partAndChunkList.resize(getChunkCount()); + for (uint32_t chunkIndex = 0; chunkIndex < getChunkCount(); ++chunkIndex) + { + partAndChunkList[chunkIndex].chunkIndex = chunkIndex; + partAndChunkList[chunkIndex].partIndex = (int32_t)getPartIndex(chunkIndex); + } + nvidia::sort<PartAndChunk, PartAndChunk::LessThan>(partAndChunkList.begin(), partAndChunkList.size(), PartAndChunk::LessThan()); + + // Create a lookup into the array + physx::Array<uint32_t> partAndChunkLookup; + createIndexStartLookup(partAndChunkLookup, 0, renderMeshAsset->getPartCount(), &partAndChunkList[0].partIndex, getChunkCount(), sizeof(PartAndChunk)); + + // 2) Sort by depth (stable sort) + + // Count how many chunks there will be + uint32_t chunkListSize = 0; + for (uint32_t partNum = 0; partNum < partIndexCount; ++partNum) + { + const uint32_t partIndex = partIndices[partNum]; + chunkListSize += partAndChunkLookup[partIndex+1] - partAndChunkLookup[partIndex]; + } + + // Fill and sort + physx::Array<ChunkAndDepth> chunkAndDepthList; + chunkAndDepthList.resize(chunkListSize); + uint32_t chunkNum = 0; + for (uint32_t partNum = 0; partNum < partIndexCount; ++partNum) + { + const uint32_t partIndex = partIndices[partNum]; + for (uint32_t partChunkNum = partAndChunkLookup[partIndex]; partChunkNum < partAndChunkLookup[partIndex+1]; ++partChunkNum, ++chunkNum) + { + const uint32_t chunkIndex = partAndChunkList[partChunkNum].chunkIndex; + chunkAndDepthList[chunkNum].chunkIndex = chunkIndex; + chunkAndDepthList[chunkNum].depth = mParams->chunks.buf[chunkIndex].depth; + } + } + nvidia::sort<ChunkAndDepth, ChunkAndDepth::LessThan>(chunkAndDepthList.begin(), chunkAndDepthList.size(), ChunkAndDepth::LessThan()); + + // And create a lookup into the array + physx::Array<uint32_t> chunkAndDepthLookup; + createIndexStartLookup(chunkAndDepthLookup, 0, mParams->depthCount, &chunkAndDepthList[0].depth, chunkListSize, sizeof(ChunkAndDepth)); + + // 3) For each depth: + for (uint32_t depth = 0; depth < mParams->depthCount; ++depth) + { + physx::Array<uint32_t> chunkIndexList; + chunkIndexList.resize(chunkAndDepthLookup[depth+1] - chunkAndDepthLookup[depth]); + if (chunkIndexList.size() == 0) + { + continue; + } + uint32_t chunkIndexListSize = 0; + for (uint32_t depthChunkNum = chunkAndDepthLookup[depth]; depthChunkNum < chunkAndDepthLookup[depth+1]; ++depthChunkNum) + { + chunkIndexList[chunkIndexListSize++] = chunkAndDepthList[depthChunkNum].chunkIndex; + } + PX_ASSERT(chunkIndexListSize == chunkIndexList.size()); + physx::Array<IntPair> overlaps; + if (depth > 0) + { + calculateChunkOverlaps(overlaps, depth-1); + } + trimCollisionGeometryInternal(chunkIndexList.begin(), chunkIndexList.size(), overlaps, depth, maxTrimFraction); + } +} + +void DestructibleAssetAuthoringImpl::setToolString(const char* toolString) +{ + if (mParams != NULL) + { + NvParameterized::Handle handle(*mParams, "comments"); + PX_ASSERT(handle.isValid()); + if (handle.isValid()) + { + PX_ASSERT(handle.parameterDefinition()->type() == NvParameterized::TYPE_STRING); + handle.setParamString(toolString); + } + } +} + +void DestructibleAssetAuthoringImpl::cookChunks(const DestructibleAssetCookingDesc& cookingDesc, bool cacheOverlaps, uint32_t* chunkIndexMapUser2Apex, uint32_t* chunkIndexMapApex2User, uint32_t chunkIndexMapCount) +{ + if (!cookingDesc.isValid()) + { + APEX_INVALID_PARAMETER("DestructibleAssetAuthoring::cookChunks: cookingDesc invalid."); + return; + } + + const uint32_t numChunks = cookingDesc.chunkDescCount; + const uint32_t numBehaviorGroups = cookingDesc.behaviorGroupDescCount; + const uint32_t numParts = renderMeshAsset->getPartCount(); + + if ((chunkIndexMapUser2Apex != NULL || chunkIndexMapApex2User != NULL) && chunkIndexMapCount < numChunks) + { + APEX_INVALID_PARAMETER("DestructibleAssetAuthoring::cookChunks: chunkIndexMap is not big enough."); + return; + } + + NvParameterized::Handle handle(*mParams); + + mParams->getParameterHandle("chunks", handle); + mParams->resizeArray(handle, (int32_t)numChunks); + mParams->depthCount = 0; + + // Create convex hulls + mParams->getParameterHandle("chunkConvexHulls", handle); + mParams->resizeArray(handle, 0); + chunkConvexHulls.reset(); + + mParams->getParameterHandle("chunkConvexHullStartIndices", handle); + mParams->resizeArray(handle, (int32_t)numParts + 1); + for (uint32_t partIndex = 0; partIndex <= numParts; ++partIndex) + { + mParams->chunkConvexHullStartIndices.buf[partIndex] = 0; // Initialize all to zero, so that the random-access rebuildCollisionGeometry does the right thing (below) + } + for (uint32_t partIndex = 0; partIndex < numParts; ++partIndex) + { + if (!rebuildCollisionGeometry(partIndex, cookingDesc.geometryDescs[partIndex])) + { + APEX_INVALID_PARAMETER("DestructibleAssetAuthoring::cookChunks: Could not find or generate collision hull for part."); + } + } + + // Sort - chunks must be in parent-sorted order + Array<ChunkSortElement> sortElements; + sortElements.resize(numChunks); + for (uint32_t i = 0; i < numChunks; ++i) + { + const DestructibleChunkDesc& chunkDesc = cookingDesc.chunkDescs[i]; + sortElements[i].index = (int32_t)i; + sortElements[i].parentIndex = chunkDesc.parentIndex; + sortElements[i].depth = 0; + int32_t parent = (int32_t)i; + uint32_t counter = 0; + while ((parent = cookingDesc.chunkDescs[parent].parentIndex) >= 0) + { + ++sortElements[i].depth; + if (++counter > numChunks) + { + APEX_INVALID_PARAMETER("DestructibleAssetAuthoring::cookChunks: loop found in cookingDesc parent indices. Cannot build an DestructibleAsset."); + return; + } + } + } + qsort(sortElements.begin(), numChunks, sizeof(ChunkSortElement), compareChunkParents); + + Array<uint32_t> ranks; + if (chunkIndexMapUser2Apex == NULL && numChunks > 0) + { + ranks.resize(numChunks); + chunkIndexMapUser2Apex = &ranks[0]; + } + + for (uint32_t i = 0; i < numChunks; ++i) + { + chunkIndexMapUser2Apex[sortElements[i].index] = i; + if (chunkIndexMapApex2User != NULL) + { + chunkIndexMapApex2User[i] = (uint32_t)sortElements[i].index; + } + } + + // Count instanced chunks and allocate instanced info array + uint32_t instancedChunkCount = 0; + for (uint32_t i = 0; i < numChunks; ++i) + { + const DestructibleChunkDesc& chunkDesc = cookingDesc.chunkDescs[sortElements[i].index]; + if (chunkDesc.useInstancedRendering) + { + ++instancedChunkCount; + } + } + + mParams->getParameterHandle("chunkInstanceInfo", handle); + mParams->resizeArray(handle, (int32_t)instancedChunkCount); + + mParams->getParameterHandle("scatterMeshIndices", handle); + mParams->resizeArray(handle, 0); + mParams->getParameterHandle("scatterMeshTransforms", handle); + mParams->resizeArray(handle, 0); + + const DestructibleChunkDesc defaultChunkDesc; + + instancedChunkCount = 0; // reset and use as cursor + + for (uint32_t i = 0; i < numChunks; ++i) + { + DestructibleAssetParametersNS::Chunk_Type& chunk = mParams->chunks.buf[i]; + const DestructibleChunkDesc& chunkDesc = cookingDesc.chunkDescs[sortElements[i].index]; + chunk.flags = 0; + if (chunkDesc.isSupportChunk) + { + chunk.flags |= SupportChunk; + } + if (chunkDesc.doNotFracture) + { + chunk.flags |= UnfracturableChunk; + } + if (chunkDesc.doNotDamage) + { + chunk.flags |= UndamageableChunk; + } + if (chunkDesc.doNotCrumble) + { + chunk.flags |= UncrumbleableChunk; + } +#if APEX_RUNTIME_FRACTURE + if (chunkDesc.runtimeFracture) + { + chunk.flags |= RuntimeFracturableChunk; + } +#endif + if (!chunkDesc.useInstancedRendering) + { + // Not instanced, meshPartIndex will be used to directly access the mesh part in the "normal" mesh + chunk.meshPartIndex = chunkDesc.meshIndex; + } + else + { + // Instanced, meshPartIndex will be used to access instance info + chunk.flags |= Instanced; + chunk.meshPartIndex = (uint16_t)instancedChunkCount++; + DestructibleAssetParametersNS::InstanceInfo_Type& instanceInfo = mParams->chunkInstanceInfo.buf[chunk.meshPartIndex]; + instanceInfo.partIndex = chunkDesc.meshIndex; + instanceInfo.chunkPositionOffset = chunkDesc.instancePositionOffset; + instanceInfo.chunkUVOffset = chunkDesc.instanceUVOffset; + } + if (sortElements[i].index == 0) + { + chunk.depth = 0; + chunk.parentIndex = DestructibleAssetImpl::InvalidChunkIndex; + } + else + { + chunk.parentIndex = (uint16_t)chunkIndexMapUser2Apex[(int16_t)chunkDesc.parentIndex]; + DestructibleAssetParametersNS::Chunk_Type& parent = mParams->chunks.buf[chunk.parentIndex]; + PX_ASSERT(chunk.parentIndex >= mParams->chunks.buf[i - 1].parentIndex || + mParams->chunks.buf[i - 1].parentIndex == DestructibleAssetImpl::InvalidChunkIndex); // Parent-sorted order + if (chunk.parentIndex != mParams->chunks.buf[i - 1].parentIndex) + { + parent.firstChildIndex = (uint16_t)i; + } + ++parent.numChildren; + chunk.depth = uint16_t(parent.depth + 1); + if ((parent.flags & SupportChunk) != 0) + { + chunk.flags |= SupportChunk; // All children of support chunks can be support chunks + } + if ((parent.flags & UnfracturableChunk) != 0) + { + chunk.flags |= UnfracturableChunk; // All children of unfracturable chunks are unfracturable + } +#if APEX_RUNTIME_FRACTURE + if ((parent.flags & RuntimeFracturableChunk) != 0) // Runtime fracturable chunks cannot have any children + { + PX_ALWAYS_ASSERT(); + } +#endif + } + if ((chunk.flags & UnfracturableChunk) != 0) + { + // All ancestors of unfracturable chunks must be unfracturable or note that they have an unfracturable descendant + uint16_t parentIndex = chunk.parentIndex; + while (parentIndex != DestructibleAssetImpl::InvalidChunkIndex) + { + DestructibleAssetParametersNS::Chunk_Type& parent = mParams->chunks.buf[parentIndex]; + if ((parent.flags & UnfracturableChunk) == 0) + { + parent.flags |= DescendantUnfractureable; + } + parentIndex = parent.parentIndex; + } + } + chunk.numChildren = 0; + chunk.firstChildIndex = DestructibleAssetImpl::InvalidChunkIndex; + mParams->depthCount = PxMax((uint16_t)mParams->depthCount, (uint16_t)(chunk.depth + 1)); + chunk.surfaceNormal = chunkDesc.surfaceNormal; + chunk.behaviorGroupIndex = chunkDesc.behaviorGroupIndex; + + // Default behavior is to take on the parent's behavior group + if (chunk.parentIndex != DestructibleAssetImpl::InvalidChunkIndex) + { + if (chunk.behaviorGroupIndex < 0) + { + chunk.behaviorGroupIndex = mParams->chunks.buf[chunk.parentIndex].behaviorGroupIndex; + } + } + + // Scatter mesh + const int32_t oldScatterMeshCount = mParams->scatterMeshIndices.arraySizes[0]; + chunk.firstScatterMesh = (uint16_t)oldScatterMeshCount; + chunk.scatterMeshCount = (uint16_t)chunkDesc.scatterMeshCount; + if (chunk.scatterMeshCount > 0) + { + mParams->getParameterHandle("scatterMeshIndices", handle); + mParams->resizeArray(handle, oldScatterMeshCount + (int32_t)chunk.scatterMeshCount); + handle.setParamU8Array(chunkDesc.scatterMeshIndices, (int32_t)chunk.scatterMeshCount, oldScatterMeshCount); + mParams->getParameterHandle("scatterMeshTransforms", handle); + mParams->resizeArray(handle, oldScatterMeshCount + (int32_t)chunk.scatterMeshCount); + for (uint16_t tmNum = 0; tmNum < chunk.scatterMeshCount; ++tmNum) + { + mParams->scatterMeshTransforms.buf[oldScatterMeshCount + tmNum] = chunkDesc.scatterMeshTransforms[tmNum]; + } + } + } + + mParams->getParameterHandle("behaviorGroups", handle); + mParams->resizeArray(handle, (int32_t)numBehaviorGroups); + + struct { + void operator() (const DestructibleBehaviorGroupDesc& behaviorGroupDesc, DestructibleAssetParameters* params, NvParameterized::Handle& elementHandle) + { + NvParameterized::Handle subElementHandle(*params); + + elementHandle.getChildHandle(params, "name", subElementHandle); + params->setParamString(subElementHandle, behaviorGroupDesc.name); + + elementHandle.getChildHandle(params, "damageThreshold", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.damageThreshold); + + elementHandle.getChildHandle(params, "damageToRadius", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.damageToRadius); + + elementHandle.getChildHandle(params, "damageSpread.minimumRadius", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.damageSpread.minimumRadius); + + elementHandle.getChildHandle(params, "damageSpread.radiusMultiplier", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.damageSpread.radiusMultiplier); + + elementHandle.getChildHandle(params, "damageSpread.falloffExponent", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.damageSpread.falloffExponent); + + elementHandle.getChildHandle(params, "damageColorSpread.minimumRadius", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.damageColorSpread.minimumRadius); + + elementHandle.getChildHandle(params, "damageColorSpread.radiusMultiplier", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.damageColorSpread.radiusMultiplier); + + elementHandle.getChildHandle(params, "damageColorSpread.falloffExponent", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.damageColorSpread.falloffExponent); + + elementHandle.getChildHandle(params, "damageColorChange", subElementHandle); + params->setParamVec4(subElementHandle, behaviorGroupDesc.damageColorChange); + + elementHandle.getChildHandle(params, "materialStrength", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.materialStrength); + + elementHandle.getChildHandle(params, "density", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.density); + + elementHandle.getChildHandle(params, "fadeOut", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.fadeOut); + + elementHandle.getChildHandle(params, "maxDepenetrationVelocity", subElementHandle); + params->setParamF32(subElementHandle, behaviorGroupDesc.maxDepenetrationVelocity); + + elementHandle.getChildHandle(params, "userData", subElementHandle); + params->setParamU64(subElementHandle, behaviorGroupDesc.userData); + } + } ConvertBehaviorGroupDesc; // local function definitions illegal, eh? + + const uint32_t bufferCount = 128; + char buffer[bufferCount] = {0}; + + for (uint32_t i = 0; i < numBehaviorGroups; ++i) + { + const DestructibleBehaviorGroupDesc& chunkDesc = cookingDesc.behaviorGroupDescs[i]; + NvParameterized::Handle elementHandle(*mParams); + + shdfnd::snprintf(buffer, bufferCount, "behaviorGroups[%d]", i); + mParams->getParameterHandle(buffer, elementHandle); + + ConvertBehaviorGroupDesc(chunkDesc, mParams, elementHandle); + } + + mParams->getParameterHandle("defaultBehaviorGroup", handle); + ConvertBehaviorGroupDesc(cookingDesc.defaultBehaviorGroupDesc, mParams, handle); + + mParams->RTFractureBehaviorGroup = cookingDesc.RTFractureBehaviorGroup; + + + // Fill in default destructible parameters up to depth + int oldDepthParametersSize = mParams->depthParameters.arraySizes[0]; + if (oldDepthParametersSize < (int)mParams->depthCount) + { + NvParameterized::Handle depthParametersHandle(*mParams); + mParams->getParameterHandle("depthParameters", depthParametersHandle); + mParams->resizeArray(depthParametersHandle, (int32_t)mParams->depthCount); + for (int i = oldDepthParametersSize; i < (int)mParams->depthCount; ++i) + { + DestructibleAssetParametersNS::DestructibleDepthParameters_Type& depthParameters = mParams->depthParameters.buf[i]; + depthParameters.OVERRIDE_IMPACT_DAMAGE = false; + depthParameters.OVERRIDE_IMPACT_DAMAGE_VALUE = false; + depthParameters.IGNORE_POSE_UPDATES = false; + depthParameters.IGNORE_RAYCAST_CALLBACKS = false; + depthParameters.IGNORE_CONTACT_CALLBACKS = false; + depthParameters.USER_FLAG_0 = false; + depthParameters.USER_FLAG_1 = false; + depthParameters.USER_FLAG_2 = false; + depthParameters.USER_FLAG_3 = false; + } + } + + // Build collision data and bounds + float skinWidth = 0.0025f; // Default value + if (GetApexSDK()->getCookingInterface()) + { + const PxCookingParams& cookingParams = GetApexSDK()->getCookingInterface()->getParams(); + skinWidth = cookingParams.skinWidth; + } + + mParams->bounds.setEmpty(); + for (uint32_t partIndex = 0; partIndex < numParts; ++partIndex) + { + const DestructibleGeometryDesc& geometryDesc = cookingDesc.geometryDescs[partIndex]; + const uint32_t startHullIndex = mParams->chunkConvexHullStartIndices.buf[partIndex]; + for (uint32_t hullIndex = 0; hullIndex < geometryDesc.convexHullCount; ++hullIndex) + { + ConvexHullImpl& chunkHullData = chunkConvexHulls[startHullIndex + hullIndex]; + PartConvexHullProxy* convexHullProxy = (PartConvexHullProxy*)geometryDesc.convexHulls[hullIndex]; + chunkHullData.mParams->copy(*convexHullProxy->impl.mParams); + if (chunkHullData.isEmpty()) + { + chunkHullData.buildFromAABB(renderMeshAsset->getBounds(partIndex)); // \todo: need better way of simplifying + } + } + } + + for (uint32_t chunkIndex = 0; chunkIndex < numChunks; ++chunkIndex) + { + DestructibleAssetParametersNS::Chunk_Type& chunk = mParams->chunks.buf[chunkIndex]; + PxBounds3 bounds = getChunkActorLocalBounds(chunkIndex); + mParams->bounds.include(bounds); + chunk.surfaceNormal = PxVec3(0.0f); + } + PX_ASSERT(!mParams->bounds.isEmpty()); + mParams->bounds.fattenFast(skinWidth); + + mParams->originalDepthCount = mParams->depthCount; + + calculateChunkDepthStarts(); + + if (cacheOverlaps) + { + cacheChunkOverlapsUpToDepth(chunkOverlapCacheDepth); + } + + Array<IntPair> supportGraphEdgesInternal(cookingDesc.supportGraphEdgeCount); + if (cookingDesc.supportGraphEdgeCount > 0) + { + for (uint32_t i = 0; i < cookingDesc.supportGraphEdgeCount; ++i) + { + supportGraphEdgesInternal[i].i0 = (int32_t)chunkIndexMapUser2Apex[(uint32_t)cookingDesc.supportGraphEdges[i].i0]; + supportGraphEdgesInternal[i].i1 = (int32_t)chunkIndexMapUser2Apex[(uint32_t)cookingDesc.supportGraphEdges[i].i1]; + } + + addChunkOverlaps(&supportGraphEdgesInternal[0], supportGraphEdgesInternal.size()); + } + + m_needsScatterMeshInstanceInfoCreation = true; +} + +void DestructibleAssetAuthoringImpl::serializeFractureToolState(PxFileBuf& stream, nvidia::ExplicitHierarchicalMesh::Embedding& embedding) const +{ + stream.storeDword((uint32_t)ApexStreamVersion::Current); + hMesh.serialize(stream, embedding); + hMeshCore.serialize(stream, embedding); + cutoutSet.serialize(stream); +} + +void DestructibleAssetAuthoringImpl::deserializeFractureToolState(PxFileBuf& stream, nvidia::ExplicitHierarchicalMesh::Embedding& embedding) +{ + const uint32_t version = stream.readDword(); + PX_UNUSED(version); // Initial version + + hMesh.deserialize(stream, embedding); + hMeshCore.deserialize(stream, embedding); + cutoutSet.deserialize(stream); +} +#endif + +NvParameterized::Interface* DestructibleAssetImpl::getDefaultActorDesc() +{ + NvParameterized::Interface* ret = 0; + + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + + // non-optimal. Should use a copy-constructor so this only gets built once. + if (!mApexDestructibleActorParams && traits) + { + mApexDestructibleActorParams = traits->createNvParameterized(DestructibleActorParam::staticClassName()); + } + + if (traits) + { + if (mApexDestructibleActorParams) + { + ret = mApexDestructibleActorParams; + DestructibleActorParam* p = static_cast<DestructibleActorParam*>(ret); + DestructibleActorParamNS::ParametersStruct* ps = static_cast<DestructibleActorParamNS::ParametersStruct*>(p); + + { + NvParameterized::Handle handle(*p); + if (p->getParameterHandle("crumbleEmitterName", handle) == NvParameterized::ERROR_NONE) + { + p->setParamString(handle, getCrumbleEmitterName()); + } + } + + { + NvParameterized::Handle handle(*p); + if (p->getParameterHandle("dustEmitterName", handle) == NvParameterized::ERROR_NONE) + { + p->setParamString(handle, getDustEmitterName()); + } + } + + DestructibleParameters destructibleParameters = getParameters(); + + ps->destructibleParameters.damageCap = destructibleParameters.damageCap; + ps->destructibleParameters.forceToDamage = destructibleParameters.forceToDamage; + ps->destructibleParameters.impactVelocityThreshold = destructibleParameters.impactVelocityThreshold; + ps->destructibleParameters.minimumFractureDepth = destructibleParameters.minimumFractureDepth; + ps->destructibleParameters.damageDepthLimit = destructibleParameters.damageDepthLimit; + ps->destructibleParameters.impactDamageDefaultDepth = destructibleParameters.impactDamageDefaultDepth; + ps->destructibleParameters.debrisDepth = destructibleParameters.debrisDepth; + ps->destructibleParameters.essentialDepth = destructibleParameters.essentialDepth; + ps->destructibleParameters.debrisLifetimeMin = destructibleParameters.debrisLifetimeMin; + ps->destructibleParameters.debrisLifetimeMax = destructibleParameters.debrisLifetimeMax; + ps->destructibleParameters.debrisMaxSeparationMin = destructibleParameters.debrisMaxSeparationMin; + ps->destructibleParameters.debrisMaxSeparationMax = destructibleParameters.debrisMaxSeparationMax; + ps->destructibleParameters.dynamicChunksGroupsMask.useGroupsMask = destructibleParameters.useDynamicChunksGroupsMask; + ps->destructibleParameters.debrisDestructionProbability = destructibleParameters.debrisDestructionProbability; + ps->destructibleParameters.dynamicChunkDominanceGroup = destructibleParameters.dynamicChunksDominanceGroup; + ps->destructibleParameters.dynamicChunksGroupsMask.bits0 = destructibleParameters.dynamicChunksFilterData.word0; + ps->destructibleParameters.dynamicChunksGroupsMask.bits1 = destructibleParameters.dynamicChunksFilterData.word1; + ps->destructibleParameters.dynamicChunksGroupsMask.bits2 = destructibleParameters.dynamicChunksFilterData.word2; + ps->destructibleParameters.dynamicChunksGroupsMask.bits3 = destructibleParameters.dynamicChunksFilterData.word3; + ps->destructibleParameters.supportStrength = destructibleParameters.supportStrength; + ps->destructibleParameters.legacyChunkBoundsTestSetting = destructibleParameters.legacyChunkBoundsTestSetting; + ps->destructibleParameters.legacyDamageRadiusSpreadSetting = destructibleParameters.legacyDamageRadiusSpreadSetting; + ps->destructibleParameters.validBounds = destructibleParameters.validBounds; + ps->destructibleParameters.maxChunkSpeed = destructibleParameters.maxChunkSpeed; + ps->destructibleParameters.flags.ACCUMULATE_DAMAGE = (destructibleParameters.flags & DestructibleParametersFlag::ACCUMULATE_DAMAGE) ? true : false; + ps->destructibleParameters.flags.DEBRIS_TIMEOUT = (destructibleParameters.flags & DestructibleParametersFlag::DEBRIS_TIMEOUT) ? true : false; + ps->destructibleParameters.flags.DEBRIS_MAX_SEPARATION = (destructibleParameters.flags & DestructibleParametersFlag::DEBRIS_MAX_SEPARATION) ? true : false; + ps->destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS = (destructibleParameters.flags & DestructibleParametersFlag::CRUMBLE_SMALLEST_CHUNKS) ? true : false; + ps->destructibleParameters.flags.ACCURATE_RAYCASTS = (destructibleParameters.flags & DestructibleParametersFlag::ACCURATE_RAYCASTS) ? true : false; + ps->destructibleParameters.flags.USE_VALID_BOUNDS = (destructibleParameters.flags & DestructibleParametersFlag::USE_VALID_BOUNDS) ? true : false; + ps->destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE = (destructibleParameters.flags & DestructibleParametersFlag::CRUMBLE_VIA_RUNTIME_FRACTURE) ? true : false; + + ps->supportDepth = mParams->supportDepth; + ps->formExtendedStructures = mParams->formExtendedStructures; + ps->useAssetDefinedSupport = mParams->useAssetDefinedSupport; + ps->useWorldSupport = mParams->useWorldSupport; + + // RT Fracture Parameters + ps->destructibleParameters.runtimeFracture.sheetFracture = destructibleParameters.rtFractureParameters.sheetFracture; + ps->destructibleParameters.runtimeFracture.depthLimit = destructibleParameters.rtFractureParameters.depthLimit; + ps->destructibleParameters.runtimeFracture.destroyIfAtDepthLimit = destructibleParameters.rtFractureParameters.destroyIfAtDepthLimit; + ps->destructibleParameters.runtimeFracture.minConvexSize = destructibleParameters.rtFractureParameters.minConvexSize; + ps->destructibleParameters.runtimeFracture.impulseScale = destructibleParameters.rtFractureParameters.impulseScale; + ps->destructibleParameters.runtimeFracture.glass.numSectors = destructibleParameters.rtFractureParameters.glass.numSectors; + ps->destructibleParameters.runtimeFracture.glass.sectorRand = destructibleParameters.rtFractureParameters.glass.sectorRand; + ps->destructibleParameters.runtimeFracture.glass.firstSegmentSize = destructibleParameters.rtFractureParameters.glass.firstSegmentSize; + ps->destructibleParameters.runtimeFracture.glass.segmentScale = destructibleParameters.rtFractureParameters.glass.segmentScale; + ps->destructibleParameters.runtimeFracture.glass.segmentRand = destructibleParameters.rtFractureParameters.glass.segmentRand; + ps->destructibleParameters.runtimeFracture.attachment.posX = destructibleParameters.rtFractureParameters.attachment.posX; + ps->destructibleParameters.runtimeFracture.attachment.negX = destructibleParameters.rtFractureParameters.attachment.negX; + ps->destructibleParameters.runtimeFracture.attachment.posY = destructibleParameters.rtFractureParameters.attachment.posY; + ps->destructibleParameters.runtimeFracture.attachment.negY = destructibleParameters.rtFractureParameters.attachment.negY; + ps->destructibleParameters.runtimeFracture.attachment.posZ = destructibleParameters.rtFractureParameters.attachment.posZ; + ps->destructibleParameters.runtimeFracture.attachment.negZ = destructibleParameters.rtFractureParameters.attachment.negZ; + + uint32_t depth = destructibleParameters.depthParametersCount; + if (depth > 0) + { + NvParameterized::Handle handle(*p); + if (p->getParameterHandle("depthParameters", handle) == NvParameterized::ERROR_NONE) + { + p->resizeArray(handle, (int32_t)depth); + for (uint32_t i = 0; i < depth; i++) + { + const DestructibleDepthParameters& dparm = destructibleParameters.depthParameters[i]; + ps->depthParameters.buf[i].OVERRIDE_IMPACT_DAMAGE = (dparm.flags & DestructibleDepthParametersFlag::OVERRIDE_IMPACT_DAMAGE) ? true : false; + ps->depthParameters.buf[i].OVERRIDE_IMPACT_DAMAGE_VALUE = (dparm.flags & DestructibleDepthParametersFlag::OVERRIDE_IMPACT_DAMAGE_VALUE) ? true : false; + ps->depthParameters.buf[i].IGNORE_POSE_UPDATES = (dparm.flags & DestructibleDepthParametersFlag::IGNORE_POSE_UPDATES) ? true : false; + ps->depthParameters.buf[i].IGNORE_RAYCAST_CALLBACKS = (dparm.flags & DestructibleDepthParametersFlag::IGNORE_RAYCAST_CALLBACKS) ? true : false; + ps->depthParameters.buf[i].IGNORE_CONTACT_CALLBACKS = (dparm.flags & DestructibleDepthParametersFlag::IGNORE_CONTACT_CALLBACKS) ? true : false; + ps->depthParameters.buf[i].USER_FLAG_0 = (dparm.flags & DestructibleDepthParametersFlag::USER_FLAG_0) ? true : false; + ps->depthParameters.buf[i].USER_FLAG_1 = (dparm.flags & DestructibleDepthParametersFlag::USER_FLAG_1) ? true : false; + ps->depthParameters.buf[i].USER_FLAG_2 = (dparm.flags & DestructibleDepthParametersFlag::USER_FLAG_2) ? true : false; + ps->depthParameters.buf[i].USER_FLAG_3 = (dparm.flags & DestructibleDepthParametersFlag::USER_FLAG_3) ? true : false; + } + } + } + + { + NvParameterized::Handle handle(*p); + if (p->getParameterHandle("behaviorGroups", handle) == NvParameterized::ERROR_NONE) + { + uint32_t behaviorGroupArraySize = (uint32_t)mParams->behaviorGroups.arraySizes[0]; + p->resizeArray(handle, (int32_t)behaviorGroupArraySize); + + struct { + void operator() (const DestructibleAssetParametersNS::BehaviorGroup_Type& src, + DestructibleActorParamNS::BehaviorGroup_Type& dest) + { + dest.damageThreshold = src.damageThreshold; + dest.damageToRadius = src.damageToRadius; + dest.damageSpread.minimumRadius = src.damageSpread.minimumRadius; + dest.damageSpread.radiusMultiplier = src.damageSpread.radiusMultiplier; + dest.damageSpread.falloffExponent = src.damageSpread.falloffExponent; + dest.materialStrength = src.materialStrength; + dest.density = src.density; + dest.fadeOut = src.fadeOut; + dest.maxDepenetrationVelocity = src.maxDepenetrationVelocity; + } + } ConvertBehaviorGroup; + + ConvertBehaviorGroup(mParams->defaultBehaviorGroup, ps->defaultBehaviorGroup); + for (uint32_t i = 0; i < behaviorGroupArraySize; i++) + { + ConvertBehaviorGroup(mParams->behaviorGroups.buf[i], + ps->behaviorGroups.buf[i]); + } + } + } + } + } + return ret; +} + +NvParameterized::Interface* DestructibleAssetImpl::getDefaultAssetPreviewDesc() +{ + NvParameterized::Interface* ret = NULL; + + if (module != NULL) + { + ret = module->getApexDestructiblePreviewParams(); + + if (ret != NULL) + { + ret->initDefaults(); + } + } + + return ret; +} + +bool DestructibleAssetImpl::isValidForActorCreation(const ::NvParameterized::Interface& params, Scene& /*apexScene*/) const +{ + return nvidia::strcmp(params.className(), DestructibleActorParam::staticClassName()) == 0 || + nvidia::strcmp(params.className(), DestructibleActorState::staticClassName()) == 0; +} + +Actor* DestructibleAssetImpl::createApexActor(const NvParameterized::Interface& params, Scene& apexScene) +{ + if (!isValidForActorCreation(params, apexScene)) + { + return NULL; + } + + return createDestructibleActor(params, apexScene); +} + +AssetPreview* DestructibleAssetImpl::createApexAssetPreview(const NvParameterized::Interface& params, AssetPreviewScene* /*previewScene*/) +{ + DestructiblePreviewProxy* proxy = NULL; + + proxy = PX_NEW(DestructiblePreviewProxy)(*this, m_previewList, ¶ms); + PX_ASSERT(proxy != NULL); + + return proxy; +} + +void DestructibleAssetImpl::appendActorTransforms(const PxMat44* transforms, uint32_t transformCount) + { + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("actorTransforms", handle); + const int32_t oldSize = mParams->actorTransforms.arraySizes[0]; + mParams->resizeArray(handle, (int32_t)(oldSize + transformCount)); + mParams->setParamMat44Array(handle, transforms, (int32_t)transformCount, oldSize); + } + +void DestructibleAssetImpl::clearActorTransforms() +{ + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("actorTransforms", handle); + mParams->resizeArray(handle, 0); +} + +bool DestructibleAssetImpl::chunksInProximity(const DestructibleAssetImpl& asset0, uint16_t chunkIndex0, const PxTransform& tm0, const PxVec3& scale0, + const DestructibleAssetImpl& asset1, uint16_t chunkIndex1, const PxTransform& tm1, const PxVec3& scale1, + float padding) +{ + PX_ASSERT(asset0.mParams != NULL); + PX_ASSERT(asset1.mParams != NULL); + + // Offset chunks (in case they are instanced) + PxTransform effectiveTM0(tm0); + effectiveTM0.p = tm0.p + tm0.rotate(scale0.multiply(asset0.getChunkPositionOffset(chunkIndex0))); + + PxTransform effectiveTM1(tm1); + effectiveTM1.p = tm1.p + tm1.rotate(scale1.multiply(asset1.getChunkPositionOffset(chunkIndex1))); + + for (uint32_t hullIndex0 = asset0.getChunkHullIndexStart(chunkIndex0); hullIndex0 < asset0.getChunkHullIndexStop(chunkIndex0); ++hullIndex0) + { + for (uint32_t hullIndex1 = asset1.getChunkHullIndexStart(chunkIndex1); hullIndex1 < asset1.getChunkHullIndexStop(chunkIndex1); ++hullIndex1) + { + if (ConvexHullImpl::hullsInProximity(asset0.chunkConvexHulls[hullIndex0], effectiveTM0, scale0, asset1.chunkConvexHulls[hullIndex1], effectiveTM1, scale1, padding)) + { + return true; + } + } + } + return false; +} + +bool DestructibleAssetImpl::chunkAndSphereInProximity(uint16_t chunkIndex, const PxTransform& chunkTM, const PxVec3& chunkScale, + const PxVec3& sphereWorldCenter, float sphereRadius, float padding, float* distance) +{ + // Offset chunk (in case it is instanced) + PxTransform effectiveTM = chunkTM; + effectiveTM.p = chunkTM.p + chunkTM.rotate(chunkScale.multiply(getChunkPositionOffset(chunkIndex))); + + ConvexHullImpl::Separation testSeparation; + ConvexHullImpl::Separation* testSeparationPtr = distance != NULL? &testSeparation : NULL; + bool result = false; + for (uint32_t hullIndex = getChunkHullIndexStart(chunkIndex); hullIndex < getChunkHullIndexStop(chunkIndex); ++hullIndex) + { + if (chunkConvexHulls[hullIndex].sphereInProximity(effectiveTM, chunkScale, sphereWorldCenter, sphereRadius, padding, testSeparationPtr)) + { + result = true; + if (distance != NULL) + { + const float testDistance = testSeparation.getDistance(); + if (testDistance < *distance) + { + *distance = testDistance; + } + } + } + } + return result; +} + + +/* + DestructibleAssetCollision +*/ + + +DestructibleAssetCollision::DestructibleAssetCollision() : + mAsset(NULL) +{ + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + mParams = DYNAMIC_CAST(DestructibleAssetCollisionDataSet*)(traits->createNvParameterized(DestructibleAssetCollisionDataSet::staticClassName())); + mOwnsParams = mParams != NULL; + PX_ASSERT(mOwnsParams); +} + +DestructibleAssetCollision::DestructibleAssetCollision(NvParameterized::Interface* params) : + mAsset(NULL) +{ + mParams = DYNAMIC_CAST(DestructibleAssetCollisionDataSet*)(params); + mOwnsParams = false; +} + +DestructibleAssetCollision::~DestructibleAssetCollision() +{ + resize(0); + + if (mParams != NULL && mOwnsParams) + { + mParams->destroy(); + } + mParams = NULL; + mOwnsParams = false; +} + +void DestructibleAssetCollision::setDestructibleAssetToCook(DestructibleAssetImpl* asset) +{ + if (asset == NULL || getAssetName() == NULL || nvidia::strcmp(asset->getName(), getAssetName())) + { + resize(0); + } + + mAsset = asset; + + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("assetName", handle); + mParams->setParamString(handle, mAsset != NULL ? mAsset->getName() : ""); +} + +void DestructibleAssetCollision::resize(uint32_t hullCount) +{ + for (uint32_t i = 0; i < mConvexMeshContainer.size(); ++i) + { + physx::Array< PxConvexMesh* >& convexMeshSet = mConvexMeshContainer[i]; + for (uint32_t j = hullCount; j < convexMeshSet.size(); ++j) + { + if (convexMeshSet[j] != NULL) + { + convexMeshSet[j]->release(); + } + } + mConvexMeshContainer[i].resize(hullCount); + } + + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + for (int i = 0; i < mParams->meshCookedCollisionStreamsAtScale.arraySizes[0]; ++i) + { + MeshCookedCollisionStreamsAtScale* streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(mParams->meshCookedCollisionStreamsAtScale.buf[i]); + if (streamsAtScale == NULL) + { + streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(traits->createNvParameterized(MeshCookedCollisionStreamsAtScale::staticClassName())); + mParams->meshCookedCollisionStreamsAtScale.buf[i] = streamsAtScale; + } + NvParameterized::Handle handle(*streamsAtScale); + streamsAtScale->getParameterHandle("meshCookedCollisionStreams", handle); + + // resizing PxParam ref arrays doesn't call destroy(), do this here + int32_t currentArraySize = 0; + streamsAtScale->getArraySize(handle, currentArraySize); + for (int j = currentArraySize - 1; j >= (int32_t)hullCount; j--) + { + NvParameterized::Interface*& hullStream = streamsAtScale->meshCookedCollisionStreams.buf[j]; + if (hullStream != NULL) + { + hullStream->destroy(); + } + hullStream = NULL; + } + streamsAtScale->resizeArray(handle, (int32_t)hullCount); + } +} + +bool DestructibleAssetCollision::addScale(const PxVec3& scale) +{ + if (getScaleIndex(scale, kDefaultDestructibleAssetCollisionScaleTolerance) >= 0) + { + return false; // Scale already exists + } + + int scaleIndex = mParams->scales.arraySizes[0]; + + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("scales", handle); + mParams->resizeArray(handle, scaleIndex + 1); + mParams->getParameterHandle("meshCookedCollisionStreamsAtScale", handle); + mParams->resizeArray(handle, scaleIndex + 1); + + mConvexMeshContainer.resize((uint32_t)scaleIndex + 1); + + mParams->scales.buf[(uint32_t)scaleIndex] = scale; + mParams->meshCookedCollisionStreamsAtScale.buf[(uint32_t)scaleIndex] = NULL; + mConvexMeshContainer[(uint32_t)scaleIndex].reset(); + + return true; +} + +bool DestructibleAssetCollision::cookAll() +{ + bool result = true; + for (int i = 0; i < mParams->scales.arraySizes[0]; ++i) + { + if (!cookScale(mParams->scales.buf[i])) + { + result = false; + } + } + + return result; +} + +bool DestructibleAssetCollision::cookScale(const PxVec3& scale) +{ + if (mAsset == NULL) + { + return false; + } + + const int32_t partCount = mAsset->mParams->chunkConvexHullStartIndices.arraySizes[0]; + if (partCount <= 0) + { + return false; + } + + const uint32_t hullCount = mAsset->mParams->chunkConvexHullStartIndices.buf[partCount-1]; + + bool result = true; + for (uint16_t i = 0; i < hullCount; ++i) + { + PxConvexMesh* convexMesh = getConvexMesh(i, scale); + if (convexMesh == NULL) + { + result = false; + } + } + + return result; +} + +PxConvexMesh* DestructibleAssetCollision::getConvexMesh(uint32_t hullIndex, const PxVec3& scale) +{ + int32_t scaleIndex = getScaleIndex(scale, kDefaultDestructibleAssetCollisionScaleTolerance); + + if (scaleIndex >= 0) + { + if (scaleIndex < (int32_t)mConvexMeshContainer.size()) + { + physx::Array<PxConvexMesh*>& convexMeshSet = mConvexMeshContainer[(uint32_t)scaleIndex]; + if (hullIndex < convexMeshSet.size()) + { + PxConvexMesh* convexMesh = convexMeshSet[hullIndex]; + if (convexMesh != NULL) + { + return convexMesh; + } + } + } + } + + NvParameterized::Handle handle(*mParams); + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + + MeshCookedCollisionStreamsAtScale* streamsAtScale; + if (scaleIndex < 0) + { + scaleIndex = mParams->scales.arraySizes[0]; + + mParams->getParameterHandle("scales", handle); + mParams->resizeArray(handle, scaleIndex + 1); + mParams->getParameterHandle("meshCookedCollisionStreamsAtScale", handle); + mParams->resizeArray(handle, scaleIndex + 1); + + mConvexMeshContainer.resize((uint32_t)scaleIndex + 1); + + mParams->scales.buf[(uint32_t)scaleIndex] = scale; + } + + if (mParams->meshCookedCollisionStreamsAtScale.buf[scaleIndex] != NULL) + { + streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(mParams->meshCookedCollisionStreamsAtScale.buf[scaleIndex]); + } + else + { + streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(traits->createNvParameterized(MeshCookedCollisionStreamsAtScale::staticClassName())); + mParams->meshCookedCollisionStreamsAtScale.buf[scaleIndex] = streamsAtScale; + } + + if (mAsset != NULL && (int)mAsset->chunkConvexHulls.size() != streamsAtScale->meshCookedCollisionStreams.arraySizes[0]) + { + NvParameterized::Handle streamsHandle(*streamsAtScale); + streamsAtScale->getParameterHandle("meshCookedCollisionStreams", streamsHandle); + streamsHandle.resizeArray((int32_t)mAsset->chunkConvexHulls.size()); + mConvexMeshContainer[(uint32_t)scaleIndex].resize(mAsset->chunkConvexHulls.size()); + } + + if ((int)hullIndex >= streamsAtScale->meshCookedCollisionStreams.arraySizes[0]) + { + return NULL; + } + + PxConvexMesh* convexMesh = NULL; + + MeshCookedCollisionStream* stream = DYNAMIC_CAST(MeshCookedCollisionStream*)(streamsAtScale->meshCookedCollisionStreams.buf[hullIndex]); + if (stream == NULL) + { + if (mAsset == NULL) + { + return NULL; + } + + stream = DYNAMIC_CAST(MeshCookedCollisionStream*)(traits->createNvParameterized(MeshCookedCollisionStream::staticClassName())); + streamsAtScale->meshCookedCollisionStreams.buf[hullIndex] = stream; + + PX_PROFILE_ZONE("DestructibleCookChunkCollisionMeshes", GetInternalApexSDK()->getContextId()); + + // Update the asset's stats with the number of cooked collision convex meshes + if (mAsset != NULL) + { + ++mAsset->mRuntimeCookedConvexCount; + } + + const ConvexHullImpl& hullData = mAsset->chunkConvexHulls[hullIndex]; + + if (hullData.getVertexCount() == 0) + { + return NULL; + } + + Array<PxVec3> scaledPoints; + scaledPoints.resize(hullData.getVertexCount()); + PxVec3 centroid(0.0f); + for (uint32_t i = 0; i < scaledPoints.size(); ++i) + { + scaledPoints[i] = hullData.getVertex(i); // Cook at unit scale first + centroid += scaledPoints[i]; + } + centroid *= 1.0f/(float)scaledPoints.size(); + for (uint32_t i = 0; i < scaledPoints.size(); ++i) + { + scaledPoints[i] -= centroid; + } + + nvidia::PsMemoryBuffer memStream; + memStream.setEndianMode(PxFileBuf::ENDIAN_NONE); + PxStreamFromFileBuf nvs(memStream); + physx::PxConvexMeshDesc meshDesc; + meshDesc.points.count = scaledPoints.size(); + meshDesc.points.data = scaledPoints.begin(); + meshDesc.points.stride = sizeof(PxVec3); + meshDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX; + const float skinWidth = GetApexSDK()->getCookingInterface() != NULL ? GetApexSDK()->getCookingInterface()->getParams().skinWidth : 0.0f; + if (skinWidth > 0.0f) + { + meshDesc.flags |= physx::PxConvexFlag::eINFLATE_CONVEX; + } + bool success = GetApexSDK()->getCookingInterface()->cookConvexMesh(meshDesc, nvs); + + // Now scale all the points, in case this array is used as-is (failure cases) + for (uint32_t i = 0; i < scaledPoints.size(); ++i) + { + scaledPoints[i] += centroid; + scaledPoints[i] = scaledPoints[i].multiply(scale); + } + + if (success) + { + PxStreamFromFileBuf nvs(memStream); + convexMesh = GetApexSDK()->getPhysXSDK()->createConvexMesh(nvs); + + // Examine the mass properties to make sure they're reasonable. + if (convexMesh != NULL) + { + float mass; + PxMat33 localInertia; + PxVec3 localCenterOfMass; + convexMesh->getMassInformation(mass, localInertia, localCenterOfMass); + PxMat33 massFrame; + const PxVec3 massLocalInertia = diagonalizeSymmetric(massFrame, localInertia); + success = (mass > 0 && massLocalInertia.x > 0 && massLocalInertia.y > 0 && massLocalInertia.z > 0); + if (success && massLocalInertia.maxElement() > 4000*massLocalInertia.minElement()) + { + convexMesh->release(); + convexMesh = NULL; + success = false; + } + } + else + { + success = false; + } + + if (success) + { + // Now scale the convex hull + memStream.reset(); + memStream.setEndianMode(PxFileBuf::ENDIAN_NONE); + PxStreamFromFileBuf nvs(memStream); + + const uint32_t numVerts = convexMesh->getNbVertices(); + const PxVec3* verts = convexMesh->getVertices(); + + scaledPoints.resize(numVerts); + for (uint32_t i = 0; i < numVerts; ++i) + { + scaledPoints[i] = (verts[i] + centroid).multiply(scale); + } + + // Unfortunately, we must build our own triangle buffer from the polygon buffer + uint32_t triangleCount = 0; + for (uint32_t i = 0; i < convexMesh->getNbPolygons(); ++i) + { + physx::PxHullPolygon polygon; + convexMesh->getPolygonData(i, polygon); + triangleCount += polygon.mNbVerts - 2; + } + const uint8_t* indexBuffer = (const uint8_t*)convexMesh->getIndexBuffer(); + Array<uint32_t> indices; + indices.reserve(triangleCount*3); + for (uint32_t i = 0; i < convexMesh->getNbPolygons(); ++i) + { + physx::PxHullPolygon polygon; + convexMesh->getPolygonData(i, polygon); + for (uint16_t j = 1; j < polygon.mNbVerts-1; ++j) + { + indices.pushBack((uint32_t)indexBuffer[polygon.mIndexBase]); + indices.pushBack((uint32_t)indexBuffer[polygon.mIndexBase+j]); + indices.pushBack((uint32_t)indexBuffer[polygon.mIndexBase+j+1]); + } + } + + physx::PxConvexMeshDesc meshDesc; + meshDesc.points.count = scaledPoints.size(); + meshDesc.points.data = scaledPoints.begin(); + meshDesc.points.stride = sizeof(PxVec3); + meshDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX; + success = GetApexSDK()->getCookingInterface()->cookConvexMesh(meshDesc, nvs); + + convexMesh->release(); + convexMesh = NULL; + + if (success) + { + convexMesh = GetApexSDK()->getPhysXSDK()->createConvexMesh(nvs); + } + + if (convexMesh == NULL) + { + success = false; + } + } + } + + if (!success) + { + convexMesh = NULL; + memStream.reset(); + memStream.setEndianMode(PxFileBuf::ENDIAN_NONE); + PxStreamFromFileBuf nvs(memStream); + // Just form bbox + PxBounds3 bounds; + bounds.setEmpty(); + for (uint32_t i = 0; i < scaledPoints.size(); ++i) + { + bounds.include(scaledPoints[i]); + } + PX_ASSERT(!bounds.isEmpty()); + bounds.fattenFast(PxMax(0.00001f, bounds.getExtents().magnitude()*0.001f)); + scaledPoints.resize(8); + for (uint32_t i = 0; i < 8; ++i) + { + scaledPoints[i] = PxVec3((i & 1) ? bounds.maximum.x : bounds.minimum.x, + (i & 2) ? bounds.maximum.y : bounds.minimum.y, + (i & 4) ? bounds.maximum.z : bounds.minimum.z); + } + meshDesc.points.data = scaledPoints.begin(); + meshDesc.points.count = 8; + if (!GetApexSDK()->getCookingInterface()->cookConvexMesh(meshDesc, nvs)) + { + memStream.reset(); + } + } + + { + NvParameterized::Handle bytesHandle(stream); + stream->getParameterHandle("bytes", bytesHandle); + stream->resizeArray(bytesHandle, (int32_t)memStream.getWriteBufferSize()); + stream->setParamU8Array(bytesHandle, memStream.getWriteBuffer(), (int32_t)memStream.getWriteBufferSize()); + } + } + + if (convexMesh == NULL) + { + nvidia::PsMemoryBuffer memStream(stream->bytes.buf, (uint32_t)stream->bytes.arraySizes[0]); + memStream.setEndianMode(PxFileBuf::ENDIAN_NONE); + PxStreamFromFileBuf nvs(memStream); + convexMesh = GetApexSDK()->getPhysXSDK()->createConvexMesh(nvs); + } + + // These resizes should not be required, fix it and remove them + if (mConvexMeshContainer.size() <= (uint32_t)scaleIndex) + { + APEX_DEBUG_WARNING("The asset's (%s) convex mesh container needed resizing, debug this", mAsset->getName()); + mConvexMeshContainer.resize((uint32_t)scaleIndex+1); + } + if (mConvexMeshContainer[(uint32_t)scaleIndex].size() <= (uint32_t)hullIndex) + { + APEX_DEBUG_WARNING("The asset's (%s) convex mesh container at scale index %d needed resizing, debug this", mAsset->getName(), scaleIndex); + mConvexMeshContainer[(uint32_t)scaleIndex].resize(hullIndex+1); + } + + mConvexMeshContainer[(uint32_t)scaleIndex][hullIndex] = convexMesh; + + return convexMesh; +} + +MeshCookedCollisionStreamsAtScale* DestructibleAssetCollision::getCollisionAtScale(const PxVec3& scale) +{ + cookScale(scale); + + const int32_t scaleIndex = getScaleIndex(scale, kDefaultDestructibleAssetCollisionScaleTolerance); + if (scaleIndex < 0) + { + return NULL; + } + + return DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(mParams->meshCookedCollisionStreamsAtScale.buf[scaleIndex]); +} + +physx::Array<PxConvexMesh*>* DestructibleAssetCollision::getConvexMeshesAtScale(const PxVec3& scale) +{ + cookScale(scale); + + const int32_t scaleIndex = getScaleIndex(scale, kDefaultDestructibleAssetCollisionScaleTolerance); + if (scaleIndex < 0) + { + return NULL; + } + + return &mConvexMeshContainer[(uint32_t)scaleIndex]; +} + +PxFileBuf& DestructibleAssetCollision::deserialize(PxFileBuf& stream, const char* assetName) +{ + // If there are any referenced meshes in ANY scales we're going to revoke this operation as not supported + for (uint32_t i=0; i<mConvexMeshContainer.size(); i++) + { + if (mConvexMeshContainer.getReferenceCount(i) > 0) + { + APEX_DEBUG_INFO("Cannot deserialize the cooked collision data cache for asset <%s> scaleIdx <%d> because it is in use by actors", getAssetName(), i); + return stream; + } + } + + mAsset = NULL; + mConvexMeshContainer.reset(); + + /*uint32_t version =*/ + stream.readDword(); // Eat version #, not used since this is the initial version + + ApexSimpleString name; + name.deserialize(stream); + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("assetName", handle); + mParams->setParamString(handle, name.c_str()); + + if (assetName != NULL) + mParams->setParamString(handle, assetName); + + stream >> mParams->cookingPlatform; + stream >> mParams->cookingVersionNum; + + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + + int scaleCount = (int)stream.readDword(); + mParams->getParameterHandle("scales", handle); + mParams->resizeArray(handle, scaleCount); + for (int i = 0; i < scaleCount; ++i) + { + stream >> mParams->scales.buf[i]; + } + + int meshScaleCount = (int)stream.readDword(); + mParams->getParameterHandle("meshCookedCollisionStreamsAtScale", handle); + mParams->resizeArray(handle, meshScaleCount); + mConvexMeshContainer.resize((uint32_t)meshScaleCount); + for (uint32_t i = 0; i < (uint32_t)meshScaleCount; ++i) + { + MeshCookedCollisionStreamsAtScale* streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(mParams->meshCookedCollisionStreamsAtScale.buf[i]); + if (streamsAtScale == NULL) + { + streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(traits->createNvParameterized(MeshCookedCollisionStreamsAtScale::staticClassName())); + mParams->meshCookedCollisionStreamsAtScale.buf[i] = streamsAtScale; + } + + handle.setInterface(streamsAtScale); + physx::Array<PxConvexMesh*>& meshSet = mConvexMeshContainer[i]; + + uint32_t meshCount = stream.readDword(); + streamsAtScale->getParameterHandle("meshCookedCollisionStreams", handle); + streamsAtScale->resizeArray(handle, (int32_t)meshCount); + meshSet.resize(meshCount); + for (uint32_t j = 0; j < meshCount; ++j) + { + MeshCookedCollisionStream* collisionStream = DYNAMIC_CAST(MeshCookedCollisionStream*)(streamsAtScale->meshCookedCollisionStreams.buf[j]); + if (collisionStream == NULL) + { + collisionStream = DYNAMIC_CAST(MeshCookedCollisionStream*)(traits->createNvParameterized(MeshCookedCollisionStream::staticClassName())); + streamsAtScale->meshCookedCollisionStreams.buf[j] = collisionStream; + } + + handle.setInterface(collisionStream); + + int bufferSize = (int)stream.readDword(); + collisionStream->getParameterHandle("bytes", handle); + collisionStream->resizeArray(handle, bufferSize); + stream.read(collisionStream->bytes.buf, (uint32_t)bufferSize); + + nvidia::PsMemoryBuffer memStream(collisionStream->bytes.buf, (uint32_t)collisionStream->bytes.arraySizes[0]); + memStream.setEndianMode(PxFileBuf::ENDIAN_NONE); + PxStreamFromFileBuf nvs(memStream); + meshSet[j] = GetApexSDK()->getPhysXSDK()->createConvexMesh(nvs); + } + } + return stream; +} + +PxFileBuf& DestructibleAssetCollision::serialize(PxFileBuf& stream) const +{ +#ifndef WITHOUT_APEX_AUTHORING + stream << (uint32_t)Version::Current; + + ApexSimpleString name(mParams->assetName); + name.serialize(stream); + + stream << mParams->cookingPlatform; + stream << mParams->cookingVersionNum; + + stream.storeDword((uint32_t)mParams->scales.arraySizes[0]); + for (uint32_t i = 0; i < (uint32_t)mParams->scales.arraySizes[0]; ++i) + { + stream << mParams->scales.buf[i]; + } + + stream.storeDword((uint32_t)mParams->meshCookedCollisionStreamsAtScale.arraySizes[0]); + for (uint32_t i = 0; i < (uint32_t)mParams->meshCookedCollisionStreamsAtScale.arraySizes[0]; ++i) + { + MeshCookedCollisionStreamsAtScale* streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(mParams->meshCookedCollisionStreamsAtScale.buf[i]); + if (streamsAtScale == NULL) + { + stream.storeDword(0); + } + else + { + stream.storeDword((uint32_t)streamsAtScale->meshCookedCollisionStreams.arraySizes[0]); + for (uint32_t j = 0; j < (uint32_t)streamsAtScale->meshCookedCollisionStreams.arraySizes[0]; ++j) + { + MeshCookedCollisionStream* collisionStream = DYNAMIC_CAST(MeshCookedCollisionStream*)(streamsAtScale->meshCookedCollisionStreams.buf[j]); + if (collisionStream == NULL) + { + stream.storeDword(0); + } + else + { + stream.storeDword((uint32_t)collisionStream->bytes.arraySizes[0]); + stream.write(collisionStream->bytes.buf, (uint32_t)collisionStream->bytes.arraySizes[0]); + } + } + } + } +#endif // #ifndef WITHOUT_APEX_AUTHORING + return stream; +} + +bool DestructibleAssetCollision::platformAndVersionMatch() const +{ + const PxCookingParams& cookingParams = GetInternalApexSDK()->getCookingInterface()->getParams(); + const uint32_t presentCookingVersionNum = GetInternalApexSDK()->getCookingVersion(); + + return ((uint32_t) cookingParams.targetPlatform == mParams->cookingPlatform) && + ((presentCookingVersionNum & 0xFFFF0000) == (mParams->cookingVersionNum & 0xFFFF0000)); +} + +void DestructibleAssetCollision::setPlatformAndVersion() +{ + mParams->cookingPlatform = GetInternalApexSDK()->getCookingInterface()->getParams().targetPlatform; + mParams->cookingVersionNum = GetInternalApexSDK()->getCookingVersion(); +} + +uint32_t DestructibleAssetCollision::memorySize() const +{ + uint32_t size = 0; + + for (int i = 0; i < mParams->meshCookedCollisionStreamsAtScale.arraySizes[0]; ++i) + { + MeshCookedCollisionStreamsAtScale* streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(mParams->meshCookedCollisionStreamsAtScale.buf[i]); + if (streamsAtScale == NULL) + { + continue; + } + for (int j = 0; j < streamsAtScale->meshCookedCollisionStreams.arraySizes[0]; ++j) + { + MeshCookedCollisionStream* stream = DYNAMIC_CAST(MeshCookedCollisionStream*)(streamsAtScale->meshCookedCollisionStreams.buf[j]); + if (stream == NULL) + { + continue; + } + size += (uint32_t)stream->bytes.arraySizes[0]; + } + } + + return size; +} + +void DestructibleAssetCollision::clearUnreferencedSets() +{ + for (uint32_t i = 0; i < mConvexMeshContainer.size(); ++i) + { + if (mConvexMeshContainer.getReferenceCount(i) == 0) + { + MeshCookedCollisionStreamsAtScale* streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(mParams->meshCookedCollisionStreamsAtScale.buf[i]); + if (streamsAtScale) + { + NvParameterized::Handle handle(*streamsAtScale); + streamsAtScale->getParameterHandle("meshCookedCollisionStreams", handle); + streamsAtScale->resizeArray(handle, 0); + } + + // We need to NULL this pointer, otherwise we'll be accessing old data as a result of the reset below + DestructibleAssetImpl* asset = mAsset; + if (asset) + { + asset->mCollisionMeshes = NULL; + } + } + } + mConvexMeshContainer.reset(false); +} + +// Spit out warnings to the error stream for any referenced sets +void DestructibleAssetCollision::reportReferencedSets() +{ + for (uint32_t i = 0; i < mConvexMeshContainer.size(); ++i) + { + if (mConvexMeshContainer.getReferenceCount(i)) + { + APEX_DEBUG_WARNING("Clearing a referenced convex mesh container for asset: %s", mAsset); + } + } +} + +bool DestructibleAssetCollision::incReferenceCount(int scaleIndex) +{ + if (scaleIndex < 0 || scaleIndex >= (int)mConvexMeshContainer.size()) + { + return false; + } + + mConvexMeshContainer.incReferenceCount((uint32_t)scaleIndex); + + return true; +} + +bool DestructibleAssetCollision::decReferenceCount(int scaleIndex) +{ + if (scaleIndex < 0 || scaleIndex >= (int)mConvexMeshContainer.size()) + { + return false; + } + + return mConvexMeshContainer.decReferenceCount((uint32_t)scaleIndex); +} + +// The source 'collisionSet' is not const because it's list of PxConvexMesh pointers +// in 'mConvexMeshContainer' needs to be cleared so they aren't released in +// DestructibleAssetCollision::resize(0) +void DestructibleAssetCollision::merge(DestructibleAssetCollision& collisionSet) +{ + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + + // Prepare the convexMesh container for the collisionSet's meshes + if (mConvexMeshContainer.size() < collisionSet.mConvexMeshContainer.size()) + { + mConvexMeshContainer.resize(collisionSet.mConvexMeshContainer.size()); + } + + // Loop through scales contained in collisionSet + for (uint32_t i = 0; i < (uint32_t)collisionSet.mParams->scales.arraySizes[0]; ++i) + { + const PxVec3& scale = collisionSet.mParams->scales.buf[i]; + int scaleIndex = getScaleIndex(scale, kDefaultDestructibleAssetCollisionScaleTolerance); + if (scaleIndex < 0) + { + // Scale not found, add it to this set + addScale(scale); + scaleIndex = getScaleIndex(scale, kDefaultDestructibleAssetCollisionScaleTolerance); + if (scaleIndex < 0) + { + continue; // Failed to add scale + } + if (mParams->meshCookedCollisionStreamsAtScale.buf[scaleIndex] == NULL) // Create streams if we need them + { + mParams->meshCookedCollisionStreamsAtScale.buf[scaleIndex] = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(traits->createNvParameterized(MeshCookedCollisionStreamsAtScale::staticClassName())); + } + mParams->meshCookedCollisionStreamsAtScale.buf[scaleIndex]->copy(*collisionSet.mParams->meshCookedCollisionStreamsAtScale.buf[i]); + } + else + { + MeshCookedCollisionStreamsAtScale* streamsAtScale = DYNAMIC_CAST(MeshCookedCollisionStreamsAtScale*)(mParams->meshCookedCollisionStreamsAtScale.buf[scaleIndex]); + PX_ASSERT(streamsAtScale != NULL); + if (streamsAtScale->meshCookedCollisionStreams.arraySizes[0] == 0) // Only merge if this scale is empty; we won't stomp any existing data + { + mParams->meshCookedCollisionStreamsAtScale.buf[scaleIndex]->copy(*collisionSet.mParams->meshCookedCollisionStreamsAtScale.buf[i]); + } + + // also copy the PxConvexMesh pointers (because the source collisionSet has them already at this point) + physx::Array<PxConvexMesh*>& srcConvexMeshSet = collisionSet.mConvexMeshContainer[i]; + + // make sure the destination list is present + bool convexMeshSetResized = false; + if (mConvexMeshContainer[i].size() < srcConvexMeshSet.size()) + { + convexMeshSetResized = true; + mConvexMeshContainer[i].resize(srcConvexMeshSet.size()); + } + + for (uint32_t j=0; j<srcConvexMeshSet.size(); j++) + { + // Only merge if we need PxConvexMesh pointers, otherwise just release these + // newly created PxConvexMesh after exiting this method + if(mConvexMeshContainer[i][j] == NULL || convexMeshSetResized) + { + mConvexMeshContainer[i][j] = srcConvexMeshSet[j]; + // This prevents DestructibleAssetCollision::resize() from releasing the convex mesh + srcConvexMeshSet[j] = NULL; + } + } + } + } +} + +int32_t DestructibleAssetCollision::getScaleIndex(const PxVec3& scale, float tolerance) const +{ + for (int i = 0; i < mParams->scales.arraySizes[0]; ++i) + { + const PxVec3& error = scale - mParams->scales.buf[i]; + if (PxAbs(error.x) <= tolerance && PxAbs(error.y) <= tolerance && PxAbs(error.z) <= tolerance) + { + return i; + } + } + + return -1; +} + +/** DestructibleAsset::ScatterMeshInstanceInfo **/ + +DestructibleAssetImpl::ScatterMeshInstanceInfo::~ScatterMeshInstanceInfo() +{ + if (m_actor != NULL) + { + m_actor->release(); + m_actor = NULL; + } + + if (m_instanceBuffer != NULL) + { + UserRenderResourceManager* rrm = GetInternalApexSDK()->getUserRenderResourceManager(); + rrm->releaseInstanceBuffer(*m_instanceBuffer); + m_instanceBuffer = NULL; + } +} + +} +} // end namespace nvidia + + diff --git a/APEX_1.4/module/destructible/src/DestructiblePreviewImpl.cpp b/APEX_1.4/module/destructible/src/DestructiblePreviewImpl.cpp new file mode 100644 index 00000000..4b633c91 --- /dev/null +++ b/APEX_1.4/module/destructible/src/DestructiblePreviewImpl.cpp @@ -0,0 +1,394 @@ +/* + * 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. + */ + + +#include "ApexDefs.h" +#include "Apex.h" +#include "ModuleDestructibleImpl.h" +#include "DestructiblePreviewImpl.h" +#include "DestructibleAssetImpl.h" +#include "DestructiblePreviewParam.h" +#include "RenderMeshAssetIntl.h" + +namespace nvidia +{ +namespace destructible +{ + +DestructiblePreviewImpl::DestructiblePreviewImpl(DestructiblePreview* _api, DestructibleAssetImpl& _asset, const NvParameterized::Interface* params) : + ApexPreview(), + m_asset(&_asset), + m_api(_api), + m_instancedChunkCount(0) +{ + for (int meshN = 0; meshN < DestructibleActorMeshType::Count; ++meshN) + { + m_renderMeshActors[meshN] = NULL; + } + + const DestructiblePreviewParam* destructiblePreviewParams = DYNAMIC_CAST(const DestructiblePreviewParam*)(params); + + PX_ALLOCA(skinnedMaterialNames, const char*, destructiblePreviewParams->overrideSkinnedMaterialNames.arraySizes[0] > 0 ? destructiblePreviewParams->overrideSkinnedMaterialNames.arraySizes[0] : 1); + for (int i = 0; i < destructiblePreviewParams->overrideSkinnedMaterialNames.arraySizes[0]; ++i) + { + skinnedMaterialNames[i] = destructiblePreviewParams->overrideSkinnedMaterialNames.buf[i].buf; + } + + PX_ASSERT(m_asset->getRenderMeshAsset()); + RenderMeshActorDesc renderableMeshDesc; + renderableMeshDesc.visible = false; + renderableMeshDesc.indexBufferHint = RenderBufferHint::DYNAMIC; + renderableMeshDesc.keepVisibleBonesPacked = true; + renderableMeshDesc.overrideMaterials = destructiblePreviewParams->overrideSkinnedMaterialNames.arraySizes[0] > 0 ? (const char**)skinnedMaterialNames : NULL; + renderableMeshDesc.overrideMaterialCount = (uint32_t)destructiblePreviewParams->overrideSkinnedMaterialNames.arraySizes[0]; + m_renderMeshActors[DestructibleActorMeshType::Skinned] = m_asset->getRenderMeshAsset()->createActor(renderableMeshDesc); + const uint32_t numParts = m_asset->getRenderMeshAsset()->getPartCount(); + for (uint32_t i = 0; i < numParts; ++i) + { + m_renderMeshActors[DestructibleActorMeshType::Skinned]->setVisibility(false, (uint16_t)i); + } + m_renderMeshActors[DestructibleActorMeshType::Skinned]->updateBounds(); + + m_drawUnexpandedChunksStatically = destructiblePreviewParams->renderUnexplodedChunksStatically; + + if (m_drawUnexpandedChunksStatically) + { + PX_ALLOCA(staticMaterialNames, const char*, destructiblePreviewParams->overrideStaticMaterialNames.arraySizes[0] > 0 ? destructiblePreviewParams->overrideStaticMaterialNames.arraySizes[0] : 1); + for (int i = 0; i < destructiblePreviewParams->overrideStaticMaterialNames.arraySizes[0]; ++i) + { + staticMaterialNames[i] = destructiblePreviewParams->overrideStaticMaterialNames.buf[i].buf; + } + + // Create static render mesh + renderableMeshDesc.renderWithoutSkinning = true; + renderableMeshDesc.overrideMaterials = destructiblePreviewParams->overrideStaticMaterialNames.arraySizes[0] > 0 ? (const char**)staticMaterialNames : NULL; + renderableMeshDesc.overrideMaterialCount = (uint32_t)destructiblePreviewParams->overrideStaticMaterialNames.arraySizes[0]; + m_renderMeshActors[DestructibleActorMeshType::Static] = m_asset->getRenderMeshAsset()->createActor(renderableMeshDesc); + for (uint32_t i = 0; i < numParts; ++i) + { + m_renderMeshActors[DestructibleActorMeshType::Static]->setVisibility(false, (uint16_t)i); + } + m_renderMeshActors[DestructibleActorMeshType::Static]->updateBounds(); + } + + // Instanced actors + physx::Array<uint16_t> tempPartToActorMap; + tempPartToActorMap.resize((uint32_t)m_asset->mParams->chunks.arraySizes[0], 0xFFFF); + + m_instancedChunkActorMap.resize((uint32_t)m_asset->mParams->chunkInstanceInfo.arraySizes[0]); + for (int32_t i = 0; i < m_asset->mParams->chunkInstanceInfo.arraySizes[0]; ++i) + { + uint16_t partIndex = m_asset->mParams->chunkInstanceInfo.buf[i].partIndex; + if (tempPartToActorMap[partIndex] == 0xFFFF) + { + tempPartToActorMap[partIndex] = m_instancedChunkCount++; + } + m_instancedChunkActorMap[(uint32_t)i] = tempPartToActorMap[partIndex]; + } + + m_instancedActorVisiblePart.resize(m_instancedChunkCount); + for (int32_t i = 0; i < m_asset->mParams->chunks.arraySizes[0]; ++i) + { + DestructibleAssetParametersNS::Chunk_Type& chunk = m_asset->mParams->chunks.buf[i]; + if ((chunk.flags & DestructibleAssetImpl::Instanced) != 0) + { + uint16_t partIndex = m_asset->mParams->chunkInstanceInfo.buf[chunk.meshPartIndex].partIndex; + m_instancedActorVisiblePart[m_instancedChunkActorMap[chunk.meshPartIndex]] = partIndex; + } + } + + setChunkVisibility(0, true); + + m_chunkDepth = destructiblePreviewParams->chunkDepth; + m_explodeAmount = destructiblePreviewParams->explodeAmount; + setPose(destructiblePreviewParams->globalPose); + m_userData = reinterpret_cast<void*>(destructiblePreviewParams->userData); +} + +DestructiblePreviewImpl::~DestructiblePreviewImpl() +{ +} + +// called at the end of 'setPose' which allows for any module specific updates. +void DestructiblePreviewImpl::setPose(const PxMat44& pose) +{ + ApexPreview::setPose(pose); + setExplodeView(m_chunkDepth, m_explodeAmount); +} + +void DestructiblePreviewImpl::setExplodeView(uint32_t depth, float explode) +{ + m_chunkDepth = PxClamp(depth, (uint32_t)0, m_asset->getDepthCount() - 1); + const float newExplodeAmount = PxMax(explode, 0.0f); + + if (m_drawUnexpandedChunksStatically) + { + // Using a static mesh for unexploded chunks + if (m_explodeAmount == 0.0f && newExplodeAmount != 0.0f) + { + // Going from unexploded to exploded. Need to make the static mesh invisible. + if (m_renderMeshActors[DestructibleActorMeshType::Static] != NULL) + { + for (uint32_t i = 0; i < m_asset->getChunkCount(); ++i) + { + m_renderMeshActors[DestructibleActorMeshType::Static]->setVisibility(false, (uint16_t)i); + } + } + } + else if (m_explodeAmount != 0.0f && newExplodeAmount == 0.0f) + { + // Going from exploded to unexploded. Need to make the skinned mesh invisible. + if (m_renderMeshActors[DestructibleActorMeshType::Skinned] != NULL) + { + for (uint32_t i = 0; i < m_asset->getChunkCount(); ++i) + { + m_renderMeshActors[DestructibleActorMeshType::Skinned]->setVisibility(false, (uint16_t)i); + } + } + } + } + + m_explodeAmount = newExplodeAmount; + + for (uint32_t i = 0; i < m_instancedChunkRenderMeshActors.size(); ++i) + { + PX_ASSERT(i < m_chunkInstanceBufferData.size()); + m_chunkInstanceBufferData[i].resize(0); + } + + if (m_asset->getRenderMeshAsset() != NULL) + { + PxBounds3 bounds = m_asset->getRenderMeshAsset()->getBounds(); + PxVec3 c = bounds.getCenter(); + + for (uint16_t i = 0; i < (uint16_t)m_asset->getChunkCount(); ++i) + { + setChunkVisibility(i, m_asset->mParams->chunks.buf[i].depth == m_chunkDepth); + } + + DestructibleAssetParametersNS::Chunk_Type* sourceChunks = m_asset->mParams->chunks.buf; + + mRenderBounds.setEmpty(); + + // Iterate over all visible chunks + const uint16_t* indexPtr = mVisibleChunks.usedIndices(); + const uint16_t* indexPtrStop = indexPtr + mVisibleChunks.usedCount(); + DestructibleAssetParametersNS::InstanceInfo_Type* instanceDataArray = m_asset->mParams->chunkInstanceInfo.buf; + while (indexPtr < indexPtrStop) + { + const uint16_t index = *indexPtr++; + if (index < m_asset->getChunkCount()) + { + DestructibleAssetParametersNS::Chunk_Type& sourceChunk = sourceChunks[index]; + PxMat44 pose = mPose; + if ((sourceChunk.flags & DestructibleAssetImpl::Instanced) == 0) + { + // Not instanced - only need to set skinned tms from chunks + if (!m_drawUnexpandedChunksStatically || m_explodeAmount != 0.0f) + { + PxBounds3 partBounds = m_asset->getRenderMeshAsset()->getBounds(sourceChunk.meshPartIndex); + PxVec3 partC = partBounds.getCenter(); + pose.setPosition(pose.getPosition() + m_explodeAmount*pose.rotate(partC-c)); + m_renderMeshActors[DestructibleActorMeshType::Skinned]->setTM(pose, sourceChunk.meshPartIndex); + } + } + else + { + // Instanced + PX_ASSERT(sourceChunk.meshPartIndex < m_asset->mParams->chunkInstanceInfo.arraySizes[0]); + DestructibleAssetImpl::ChunkInstanceBufferDataElement instanceDataElement; + DestructibleAssetParametersNS::InstanceInfo_Type& instanceData = instanceDataArray[sourceChunk.meshPartIndex]; + const uint16_t instancedActorIndex = m_instancedChunkActorMap[sourceChunk.meshPartIndex]; + physx::Array<DestructibleAssetImpl::ChunkInstanceBufferDataElement>& instanceBufferData = m_chunkInstanceBufferData[instancedActorIndex]; + instanceDataElement.scaledRotation = PxMat33(pose.getBasis(0), pose.getBasis(1), pose.getBasis(2)); + const PxVec3 globalOffset = instanceDataElement.scaledRotation*instanceData.chunkPositionOffset; + PxBounds3 partBounds = m_asset->getRenderMeshAsset()->getBounds(instanceData.partIndex); + partBounds.minimum += globalOffset; + partBounds.maximum += globalOffset; + PxVec3 partC = partBounds.getCenter(); + instanceDataElement.translation = pose.getPosition() + globalOffset + m_explodeAmount*pose.rotate(partC-c); + instanceDataElement.uvOffset = instanceData.chunkUVOffset; + instanceDataElement.localOffset = instanceData.chunkPositionOffset; + instanceBufferData.pushBack(instanceDataElement); + // Transform bounds + PxVec3 center, extents; + center = partBounds.getCenter(); + extents = partBounds.getExtents(); + center = instanceDataElement.scaledRotation.transform(center) + instanceDataElement.translation; + extents = PxVec3(PxAbs(instanceDataElement.scaledRotation(0, 0) * extents.x) + PxAbs(instanceDataElement.scaledRotation(0, 1) * extents.y) + PxAbs(instanceDataElement.scaledRotation(0, 2) * extents.z), + PxAbs(instanceDataElement.scaledRotation(1, 0) * extents.x) + PxAbs(instanceDataElement.scaledRotation(1, 1) * extents.y) + PxAbs(instanceDataElement.scaledRotation(1, 2) * extents.z), + PxAbs(instanceDataElement.scaledRotation(2, 0) * extents.x) + PxAbs(instanceDataElement.scaledRotation(2, 1) * extents.y) + PxAbs(instanceDataElement.scaledRotation(2, 2) * extents.z)); + mRenderBounds.include(PxBounds3::centerExtents(center, extents)); + } + } + } + + m_renderMeshActors[DestructibleActorMeshType::Skinned]->updateBounds(); + mRenderBounds.include(m_renderMeshActors[DestructibleActorMeshType::Skinned]->getBounds()); + + // If a static mesh exists, set its (single) tm from the destructible's tm + if (m_renderMeshActors[DestructibleActorMeshType::Static] != NULL) + { + m_renderMeshActors[DestructibleActorMeshType::Static]->syncVisibility(); + m_renderMeshActors[DestructibleActorMeshType::Static]->setTM(mPose); + m_renderMeshActors[DestructibleActorMeshType::Static]->updateBounds(); + mRenderBounds.include(m_renderMeshActors[DestructibleActorMeshType::Static]->getBounds()); + } + } +} + +void DestructiblePreviewImpl::updateRenderResources(bool rewriteBuffers, void* userRenderData) +{ + for (uint32_t i = 0; i < DestructibleActorMeshType::Count; ++i) + { + if (m_renderMeshActors[i] != NULL) + { + RenderMeshActorIntl* renderMeshActor = (RenderMeshActorIntl*)m_renderMeshActors[i]; + renderMeshActor->updateRenderResources((i == DestructibleActorMeshType::Skinned), rewriteBuffers, userRenderData); + } + } + + setInstancedChunkCount(m_instancedChunkCount); + + for (uint32_t i = 0; i < m_instancedChunkRenderMeshActors.size(); ++i) + { + PX_ASSERT(i < m_chunkInstanceBufferData.size()); + RenderMeshActorIntl* renderMeshActor = (RenderMeshActorIntl*)m_instancedChunkRenderMeshActors[i]; + if (renderMeshActor != NULL) + { + physx::Array<DestructibleAssetImpl::ChunkInstanceBufferDataElement>& instanceBufferData = m_chunkInstanceBufferData[i]; + const uint32_t instanceBufferSize = instanceBufferData.size(); + if (instanceBufferSize > 0) + { + m_chunkInstanceBuffers[i]->writeBuffer(&instanceBufferData[0], 0, instanceBufferSize); + } + renderMeshActor->setInstanceBufferRange(0, instanceBufferSize); + renderMeshActor->updateRenderResources(false, rewriteBuffers, userRenderData); + } + } +} + +void DestructiblePreviewImpl::dispatchRenderResources(UserRenderer& renderer) +{ + for (uint32_t i = 0; i < DestructibleActorMeshType::Count; ++i) + { + if (m_renderMeshActors[i] != NULL) + { + m_renderMeshActors[i]->dispatchRenderResources(renderer); + } + } + + for (uint32_t i = 0; i < m_instancedChunkRenderMeshActors.size(); ++i) + { + PX_ASSERT(i < m_chunkInstanceBufferData.size()); + if (m_instancedChunkRenderMeshActors[i] != NULL) + { + if (m_chunkInstanceBufferData[i].size() > 0) + { + m_instancedChunkRenderMeshActors[i]->dispatchRenderResources(renderer); + } + } + } +} + +void DestructiblePreviewImpl::release() +{ + if (mInRelease) + { + return; + } + mInRelease = true; + destroy(); +} + +void DestructiblePreviewImpl::destroy() +{ + ApexPreview::destroy(); + + for (uint32_t i = 0; i < DestructibleActorMeshType::Count; ++i) + { + if (m_renderMeshActors[i] != NULL) + { + m_renderMeshActors[i]->release(); + } + } + + setInstancedChunkCount(0); +} + +void DestructiblePreviewImpl::setInstancedChunkCount(uint32_t count) +{ + UserRenderResourceManager* rrm = GetInternalApexSDK()->getUserRenderResourceManager(); + + const uint32_t oldCount = m_instancedChunkRenderMeshActors.size(); + for (uint32_t i = count; i < oldCount; ++i) + { + if (m_instancedChunkRenderMeshActors[i] != NULL) + { + m_instancedChunkRenderMeshActors[i]->release(); + m_instancedChunkRenderMeshActors[i] = NULL; + } + if (m_chunkInstanceBuffers[i] != NULL) + { + rrm->releaseInstanceBuffer(*m_chunkInstanceBuffers[i]); + m_chunkInstanceBuffers[i] = NULL; + } + } + m_instancedChunkRenderMeshActors.resize(count); + m_chunkInstanceBuffers.resize(count); + m_chunkInstanceBufferData.resize(count); + for (uint32_t index = oldCount; index < count; ++index) + { + m_instancedChunkRenderMeshActors[index] = NULL; + m_chunkInstanceBuffers[index] = NULL; + m_chunkInstanceBufferData[index].reset(); + + // Find out how many potential instances there are + uint32_t maxInstanceCount = 0; + for (int32_t i = 0; i < m_asset->mParams->chunkInstanceInfo.arraySizes[0]; ++i) + { + if (m_asset->mParams->chunkInstanceInfo.buf[i].partIndex == m_instancedActorVisiblePart[index]) + { + ++maxInstanceCount; + } + } + + // Create instance buffer + UserRenderInstanceBufferDesc instanceBufferDesc; + instanceBufferDesc.maxInstances = maxInstanceCount; + instanceBufferDesc.hint = RenderBufferHint::DYNAMIC; + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::POSITION_FLOAT3] = DestructibleAssetImpl::ChunkInstanceBufferDataElement::translationOffset(); + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::ROTATION_SCALE_FLOAT3x3] = DestructibleAssetImpl::ChunkInstanceBufferDataElement::scaledRotationOffset(); + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::UV_OFFSET_FLOAT2] = DestructibleAssetImpl::ChunkInstanceBufferDataElement::uvOffsetOffset(); + instanceBufferDesc.semanticOffsets[RenderInstanceLayoutElement::LOCAL_OFFSET_FLOAT3] = DestructibleAssetImpl::ChunkInstanceBufferDataElement::localOffsetOffset(); + instanceBufferDesc.stride = sizeof(DestructibleAssetImpl::ChunkInstanceBufferDataElement); + m_chunkInstanceBuffers[index] = rrm->createInstanceBuffer(instanceBufferDesc); + + // Instance buffer data + m_chunkInstanceBufferData[index].reserve(maxInstanceCount); + m_chunkInstanceBufferData[index].resize(0); + + // Create actor + if (m_asset->renderMeshAsset != NULL) + { + RenderMeshActorDesc renderableMeshDesc; + renderableMeshDesc.maxInstanceCount = maxInstanceCount; + renderableMeshDesc.renderWithoutSkinning = true; + renderableMeshDesc.visible = false; + m_instancedChunkRenderMeshActors[index] = m_asset->renderMeshAsset->createActor(renderableMeshDesc); + m_instancedChunkRenderMeshActors[index]->setInstanceBuffer(m_chunkInstanceBuffers[index]); + m_instancedChunkRenderMeshActors[index]->setVisibility(true, m_instancedActorVisiblePart[index]); + } + } +} + +} +} // end namespace nvidia + diff --git a/APEX_1.4/module/destructible/src/DestructibleRenderableImpl.cpp b/APEX_1.4/module/destructible/src/DestructibleRenderableImpl.cpp new file mode 100644 index 00000000..43ca5c05 --- /dev/null +++ b/APEX_1.4/module/destructible/src/DestructibleRenderableImpl.cpp @@ -0,0 +1,180 @@ +/* + * 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. + */ + + +#include "DestructibleRenderable.h" +#include "RenderMeshActor.h" +#include "DestructibleActorImpl.h" +#include "ModulePerfScope.h" + +namespace nvidia +{ +namespace destructible +{ + +DestructibleRenderableImpl::DestructibleRenderableImpl(RenderMeshActor* renderMeshActors[DestructibleActorMeshType::Count], DestructibleAssetImpl* asset, int32_t listIndex) +: mAsset(asset) +, mListIndex(listIndex) +, mRefCount(1) // Ref count initialized to 1, assuming that whoever calls this constructor will store a reference +{ + for (uint32_t i = 0; i < DestructibleActorMeshType::Count; ++i) + { + mRenderMeshActors[i] = renderMeshActors[i]; + } +} + +DestructibleRenderableImpl::~DestructibleRenderableImpl() +{ + WRITE_ZONE(); + for (uint32_t i = 0; i < DestructibleActorMeshType::Count; ++i) + { + if (mRenderMeshActors[i]) + { + mRenderMeshActors[i]->release(); + mRenderMeshActors[i] = NULL; + } + } +} + +void DestructibleRenderableImpl::release() +{ + bool triggerDelete = false; + lockRenderResources(); + if (mRefCount > 0) + { + triggerDelete = !(--mRefCount); + } + unlockRenderResources(); + if (triggerDelete) + { + delete this; + } +} + +void DestructibleRenderableImpl::updateRenderResources(bool rewriteBuffers, void* userRenderData) +{ + PX_PROFILE_ZONE("DestructibleRenderableUpdateRenderResources", GetInternalApexSDK()->getContextId()); + + URR_SCOPE; + + for (uint32_t typeN = 0; typeN < DestructibleActorMeshType::Count; ++typeN) + { + RenderMeshActorIntl* renderMeshActor = (RenderMeshActorIntl*)mRenderMeshActors[typeN]; + if (renderMeshActor != NULL) + { + renderMeshActor->updateRenderResources((typeN == DestructibleActorMeshType::Skinned), rewriteBuffers, userRenderData); + } + } + + // Render instanced meshes + if (mAsset->m_instancingRepresentativeActorIndex == -1) + { + mAsset->m_instancingRepresentativeActorIndex = (int32_t)mListIndex; // using this actor as our representative + } + if ((int32_t)mListIndex == mAsset->m_instancingRepresentativeActorIndex) // doing it this way, in case (for some reason) someone wants to call this fn twice per frame + { + mAsset->updateChunkInstanceRenderResources(rewriteBuffers, userRenderData); + + mAsset->createScatterMeshInstanceInfo(); + + for (uint32_t i = 0; i < mAsset->m_scatterMeshInstanceInfo.size(); ++i) + { + DestructibleAssetImpl::ScatterMeshInstanceInfo& info = mAsset->m_scatterMeshInstanceInfo[i]; + RenderMeshActorIntl* renderMeshActor = (RenderMeshActorIntl*)info.m_actor; + if (renderMeshActor != NULL) + { + RenderInstanceBufferData data; + physx::Array<DestructibleAssetImpl::ScatterInstanceBufferDataElement>& instanceBufferData = info.m_instanceBufferData; + const uint32_t instanceBufferSize = instanceBufferData.size(); + + if (info.m_instanceBuffer != NULL && instanceBufferSize > 0) + { + // If a new actor has added instances for this scatter mesh, recreate a larger instance buffer + if (info.m_IBSize < instanceBufferSize) + { + UserRenderResourceManager* rrm = GetInternalApexSDK()->getUserRenderResourceManager(); + rrm->releaseInstanceBuffer(*info.m_instanceBuffer); + + UserRenderInstanceBufferDesc instanceBufferDesc = mAsset->getScatterMeshInstanceBufferDesc(); + instanceBufferDesc.maxInstances = instanceBufferSize; + + info.m_instanceBuffer = rrm->createInstanceBuffer(instanceBufferDesc); + info.m_IBSize = instanceBufferSize; + + renderMeshActor->setInstanceBuffer(info.m_instanceBuffer); + renderMeshActor->setMaxInstanceCount(instanceBufferSize); + } + + info.m_instanceBuffer->writeBuffer(&instanceBufferData[0], 0, instanceBufferSize); + } + renderMeshActor->setInstanceBufferRange(0, instanceBufferSize); + renderMeshActor->updateRenderResources(false, rewriteBuffers, userRenderData); + } + } + } + +#if APEX_RUNTIME_FRACTURE + mRTrenderable.updateRenderResources(rewriteBuffers,userData); +#endif +} + +void DestructibleRenderableImpl::dispatchRenderResources(UserRenderer& renderer) +{ + PX_PROFILE_ZONE("DestructibleRenderableDispatchRenderResources", GetInternalApexSDK()->getContextId()); + + for (uint32_t typeN = 0; typeN < DestructibleActorMeshType::Count; ++typeN) + { + RenderMeshActor* renderMeshActor = mRenderMeshActors[typeN]; + if (renderMeshActor != NULL) + { + renderMeshActor->dispatchRenderResources(renderer); + } + } + + // Render instanced meshes + if ((int32_t)mListIndex == mAsset->m_instancingRepresentativeActorIndex) + { + for (uint32_t i = 0; i < mAsset->m_instancedChunkRenderMeshActors.size(); ++i) + { + if (mAsset->m_instancedChunkRenderMeshActors[i] != NULL) + { + mAsset->m_instancedChunkRenderMeshActors[i]->dispatchRenderResources(renderer); + } + } + + for (uint32_t i = 0; i < mAsset->m_scatterMeshInstanceInfo.size(); ++i) + { + DestructibleAssetImpl::ScatterMeshInstanceInfo& scatterMeshInstanceInfo = mAsset->m_scatterMeshInstanceInfo[i]; + if (scatterMeshInstanceInfo.m_actor != NULL) + { + scatterMeshInstanceInfo.m_actor->dispatchRenderResources(renderer); + } + } + } +#if APEX_RUNTIME_FRACTURE + mRTrenderable.dispatchRenderResources(renderer); +#endif +} + +DestructibleRenderableImpl* DestructibleRenderableImpl::incrementReferenceCount() +{ + DestructibleRenderableImpl* returnValue = NULL; + lockRenderResources(); + if (mRefCount > 0) + { + ++mRefCount; + returnValue = this; + } + unlockRenderResources(); + return returnValue; +} + +} +} // end namespace nvidia diff --git a/APEX_1.4/module/destructible/src/DestructibleScene.cpp b/APEX_1.4/module/destructible/src/DestructibleScene.cpp new file mode 100644 index 00000000..4217e71f --- /dev/null +++ b/APEX_1.4/module/destructible/src/DestructibleScene.cpp @@ -0,0 +1,4078 @@ +/* + * 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. + */ + + +#include "ApexDefs.h" + +#include "Apex.h" +#include "SceneIntl.h" +#include "ModuleDestructibleImpl.h" +#include "DestructibleScene.h" +#include "DestructibleAssetImpl.h" +#include "DestructibleActorImpl.h" +#include "DestructibleActorProxy.h" +#include "DestructibleActorJointProxy.h" +#include "DestructibleStructureStressSolver.h" +#if APEX_USE_PARTICLES +#include "EmitterActor.h" +#include "EmitterGeoms.h" +#endif + +#include "PsArray.h" +#include "PxScene.h" +#include "PxConvexMeshDesc.h" +#include "PxConvexMeshGeometry.h" +#include "PxBoxGeometry.h" +#include "PxSphereGeometry.h" + +#if APEX_RUNTIME_FRACTURE +#include "SimScene.h" +#include "Convex.h" +#include "Compound.h" +#include "Actor.h" +#endif + +#include "ApexRand.h" +#include "ModulePerfScope.h" +#include "PsString.h" +#include "PsTime.h" + +#include "RenderMeshAssetIntl.h" + +#include "Lock.h" +#include "PxProfiler.h" + +#define USE_ACTIVE_TRANSFORMS_FOR_AWAKE_LIST 1 + +namespace nvidia +{ +namespace destructible +{ +using namespace physx; + +namespace +{ + void unfortunateCompilerWorkaround(uint32_t) + { + } +}; + +PX_INLINE PxVec3 transformToScreenSpace(const PxVec3& pos, const float* viewProjectionMatrix) +{ + const float v[4] = { pos.x, pos.y, pos.z, 1.0f }; + + float u[4] = { 0, 0, 0, 0 }; + + const float* row = viewProjectionMatrix; + for (uint32_t i = 0; i < 4; ++i, ++row) + { + for (uint32_t j = 0; j < 4; ++j) + { + u[i] += row[j << 2] * v[j]; + } + } + + const float recipW = 1.0f / u[3]; + + return PxVec3(u[0] * recipW, u[1] * recipW, u[2] * recipW); +} + +// Put an actor to sleep based upon input velocities. +PX_INLINE void handleSleeping(PxRigidDynamic* actor, PxVec3 linearVelocity, PxVec3 angularVelocity) +{ + // In PhysX3, we only use an energy threshold. + if (actor == NULL) + { + return; + } + // Calculate kinetic energy + const float mass = actor->getMass(); + const float linearKE = 0.5f*mass*linearVelocity.magnitudeSquared(); + const PxTransform globalToMassT = actor->getCMassLocalPose().transform(actor->getGlobalPose()); + const PxVec3 massSpaceAngularVelocity = globalToMassT.rotateInv(angularVelocity); + const float rotationalKE = 0.5f*massSpaceAngularVelocity.dot(actor->getMassSpaceInertiaTensor().multiply(massSpaceAngularVelocity)); + const float totalKE = linearKE + rotationalKE; + // Put to sleep if below threshold + if (totalKE <= actor->getSleepThreshold()*mass) + { + actor->setLinearVelocity(PxVec3(0.0f)); + actor->setAngularVelocity(PxVec3(0.0f)); + actor->putToSleep(); + } +} + +/**************************** +* DestructibleUserNotify * +*****************************/ + +DestructibleUserNotify::DestructibleUserNotify(ModuleDestructibleImpl& module, DestructibleScene* destructibleScene) : +mModule(module), +mDestructibleScene(destructibleScene) +{ + +} +void DestructibleUserNotify::onConstraintBreak(physx::PxConstraintInfo* constraints, uint32_t count) +{ + PX_UNUSED(constraints); + PX_UNUSED(count); +} + +void DestructibleUserNotify::onWake(PxActor** actors, uint32_t count) +{ + if (mDestructibleScene->mUsingActiveTransforms) // The remaining code in this function only updates the destructible actor awake list when not using active transforms + { + return; + } + + for (uint32_t i = 0; i < count; i++) + { + PxActor* actor = actors[i]; + PhysXObjectDescIntl* desc = (PhysXObjectDescIntl*)(mModule.mSdk->getPhysXObjectInfo(actor)); + if (desc != NULL) + { + if (desc->getUserDefinedFlag(PhysXActorFlags::CREATED_THIS_FRAME) || desc->getUserDefinedFlag(PhysXActorFlags::IS_SLEEPING)) + { + // Only increase the counter in the first wake call, or + // when the state has changed since the last callback. + // IS_SLEEPING has to be checked, because with PhysX 3.3 we also + // receive a callback when the user calls putToSleep on an awake actor + // and the SDK wakes it up again. + + // increase wake count on each referenced destructible + const uint32_t dActorCount = desc->mApexActors.size(); + for (uint32_t i = 0; i < dActorCount; ++i) + { + const DestructibleActor* dActor = static_cast<const DestructibleActor*>(desc->mApexActors[i]); + if (dActor != NULL) + { + if (desc->mApexActors[i]->getOwner()->getObjTypeID() == DestructibleAssetImpl::getAssetTypeID()) + { + DestructibleActorImpl& destructibleActor = const_cast<DestructibleActorImpl&>(static_cast<const DestructibleActorProxy*>(dActor)->impl); + destructibleActor.incrementWakeCount(); + } + } + } + + // update externally stored state of this physx actor + desc->setUserDefinedFlag(PhysXActorFlags::IS_SLEEPING, false); + } + + desc->setUserDefinedFlag(PhysXActorFlags::CREATED_THIS_FRAME, false); + } + } +} + +void DestructibleUserNotify::onSleep(PxActor** actors, uint32_t count) +{ + if (mDestructibleScene->mUsingActiveTransforms) // The remaining code in this function only updates the destructible actor awake list when not using active transforms + { + return; + } + + for (uint32_t i = 0; i < count; i++) + { + PxActor* actor = actors[i]; + PhysXObjectDescIntl* desc = (PhysXObjectDescIntl*)(mModule.mSdk->getPhysXObjectInfo(actor)); + if (desc != NULL) + { + if (desc->getUserDefinedFlag(PhysXActorFlags::CREATED_THIS_FRAME)) + { + // first sleep callback must be ignored, as it's not a state change, but initialization + desc->setUserDefinedFlag(PhysXActorFlags::CREATED_THIS_FRAME, false); + desc->setUserDefinedFlag(PhysXActorFlags::IS_SLEEPING, true); + continue; + } + + if (!desc->getUserDefinedFlag(PhysXActorFlags::IS_SLEEPING)) + { + // Only decrease the wake count, if the state has really changed to sleeping + // since the last callback + const uint32_t dActorCount = desc->mApexActors.size(); + for (uint32_t i = 0; i < dActorCount; ++i) + { + const DestructibleActor* dActor = static_cast<const DestructibleActor*>(desc->mApexActors[i]); + if (dActor != NULL) + { + if (desc->mApexActors[i]->getOwner()->getObjTypeID() == DestructibleAssetImpl::getAssetTypeID()) + { + DestructibleActorImpl& destructibleActor = const_cast<DestructibleActorImpl&>(static_cast<const DestructibleActorProxy*>(dActor)->impl); + destructibleActor.decrementWakeCount(); + } + } + } + + desc->setUserDefinedFlag(PhysXActorFlags::IS_SLEEPING, true); + } + } + } +} + + +void DestructibleUserNotify::onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, uint32_t nbPairs) +{ + if (pairHeader.flags & physx::PxContactPairHeaderFlag::eREMOVED_ACTOR_0 || + pairHeader.flags & physx::PxContactPairHeaderFlag::eREMOVED_ACTOR_1 || + pairHeader.actors[0] == NULL || + pairHeader.actors[1] == NULL) + { + return; + } + + ModuleDestructibleImpl* module = mDestructibleScene->mModule; + int moduleOwnsActor[2] = + { + (int)module->owns(pairHeader.actors[0]->is<physx::PxRigidActor>()), + (int)module->owns(pairHeader.actors[1]->is<physx::PxRigidActor>()) + }; + + if (!(moduleOwnsActor[0] | moduleOwnsActor[1])) + { + return; // Neither is owned by the destruction module + } + + for (uint32_t pairIdx = 0; pairIdx < nbPairs; pairIdx++) + { + const PxContactPair& currentPair = pairs[pairIdx]; + + if (currentPair.flags & physx::PxContactPairFlag::eREMOVED_SHAPE_0 || + currentPair.flags & physx::PxContactPairFlag::eREMOVED_SHAPE_1 || + currentPair.shapes[0] == NULL || + currentPair.shapes[1] == NULL) + { + continue; + } + + DestructibleActorImpl* destructibles[2] = {NULL, NULL}; + DestructibleStructure::Chunk* chunks[2] = {NULL, NULL}; + bool takesImpactDamage[2] = {false, false}; + float minImpactVelocityThresholdsSq = PX_MAX_REAL; + + for (int i = 0; i < 2; ++i) + { + PxShape* shape = currentPair.shapes[i]; + if (moduleOwnsActor[i] && module->getDestructibleAndChunk(shape, NULL) == NULL) + { + chunks[i] = NULL; + } + else + { + chunks[i] = mDestructibleScene->getChunk(shape); + } + if (chunks[i] != NULL) + { + destructibles[i] = mDestructibleScene->mDestructibles.direct(chunks[i]->destructibleID); + PX_ASSERT(destructibles[i] != NULL); + if (destructibles[i] != NULL) + { + float ivts = destructibles[i]->getDestructibleParameters().impactVelocityThreshold; + ivts *= ivts; + if (ivts < minImpactVelocityThresholdsSq) + { + minImpactVelocityThresholdsSq = ivts; + } + + int32_t depth = destructibles[i]->getDestructibleAsset()->getChunkDepth(chunks[i]->indexInAsset); + takesImpactDamage[i] = destructibles[i]->takesImpactDamageAtDepth((uint32_t)depth); + } + } + } + if (destructibles[0] == destructibles[1]) + { + return; // No self-collision. To do: multiply by a self-collision factor instead? + } + + if (!takesImpactDamage[0] && !takesImpactDamage[1]) + { + return; + } + + float masses[2]; + { + for (int i = 0; i < 2; ++i) + { + masses[i] = 0; + PxRigidDynamic* rigidDynamic = pairHeader.actors[i]->is<physx::PxRigidDynamic>(); + if (rigidDynamic) + { + SCOPED_PHYSX_LOCK_READ(rigidDynamic->getScene()); + if (!(rigidDynamic->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC)) + { + masses[i] = rigidDynamic->getMass(); + } + } + } + }; + + float reducedMass; + if (masses[0] == 0.0f) + { + reducedMass = masses[1]; + } + else if (masses[1] == 0.0f) + { + reducedMass = masses[0]; + } + else + { + reducedMass = masses[0] * masses[1] / (masses[0] + masses[1]); + } + + + PxVec3 destructibleForces[2] = {PxVec3(0.0f), PxVec3(0.0f)}; + PxVec3 avgContactPosition = PxVec3(0.0f); + PxVec3 avgContactNormal = PxVec3(0.0f); + uint32_t numContacts = 0; + +#if USE_EXTRACT_CONTACTS +#if PAIR_POINT_ALLOCS + PxContactPairPoint* pairPointBuffer = (PxContactPairPoint*)PX_ALLOC(currentPair.contactCount * sizeof(PxContactPairPoint), PX_DEBUG_EXP("PxContactPairPoints")); +#else + mPairPointBuffer.reserve(currentPair.contactCount * sizeof(PxContactPairPoint)); + + // if this method isn't used, the operator[] method will fail because the actual size may be zero + mPairPointBuffer.forceSize_Unsafe(currentPair.contactCount * sizeof(PxContactPairPoint)); + PxContactPairPoint* pairPointBuffer = currentPair.contactCount > 0 ? (PxContactPairPoint*)&(mPairPointBuffer[0]) : NULL; +#endif + uint32_t numContactsInStream = pairPointBuffer != NULL ? currentPair.extractContacts(pairPointBuffer, currentPair.contactCount) : 0; +#else + uint32_t numContactsInStream = currentPair.contactCount; + const PxContactPoint* contacts = reinterpret_cast<const PxContactPoint*>(currentPair.contactStream); +#endif + + + for (uint32_t contactIdx = 0; contactIdx < numContactsInStream; contactIdx++) + { +#if USE_EXTRACT_CONTACTS + PxContactPairPoint& currentPoint = pairPointBuffer[contactIdx]; + + const PxVec3& patchNormal = currentPoint.normal; + const PxVec3& position = currentPoint.position; +#else + const PxContactPoint& cp = contacts[contactIdx]; + + const PxVec3& patchNormal = cp.normal; + const PxVec3& position = cp.point; +#endif + PxVec3 velocities[2]; + for (int i = 0; i < 2; ++i) + { + PxRigidBody* rigidBody = pairHeader.actors[i]->is<physx::PxRigidBody>(); + if (rigidBody) + { + SCOPED_PHYSX_LOCK_READ(rigidBody->getScene()); + velocities[i] = physx::PxRigidBodyExt::getVelocityAtPos(*rigidBody, position); + } + } + + const PxVec3 velocityDelta = velocities[0] - velocities[1]; + if (velocityDelta.magnitudeSquared() >= minImpactVelocityThresholdsSq || reducedMass == 0.0f) // If reduced mass == 0, this is kineamtic vs. kinematic. Generate damage. + { + for (int i = 0; i < 2; ++i) + { + DestructibleActorImpl* destructible = destructibles[i]; + if (destructible) + { + // this is not really physically correct, but at least its deterministic... + destructibleForces[i] += (patchNormal * patchNormal.dot(velocityDelta)) * reducedMass * (i ? 1.0f : -1.0f); + } + } + avgContactPosition += position; + avgContactNormal += patchNormal; + numContacts++; + } + if (numContacts) + { + avgContactPosition /= (float)numContacts; + avgContactNormal.normalize(); + for (uint32_t i = 0; i < 2; i++) + { + if (!takesImpactDamage[i]) + continue; + + const PxVec3 force = destructibleForces[i] / (float)numContacts; + DestructibleActorImpl* destructible = destructibles[i]; + if (destructible != NULL) + { + if (!force.isZero()) + { + destructible->takeImpact(force, avgContactPosition, chunks[i]->indexInAsset, pairHeader.actors[i ^ 1]); + } + else if (reducedMass == 0.0f) // Handle kineamtic vs. kinematic + { + const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = destructible->getBehaviorGroup(chunks[i]->indexInAsset); + destructible->applyDamage(2.0f*behaviorGroup.damageThreshold, 0.0f, avgContactPosition, (avgContactNormal * (i ? 1.0f : -1.0f)), chunks[i]->indexInAsset); + } + } + } + } + } + +#if PAIR_POINT_ALLOCS + if (pairPointBuffer != NULL) + { + PX_FREE(pairPointBuffer); + } +#endif + } +} + + +void DestructibleUserNotify::onTrigger(PxTriggerPair* pairs, uint32_t count) +{ + PX_UNUSED(pairs); + PX_UNUSED(count); +} + + +void DestructibleUserNotify::onAdvance(const PxRigidBody*const* bodyBuffer, const PxTransform* poseBuffer, const PxU32 count) +{ + PX_UNUSED(bodyBuffer); + PX_UNUSED(poseBuffer); + PX_UNUSED(count); +} + + +/**************************** +* DestructibleContactModify * +*****************************/ + +void DestructibleContactModify::onContactModify(PxContactModifyPair* const pairs, uint32_t count) +{ + PX_PROFILE_ZONE("DestructibleOnContactConstraint", GetInternalApexSDK()->getContextId()); + + for (uint32_t iPair = 0; iPair < count; iPair++) + { + PxContactModifyPair& pair = pairs[iPair]; + + ModuleDestructibleImpl* module = destructibleScene->mModule; + + int32_t chunkIndex0 = 0; + DestructibleActorProxy* proxy0 = static_cast<DestructibleActorProxy*>(module->getDestructibleAndChunk((PxShape*)pair.shape[0], &chunkIndex0)); + int32_t chunkIndex1 = 0; + DestructibleActorProxy* proxy1 = static_cast<DestructibleActorProxy*>(module->getDestructibleAndChunk((PxShape*)pair.shape[1], &chunkIndex1)); + + const bool moduleOwnsActor[2] = {proxy0 != NULL, proxy1 != NULL}; + + if (moduleOwnsActor[0] == moduleOwnsActor[1]) + { + continue; // Neither is owned by the destruction module, or both are + } + + const int externalRBIndex = (int)(moduleOwnsActor[1] == 0); + + destructibleScene->mApexScene->getPhysXScene()->lockRead(); + const bool externalActorDynamic = pair.actor[externalRBIndex]->is<physx::PxRigidDynamic>() != NULL; + destructibleScene->mApexScene->getPhysXScene()->unlockRead(); + + if (!externalActorDynamic) + { + continue; + } + + DestructibleActorProxy* proxy = externalRBIndex ? proxy0 : proxy1; + const float materialStrength = proxy->impl.getBehaviorGroup(uint32_t(externalRBIndex ? chunkIndex0 : chunkIndex1)).materialStrength; + if (materialStrength > 0.0f) + { + for (uint32_t contactIndex = 0; contactIndex < pair.contacts.size(); ++contactIndex) + { + pair.contacts.setMaxImpulse(contactIndex, materialStrength); + } + } + } +} + + +/**************************** +* ApexDamageEventReportDataImpl * +*****************************/ + +uint32_t +ApexDamageEventReportDataImpl::addFractureEvent(const DestructibleStructure::Chunk& chunk, uint32_t flags) +{ + PX_ASSERT(m_destructible != NULL); + if (m_destructible == NULL) + { + return 0xFFFFFFFF; + } + + // Find flags to see if we record this event + PX_ASSERT(!chunk.isDestroyed()); + if (chunk.state & ChunkDynamic) + { + flags |= ApexChunkFlag::DYNAMIC; + } + if (chunk.flags & ChunkExternallySupported) + { + flags |= ApexChunkFlag::EXTERNALLY_SUPPORTED; + } + if (chunk.flags & ChunkWorldSupported) + { + flags |= ApexChunkFlag::WORLD_SUPPORTED; + } + if (chunk.flags & ChunkCrumbled) + { + flags |= ApexChunkFlag::DESTROYED_CRUMBLED; + } + + // return invalid index if we don't record this event + if ((m_chunkReportBitMask & flags) == 0) + { + return 0xFFFFFFFF; + } + + PX_ASSERT(m_destructible->getID() == chunk.destructibleID); + const DestructibleAssetParametersNS::Chunk_Type& source = m_destructible->getDestructibleAsset()->mParams->chunks.buf[chunk.indexInAsset]; + + PxBounds3 chunkWorldBoundsOnStack; + PxBounds3* chunkWorldBounds = &chunkWorldBoundsOnStack; + + uint32_t fractureEventIndex = 0xFFFFFFFF; + + if (source.depth <= m_chunkReportMaxFractureEventDepth) + { + fractureEventIndex = m_fractureEvents.size(); + ChunkData& fractureEvent = m_fractureEvents.insert(); + fractureEventList = &m_fractureEvents[0]; + fractureEventListSize = m_fractureEvents.size(); + fractureEvent.index = chunk.indexInAsset; + fractureEvent.depth = source.depth; + fractureEvent.damage = chunk.damage; + chunkWorldBounds = &fractureEvent.worldBounds; // Will be filled in below + fractureEvent.flags = flags; + } + + // Adjust bounds to world coordinates + const PxVec3 scale = m_destructible->getScale(); + const PxBounds3& bounds = m_destructible->getDestructibleAsset()->getChunkShapeLocalBounds(chunk.indexInAsset); + chunkWorldBounds->minimum = bounds.minimum.multiply(scale); + chunkWorldBounds->maximum = bounds.maximum.multiply(scale); + PxBounds3Transform(*chunkWorldBounds, PxMat44(m_destructible->getChunkPose(chunk.indexInAsset))); + + worldBounds.include(*chunkWorldBounds); + minDepth = PxMin(minDepth, source.depth); + maxDepth = PxMax(maxDepth, source.depth); + ++totalNumberOfFractureEvents; + + return fractureEventIndex; +} + +void +ApexDamageEventReportDataImpl::setDestructible(DestructibleActorImpl* inDestructible) +{ + m_destructible = inDestructible; + if (m_destructible != NULL) + { + m_chunkReportBitMask = m_destructible->getStructure()->dscene->mModule->m_chunkReportBitMask; + m_chunkReportMaxFractureEventDepth = m_destructible->getStructure()->dscene->mModule->m_chunkReportMaxFractureEventDepth; + destructible = m_destructible->getAPI(); + minDepth = (uint16_t)(m_destructible->getDestructibleAsset()->mParams->depthCount > 0 ? m_destructible->getDestructibleAsset()->mParams->depthCount - 1 : 0); + maxDepth = 0; + } + else + { + clear(); + } +} + +void +ApexDamageEventReportDataImpl::clearChunkReports() +{ + PX_ASSERT(m_destructible != NULL); + if (m_destructible == NULL) + { + return; + } + + for (uint32_t i = 0; i < m_fractureEvents.size(); ++i) + { + ChunkData& fractureEvent = m_fractureEvents[i]; + DestructibleStructure::Chunk& chunk = m_destructible->getStructure()->chunks[fractureEvent.index + m_destructible->getFirstChunkIndex()]; + chunk.reportID = (uint32_t)DestructibleScene::InvalidReportID; + } + + totalNumberOfFractureEvents = 0; +} + +/******************** +* DestructibleScene * +********************/ + +class DestructibleBeforeTick : public PxTask, public UserAllocated +{ +public: + DestructibleBeforeTick(DestructibleScene& scene) : mScene(&scene), mDeltaTime(0.0f) {} + const char* getName() const + { + return "DestructibleScene::BeforeTick"; + } + void setDeltaTime(float deltaTime) + { + mDeltaTime = deltaTime; + } + void run() + { + mScene->tasked_beforeTick(mDeltaTime); + } + DestructibleScene* mScene; + float mDeltaTime; +}; + +static int comparePointers(const void* a, const void* b) +{ + return (uintptr_t)a == (uintptr_t)b ? 0 : ((uintptr_t)a < (uintptr_t)b ? -1 : 1); +} + +static int compareOverlapHitShapePointers(const void* a, const void* b) +{ + const physx::PxOverlapHit* overlapA = (const physx::PxOverlapHit*)a; + const physx::PxOverlapHit* overlapB = (const physx::PxOverlapHit*)b; + + return comparePointers(overlapA->shape, overlapB->shape); +} + +DestructibleScene::DestructibleScene(ModuleDestructibleImpl& module, SceneIntl& scene, RenderDebugInterface* debugRender, ResourceList& list) : + mUserNotify(module, this), + mElapsedTime(0.0f), + mMassScale(1.0f), + mMassScaleInv(1.0f), + mScaledMassExponent(0.5f), + mScaledMassExponentInv(2.0f), + mPreviousVisibleDestructibleChunkCount(0), + mPreviousDynamicDestructibleChunkIslandCount(0), + mDynamicActorFIFONum(0), + mTotalChunkCount(0), + mFractureEventCount(0), + mDamageBufferWriteIndex(0), + mUsingActiveTransforms(false), + m_worldSupportPhysXScene(NULL), + m_damageApplicationRaycastFlags(nvidia::DestructibleActorRaycastFlags::StaticChunks), + mDebugRender(debugRender), + mRenderLockMode(RenderLockMode::PER_ACTOR_RENDER_LOCK), + mSyncParams(module.getSyncParams()) +{ + list.add(*this); + mModule = &module; + mApexScene = &scene; + mPhysXScene = NULL; + mOverlapHits.resize(MAX_SHAPE_COUNT); + mApexScene->addModuleUserContactModify(mContactModify); + mContactModify.destructibleScene = this; + mNumFracturesProcessedThisFrame = 0; + mNumActorsCreatedThisFrame = 0; + mApexScene->addModuleUserNotifier(mUserNotify); + +#if APEX_RUNTIME_FRACTURE + mRTScene = NULL; +#endif + + mBeforeTickTask = PX_NEW(DestructibleBeforeTick)(*this); + + /* Initialize reference to DestructibleDebugRenderParams */ + { + READ_LOCK(*mApexScene); + mDebugRenderParams = DYNAMIC_CAST(DebugRenderParams*)(mApexScene->getDebugRenderParams()); + } + PX_ASSERT(mDebugRenderParams); + NvParameterized::Handle handle(*mDebugRenderParams), memberHandle(*mDebugRenderParams); + int size; + + if (mDebugRenderParams->getParameterHandle("moduleName", handle) == NvParameterized::ERROR_NONE) + { + handle.getArraySize(size, 0); + handle.resizeArray(size + 1); + if (handle.getChildHandle(size, memberHandle) == NvParameterized::ERROR_NONE) + { + memberHandle.initParamRef(DestructibleDebugRenderParams::staticClassName(), true); + } + } + + /* Load reference to DestructibleDebugRenderParams */ + NvParameterized::Interface* refPtr = NULL; + memberHandle.getParamRef(refPtr); + mDestructibleDebugRenderParams = DYNAMIC_CAST(DestructibleDebugRenderParams*)(refPtr); + PX_ASSERT(mDestructibleDebugRenderParams); + + if (mModule->isInitialized()) + { + // when scene is created after the module + initModuleSettings(); + } + setMassScaling(mModule->m_massScale, mModule->m_scaledMassExponent); + + createModuleStats(); +} + +void DestructibleScene::initModuleSettings() +{ + /* Initialize module defaults */ + setMassScaling(mModule->m_massScale, mModule->m_scaledMassExponent); +} + +DestructibleScene::~DestructibleScene() +{ +#if APEX_RUNTIME_FRACTURE + PX_DELETE(mRTScene); +#endif + + delete(DestructibleBeforeTick*) mBeforeTickTask; + + destroyModuleStats(); +} + +void DestructibleScene::destroy() +{ + removeAllActors(); + reset(); + PX_ASSERT(mAwakeActors.usedCount() == 0); // if there are actors left in here... thats very bad indeed. + mApexScene->removeModuleUserNotifier(mUserNotify); + mApexScene->removeModuleUserContactModify(mContactModify); + mApexScene->moduleReleased(*this); + + // The order of user callbacks being modified needed to change due to a crash (DE9025) +#if APEX_RUNTIME_FRACTURE + if(mRTScene) + { + mRTScene->restoreUserCallbacks(); + } +#endif + + delete this; +} + +void DestructibleScene::setModulePhysXScene(PxScene* pxScene) +{ + if (pxScene == mPhysXScene) + { + return; + } + + mPhysXScene = pxScene; + mSceneClientIDs.reset(); + + if (pxScene) + { +#if USE_ACTIVE_TRANSFORMS_FOR_AWAKE_LIST + SCOPED_PHYSX_LOCK_READ(mApexScene); + mUsingActiveTransforms = (mPhysXScene->getFlags() & PxSceneFlag::eENABLE_ACTIVETRANSFORMS); +#endif + // Actors will make calls back to add themselves to structures + for (uint32_t i = 0 ; i < mActorArray.size() ; i++) + { + mActorArray[i]->setPhysXScene(pxScene); + } + } + else + { + mUsingActiveTransforms = false; + + /* Release all destructible structures. TODO - this is not an optimal way to do this */ + for (uint32_t i = 0 ; i < mActorArray.size() ; i++) + { + mActorArray[i]->setPhysXScene(0); + } + + tasked_beforeTick(0.0f); + } +} + +#if APEX_RUNTIME_FRACTURE +::nvidia::fracture::SimScene* DestructibleScene::getDestructibleRTScene(bool create) +{ + if(mRTScene == NULL && create) + { + READ_LOCK(*mApexScene); + mRTScene = nvidia::fracture::SimScene::createSimScene(&mApexScene->getPhysXScene()->getPhysics(),GetApexSDK()->getCookingInterface(),mPhysXScene,0.02f,NULL,NULL); + mRTScene->clear(); + } + return mRTScene; +} +#endif + +DestructibleActorJoint* DestructibleScene::createDestructibleActorJoint(const DestructibleActorJointDesc& destructibleActorJointDesc) +{ + return PX_NEW(DestructibleActorJointProxy)(destructibleActorJointDesc, *this, mDestructibleActorJointList); +} + +PX_INLINE float square(float x) +{ + return x * x; +} + +bool DestructibleScene::insertDestructibleActor(DestructibleActor* nxdestructible) +{ + DestructibleActorImpl* destructible = &((DestructibleActorProxy*)nxdestructible)->impl; + if (destructible->getStructure()) + { + return false; + } + + const DestructibleActorParam* p = destructible->getParams(); + const physx::PxClientID clientID = p->p3ActorDescTemplate.ownerClient; + if (mSceneClientIDs.find(clientID) == mSceneClientIDs.end()) + { + mSceneClientIDs.pushBack(clientID); + } + + const float paddingFactor = destructible->getDestructibleAsset()->mParams->neighborPadding; + + physx::Array<DestructibleStructure*> overlappedStructures; + + const float padding = (destructible->getOriginalBounds().maximum - destructible->getOriginalBounds().minimum).magnitude() * paddingFactor; + + const bool formsExtendedStructures = !destructible->isInitiallyDynamic() && + destructible->formExtendedStructures(); + + uint32_t destructibleCount = 0; + DestructibleStructure* structureToUse = NULL; + + if (formsExtendedStructures) + { + // Static actor + const PxBounds3& box = destructible->getOriginalBounds(); + + // Find structures that this actor touches + for (uint32_t structureNum = 0; structureNum < mStructures.usedCount(); ++structureNum) + { + DestructibleStructure* structure = mStructures.getUsed(structureNum); + if (structure->destructibles.size() == 0) + { + continue; + } + DestructibleActorImpl* firstDestructible = structure->destructibles[0]; + if (firstDestructible->isInitiallyDynamic() || !firstDestructible->formExtendedStructures()) + { + continue; + } + // TODO: Support structure selection by hashing structure when serializing actor + // We can hook up with this structure + for (uint32_t destructibleIndex = 0; destructibleIndex < structure->destructibles.size(); ++destructibleIndex) + { + DestructibleActorImpl* existingDestructible = structure->destructibles[destructibleIndex]; + const PxBounds3& existingDestructibleBox = existingDestructible->getOriginalBounds(); + if (box.intersects(existingDestructibleBox)) + { + if (DestructibleAssetImpl::chunksInProximity(*destructible->getDestructibleAsset(), 0, PxTransform(destructible->getInitialGlobalPose()), destructible->getScale(), + *existingDestructible->getDestructibleAsset(), 0, PxTransform(existingDestructible->getInitialGlobalPose()), existingDestructible->getScale(), padding)) + { + // Record individual actor touches for neighbor list + if (structureToUse == NULL || structureToUse->destructibles.size() < structure->destructibles.size()) + { + structureToUse = structure; + } + overlappedStructures.pushBack(structure); + destructibleCount += structure->destructibles.size(); + break; + } + } + } + } + } + + physx::Array<DestructibleActorImpl*> destructiblesToAdd; + + if (structureToUse == NULL) + { + // Need to make a structure for this destructible + destructiblesToAdd.pushBack(destructible); + uint32_t structureID = UINT32_MAX; + if (!mStructures.useNextFree(structureID)) + { + PX_ASSERT(!"Could not create a new structure ID.\n"); + return false; + } + structureToUse = PX_NEW(DestructibleStructure)(this, structureID); + mStructures.direct(structureID) = structureToUse; + } + else + { + // We may re-use one of the overlappedStructures, and delete the rest + destructiblesToAdd.resize(destructibleCount - structureToUse->destructibles.size() + 1); // Exclude the ones in the structure already, include the one we're adding + uint32_t destructibleIndexOffset = 0; + for (uint32_t i = 0; i < overlappedStructures.size(); ++i) + { + DestructibleStructure* structure = overlappedStructures[i]; + if (structure == structureToUse) + { + continue; + } + memcpy(&destructiblesToAdd[destructibleIndexOffset], structure->destructibles.begin(), structure->destructibles.size()*sizeof(DestructibleActorImpl*)); + destructibleIndexOffset += structure->destructibles.size(); + mStructures.free(structure->ID); + mStructures.direct(structure->ID) = NULL; + delete structure; + } + PX_ASSERT(destructibleIndexOffset == destructiblesToAdd.size() - 1); + // Finally, add our new destructible to the list + destructiblesToAdd[destructibleIndexOffset] = destructible; + } + + return structureToUse->addActors(destructiblesToAdd); +} + +void DestructibleScene::reset() +{ + //===SyncParams=== + mDeprioritisedFractureBuffer.erase(); + + // Fracture buffer + mFractureBuffer.erase(); + + // Damage buffer + getDamageWriteBuffer().erase(); + getDamageReadBuffer().erase(); + + // FIFO + mDynamicActorFIFONum = 0; + mTotalChunkCount = 0; + mActorFIFO.reset(); + + // Dormant list + mDormantActors.clear(); + + // Level-specific arrays + mStructureKillList.reset(); + for (uint32_t actorKillIndex = 0; actorKillIndex < mActorKillList.size(); ++actorKillIndex) + { + PxRigidDynamic* actor = mActorKillList[actorKillIndex]; + PX_ASSERT(actor); + if (actor) + { + releasePhysXActor(*actor); + } + } + mActorKillList.reset(); + mDamageEventReportData.reset(); // DestructibleScene::reset should delete all DestructibleActors, too, so we shouldn't have bad DestructibleActor::mDamageEventReportIndex values floating around + mChunkReportHandles.reset(); + + // Structure container + for (uint32_t i = mStructures.usedCount(); i--;) + { + uint32_t index = mStructures.usedIndices()[i]; + delete mStructures.direct(index); + mStructures.free(index); + } + + mStructures.~Bank<DestructibleStructure*, uint32_t>(); + PX_PLACEMENT_NEW(&mStructures, (Bank<DestructibleStructure*, uint32_t>))(); + + mStructureUpdateList.~Bank<DestructibleStructure*, uint32_t>(); + PX_PLACEMENT_NEW(&mStructureUpdateList, (Bank<DestructibleStructure*, uint32_t>))(); + + mStructureSupportRebuildList.~Bank<DestructibleStructure*, uint32_t>(); + PX_PLACEMENT_NEW(&mStructureSupportRebuildList, (Bank<DestructibleStructure*, uint32_t>))(); + + uint32_t apexActorKillIndex = mApexActorKillList.getSize(); + while (apexActorKillIndex--) + { + DestructibleActorProxy* proxy = DYNAMIC_CAST(DestructibleActorProxy*)(mApexActorKillList.getResource(apexActorKillIndex)); + PX_ASSERT(proxy); + delete proxy; + } + + mChunkKillList.clear(); + + m_damageApplicationRaycastFlags = nvidia::DestructibleActorRaycastFlags::StaticChunks; +} + +void DestructibleScene::resetEmitterActors() +{ +# if APEX_USE_PARTICLES + for (uint32_t structureNum = 0; structureNum < mStructures.usedCount(); ++structureNum) + { + DestructibleStructure* structure = mStructures.getUsed(structureNum); + if (structure) + { + for (uint32_t destructibleIndex = 0; destructibleIndex < structure->destructibles.size(); ++destructibleIndex) + { + DestructibleActorImpl* destructible = structure->destructibles[destructibleIndex]; + if (!destructible) + { + continue; + } + + // stop all of the crumble and dust emitters in the destructible actors + if (destructible->getCrumbleEmitter() && destructible->getCrumbleEmitter()->isExplicitGeom()) + { + destructible->getCrumbleEmitter()->isExplicitGeom()->resetParticleList(); + } + if (destructible->getDustEmitter() && destructible->getDustEmitter()->isExplicitGeom()) + { + destructible->getDustEmitter()->isExplicitGeom()->resetParticleList(); + } + } + } + } +#endif +} + +void DestructibleScene::submitTasks(float elapsedTime, float /*substepSize*/, uint32_t /*numSubSteps*/) +{ + PX_PROFILE_ZONE("DestructibleScene/submitTasks", GetInternalApexSDK()->getContextId()); + mFractureEventCount = 0; + PxTaskManager* tm; + { + tm = mApexScene->getTaskManager(); + } + tm->submitNamedTask(mBeforeTickTask, mBeforeTickTask->getName()); + mBeforeTickTask->setDeltaTime(elapsedTime); +} + +void DestructibleScene::setTaskDependencies() +{ + PxTaskManager* tm; + { + tm = mApexScene->getTaskManager(); + } + const PxTaskID physxTick = tm->getNamedTask(AST_PHYSX_SIMULATE); + mBeforeTickTask->finishBefore(physxTick); +} + +class IRLess +{ +public: + bool operator()(IndexedReal& ir1, IndexedReal& ir2) const + { + return ir1.value < ir2.value; + } +}; + +void DestructibleScene::tasked_beforeTick(float elapsedTime) +{ + SCOPED_PHYSX_LOCK_WRITE(mApexScene); + + for (uint32_t i = 0; i < mStructureSupportRebuildList.usedCount(); ++i) + { + DestructibleStructure*& structure = mStructureSupportRebuildList.getUsed(i); + structure->buildSupportGraph(); + structure = NULL; // This is only OK because we are calling clearFast after this. This allows setStructureSupportRebuild to operate without firing asserts. + } + mStructureSupportRebuildList.clearFast(); + + if (m_invalidBounds.size()) + { + for (uint32_t i = 0; i < mStructures.usedCount(); ++i) + { + DestructibleStructure* structure = mStructures.getUsed(i); + if (structure != NULL) + { + structure->invalidateBounds(&m_invalidBounds[0], m_invalidBounds.size()); + } + } + m_invalidBounds.clear(); + } + processEventBuffers(); + + + capDynamicActorCount(); + + for (uint32_t actorKillIndex = 0; actorKillIndex < mActorKillList.size(); ++actorKillIndex) + { + PxRigidDynamic* actor = mActorKillList[actorKillIndex]; + PX_ASSERT(actor); + PhysXObjectDescIntl* actorObjDesc = mModule->mSdk->getGenericPhysXObjectInfo(actor); + if (actorObjDesc != NULL) + { + const uint32_t dActorCount = actorObjDesc->mApexActors.size(); + for (uint32_t i = 0; i < dActorCount; ++i) + { + const DestructibleActor* dActor = static_cast<const DestructibleActor*>(actorObjDesc->mApexActors[i]); + if (dActor != NULL) + { + if (actorObjDesc->mApexActors[i]->getOwner()->getObjTypeID() == DestructibleAssetImpl::getAssetTypeID()) + { + DestructibleActorImpl& destructibleActor = const_cast<DestructibleActorImpl&>(static_cast<const DestructibleActorProxy*>(dActor)->impl); + if (destructibleActor.getStructure() != NULL) + { + if (actor == destructibleActor.getStructure()->actorForStaticChunks) + { + destructibleActor.getStructure()->actorForStaticChunks = NULL; + } + } + } + } + } + actorObjDesc->mApexActors.clear(); + releasePhysXActor(*actor); + } + } + mActorKillList.reset(); + + NvParameterized::Interface* iface; + { + iface = mApexScene->getDebugRenderParams(); + } + + mNumFracturesProcessedThisFrame = 0; //reset this counter + mNumActorsCreatedThisFrame = 0; //reset this counter + + resetEmitterActors(); + + { + PX_PROFILE_ZONE("DestructibleRemoveChunksForBudget", GetInternalApexSDK()->getContextId()); + + // Remove chunks which need eliminating to keep budget + for (uint32_t i = 0; i < mChunkKillList.size(); ++i) + { + const IntPair& deadChunk = mChunkKillList[i]; + DestructibleStructure* structure = mStructures.direct((uint32_t)deadChunk.i0); + if (structure != NULL) + { + DestructibleStructure::Chunk& chunk = structure->chunks[(uint32_t)deadChunk.i1]; + if (!chunk.isDestroyed()) + { + structure->removeChunk(chunk); + } + } + } + mChunkKillList.clear(); + } + + //===SyncParams=== prepare user's fracture event buffer, if available + UserFractureEventHandler * callback = NULL; + callback = mModule->getSyncParams().getUserFractureEventHandler(); + const physx::Array<SyncParams::UserFractureEvent> * userSource = NULL; + if(NULL != callback) + { + mSyncParams.onPreProcessReadData(*callback, userSource); + } + + //===SyncParams=== give the user the fracture event buffer. fracture event buffer must be fully populated and locked during this call + if(NULL != callback) + { + mSyncParams.onProcessWriteData(*callback, mFractureBuffer); + } + + // Clear as much of the queue as we can + processFractureBuffer(); + //===SyncParams=== process user's fracture events + processFractureBuffer(userSource); + + // at this point all actors should have been created and added to the list for this tick + addActorsToScene(); + + //===SyncParams=== done with user's fracture event buffer, if available + if(NULL != callback) + { + mSyncParams.onPostProcessReadData(*callback); + } + callback = NULL; + + // Process Damage coloring from forceDamageColoring() + processDamageColoringBuffer(); + + { + PX_PROFILE_ZONE("DestructibleKillStructures", GetInternalApexSDK()->getContextId()); + + for (uint32_t structureKillIndex = 0; structureKillIndex < mStructureKillList.size(); ++structureKillIndex) + { + DestructibleStructure* structure = mStructureKillList[structureKillIndex]; + if (structure) + { + for (uint32_t destructibleIndex = structure->destructibles.size(); destructibleIndex--;) + { + DestructibleActorImpl*& destructible = structure->destructibles[destructibleIndex]; + if (destructible) + { + destructible->setStructure(NULL); + mDestructibles.direct(destructible->getID()) = NULL; + mDestructibles.free(destructible->getID()); + destructible = NULL; + } + } + } + + setStructureUpdate(structure, false); + + mStructures.free(structure->ID); + mStructures.direct(structure->ID) = NULL; + delete structure; + } + mStructureKillList.reset(); + } + + switch (getRenderLockMode()) + { + case RenderLockMode::NO_RENDER_LOCK: + break; + case RenderLockMode::PER_MODULE_SCENE_RENDER_LOCK: + lockModuleSceneRenderLock(); + break; + case RenderLockMode::PER_ACTOR_RENDER_LOCK: + default: + { + PX_PROFILE_ZONE("DestructibleBeforeTickLockRenderables", GetInternalApexSDK()->getContextId()); + for (uint32_t i = 0; i < mActorArray.size(); ++i) + { + mActorArray[i]->renderDataLock(); + } + } + break; + } + + const uint32_t actorCount = mActorFIFO.size(); + + if (mDynamicActorFIFONum > 0 && (((mModule->m_dynamicActorFIFOMax > 0 && mDynamicActorFIFONum > mModule->m_dynamicActorFIFOMax) || + (mModule->m_chunkFIFOMax > 0 && mTotalChunkCount > mModule->m_chunkFIFOMax)) && mModule->m_sortByBenefit)) + { + if (mActorBenefitSortArray.size() < mActorFIFO.size()) + { + mActorBenefitSortArray.resize(mActorFIFO.size()); + } + for (uint32_t i = 0; i < mActorFIFO.size(); ++i) + { + IndexedReal& ir = mActorBenefitSortArray[i]; + ActorFIFOEntry& entry = mActorFIFO[i]; + ir.value = entry.benefitCache; + ir.index = i; + } + if (mActorFIFO.size() > 1) + { + shdfnd::sort(&mActorBenefitSortArray[0], mActorFIFO.size(), IRLess()); + } + uint32_t sortIndex = 0; + if (mModule->m_dynamicActorFIFOMax > 0 && mDynamicActorFIFONum > mModule->m_dynamicActorFIFOMax) + { + while (sortIndex < mActorFIFO.size() && mDynamicActorFIFONum > mModule->m_dynamicActorFIFOMax) + { + IndexedReal& ir = mActorBenefitSortArray[sortIndex++]; + ActorFIFOEntry& entry = mActorFIFO[ir.index]; + if (entry.actor) + { + entry.flags |= ActorFIFOEntry::ForceLODRemove; + --mDynamicActorFIFONum; + } + } + } + uint32_t estTotalChunkCount = mTotalChunkCount; // This will get decremented again, in the FIFO loop below + if (mModule->m_chunkFIFOMax > 0 && estTotalChunkCount > mModule->m_chunkFIFOMax) + { + while (sortIndex < mActorFIFO.size() && estTotalChunkCount > mModule->m_chunkFIFOMax) + { + IndexedReal& ir = mActorBenefitSortArray[sortIndex++]; + ActorFIFOEntry& entry = mActorFIFO[ir.index]; + if (entry.actor) + { + entry.flags |= ActorFIFOEntry::ForceLODRemove; + const uint32_t chunkCount = entry.actor->getNbShapes(); + estTotalChunkCount = estTotalChunkCount > chunkCount ? estTotalChunkCount - chunkCount : 0; + } + } + } + } + + mDynamicActorFIFONum = 0; + for (uint32_t FIFOIndex = 0; FIFOIndex < actorCount; ++FIFOIndex) + { + ActorFIFOEntry& entry = mActorFIFO[FIFOIndex]; + if (!entry.actor) + { + continue; + } + PhysXObjectDescIntl* actorObjDesc = mModule->mSdk->getGenericPhysXObjectInfo(entry.actor); + if (!actorObjDesc) + { + continue; + } + + entry.benefitCache = 0.0f; + entry.age += elapsedTime; + uint32_t shapeCount; + if (actorObjDesc->userData != NULL && (shapeCount = entry.actor->getNbShapes()) != 0) + { + uint32_t reasonToDestroy = 0; + DestructibleActorImpl* destructible = NULL; + entry.maxSpeed = PX_MAX_F32; + float sleepVelocityFrameDecayConstant = 0.0f; + bool useHardSleeping = false; + for (uint32_t i = 0; i < actorObjDesc->mApexActors.size(); ++i) + { + DestructibleActorProxy* proxy = const_cast<DestructibleActorProxy*>(static_cast<const DestructibleActorProxy*>(actorObjDesc->mApexActors[i])); + if (proxy == NULL) + { + continue; + } + destructible = &proxy->impl; + const DestructibleParameters& parameters = destructible->getDestructibleParameters(); + PxVec3 islandPos; + { + SCOPED_PHYSX_LOCK_READ(entry.actor->getScene()); + islandPos = (entry.actor->getGlobalPose() * entry.actor->getCMassLocalPose()).p; + } + if (destructible->getParams()->deleteChunksLeavingUserDefinedBB) + { + const uint32_t bbc = mApexScene->getBoundingBoxCount(); + for(uint32_t i = 0; i < bbc; ++i) + { + if(mApexScene->getBoundingBoxFlags(i) & UserBoundingBoxFlags::LEAVE) + { + if(!mApexScene->getBoundingBox(i).contains(islandPos)) + { + reasonToDestroy = ApexChunkFlag::DESTROYED_LEFT_USER_BOUNDS; + break; + } + } + } + } + if (destructible->getParams()->deleteChunksEnteringUserDefinedBB) + { + const uint32_t bbc = mApexScene->getBoundingBoxCount(); + for(uint32_t i = 0; i < bbc; ++i) + { + if(mApexScene->getBoundingBoxFlags(i) & UserBoundingBoxFlags::ENTER) + { + if(mApexScene->getBoundingBox(i).contains(islandPos)) + { + reasonToDestroy = ApexChunkFlag::DESTROYED_ENTERED_USER_BOUNDS; + break; + } + } + } + } + if ((parameters.flags & DestructibleParametersFlag::USE_VALID_BOUNDS) != 0 && + !parameters.validBounds.contains(islandPos - destructible->getInitialGlobalPose().getPosition())) + { + reasonToDestroy = ApexChunkFlag::DESTROYED_LEFT_VALID_BOUNDS; + } + else if ((entry.flags & ActorFIFOEntry::ForceLODRemove) != 0) + { + reasonToDestroy = ApexChunkFlag::DESTROYED_FIFO_FULL; + } + else if ((entry.flags & ActorFIFOEntry::IsDebris) != 0) + { + // Check if too old or too far + if ((parameters.flags & DestructibleParametersFlag::DEBRIS_TIMEOUT) != 0 && + entry.age > (parameters.debrisLifetimeMax - parameters.debrisLifetimeMin)*mModule->m_maxChunkSeparationLOD + parameters.debrisLifetimeMin) + { + reasonToDestroy = ApexChunkFlag::DESTROYED_TIMED_OUT; + } + else if ((parameters.flags & DestructibleParametersFlag::DEBRIS_MAX_SEPARATION) != 0 && + (entry.origin - islandPos).magnitudeSquared() > + square((parameters.debrisMaxSeparationMax - parameters.debrisMaxSeparationMin)*mModule->m_maxChunkSeparationLOD + parameters.debrisMaxSeparationMin)) + { + reasonToDestroy = ApexChunkFlag::DESTROYED_EXCEEDED_MAX_DISTANCE; + } + } + if (reasonToDestroy) + { + destroyActorChunks(*entry.actor, reasonToDestroy); // places the actor on the kill list + entry.actor = NULL; + destructible->wakeForEvent(); + break; + } + if (parameters.maxChunkSpeed > 0.0f) + { + entry.maxSpeed = PxMin(entry.maxSpeed, parameters.maxChunkSpeed); + } + sleepVelocityFrameDecayConstant = PxMax(sleepVelocityFrameDecayConstant, destructible->getSleepVelocityFrameDecayConstant()); + useHardSleeping = useHardSleeping || destructible->useHardSleeping(); + } + if (reasonToDestroy) + { + continue; + } + // Smooth velocities and see if the actor should be put to sleep + if (sleepVelocityFrameDecayConstant > 1.0f) + { + // Create smoothed velocities + const float sleepVelocitySmoothingFactor = 1.0f-1.0f/sleepVelocityFrameDecayConstant; + const float sleepVelocitySmoothingFactorComplement = 1.0f-sleepVelocitySmoothingFactor; + const PxVec3 currentLinearVelocity = entry.actor->getLinearVelocity(); + const PxVec3 currentAngularVelocity = entry.actor->getAngularVelocity(); + if (!entry.actor->isSleeping()) + { + entry.averagedLinearVelocity = sleepVelocitySmoothingFactor*entry.averagedLinearVelocity + sleepVelocitySmoothingFactorComplement*currentLinearVelocity; + entry.averagedAngularVelocity = sleepVelocitySmoothingFactor*entry.averagedAngularVelocity + sleepVelocitySmoothingFactorComplement*currentAngularVelocity; + handleSleeping(entry.actor, entry.averagedLinearVelocity, entry.averagedAngularVelocity); + } + else + { + // Initialize smoothed velocity so that the actor may wake up again + entry.averagedLinearVelocity = mApexScene->getGravity(); + entry.averagedAngularVelocity = PxVec3(0.0f, 0.0f, PxTwoPi); + } + } + // Cap the linear velocity here + if (entry.maxSpeed < PX_MAX_F32) + { + const PxVec3 chunkVel = entry.actor->getLinearVelocity(); + const float chunkSpeed2 = chunkVel.magnitudeSquared(); + if (chunkSpeed2 > entry.maxSpeed * entry.maxSpeed) + { + entry.actor->setLinearVelocity((entry.maxSpeed * RecipSqrt(chunkSpeed2))*chunkVel); + } + } + if (actorObjDesc->userData == NULL) // Signals that shapes have changed, need to recalculate the mass properties + { + PX_ASSERT(destructible != NULL); + } + if (destructible != NULL) + { + entry.benefitCache += destructible->getBenefit() * (float)shapeCount / (float)PxMax<uint32_t>(destructible->getVisibleDynamicChunkShapeCount(), 1); + } + if ((entry.flags & ActorFIFOEntry::MassUpdateNeeded) != 0) + { + PX_ASSERT(entry.unscaledMass > 0.0f); + if (entry.unscaledMass > 0.0f) + { + physx::PxRigidBodyExt::setMassAndUpdateInertia(*entry.actor, scaleMass(entry.unscaledMass), NULL, false); + } + entry.flags &= ~(uint32_t)ActorFIFOEntry::MassUpdateNeeded; + } + if (useHardSleeping && entry.actor->isSleeping()) + { + bool isKinematic; + { + SCOPED_PHYSX_LOCK_READ(entry.actor->getScene()); + isKinematic = (entry.actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC); + } + if (!isKinematic) + { + { + entry.actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, true); + } + uint32_t dormantID = 0; + if (mDormantActors.useNextFree(dormantID)) + { + actorObjDesc->userData = (void*)~(uintptr_t)dormantID; + mDormantActors.direct(dormantID) = DormantActorEntry(entry.actor, entry.unscaledMass, entry.flags); + } + else + { + actorObjDesc->userData = NULL; + } + } + entry.actor = NULL; + continue; + } + if (mDynamicActorFIFONum != FIFOIndex) + { + actorObjDesc->userData = (void*)~(uintptr_t)mDynamicActorFIFONum; + mActorFIFO[mDynamicActorFIFONum] = entry; + } + ++mDynamicActorFIFONum; + } + else + { + schedulePxActorForDelete(*actorObjDesc); + entry.actor = NULL; + } + } + mActorFIFO.resize(mDynamicActorFIFONum); + + mElapsedTime += elapsedTime; + + + for (uint32_t structureNum = mStructureUpdateList.usedCount(); structureNum--;) + { + DestructibleStructure* structure = mStructureUpdateList.getUsed(structureNum); + structure->updateIslands(); + setStructureUpdate(structure, false); + } + + + for (uint32_t structureNum = mStressSolverTickList.usedCount(); structureNum--;) + { + DestructibleStructure* structure = mStressSolverTickList.getUsed(structureNum); + structure->tickStressSolver(elapsedTime); + } + + + switch (getRenderLockMode()) + { + case RenderLockMode::NO_RENDER_LOCK: + break; + case RenderLockMode::PER_MODULE_SCENE_RENDER_LOCK: + unlockModuleSceneRenderLock(); + break; + case RenderLockMode::PER_ACTOR_RENDER_LOCK: + default: + { + PX_PROFILE_ZONE("DestructibleBeforeTickLockRenderables", GetInternalApexSDK()->getContextId()); + for (uint32_t i = 0; i < mActorArray.size(); ++i) + { + mActorArray[i]->renderDataUnLock(); + } + } + break; + } + + for (uint32_t jointIndex = mDestructibleActorJointList.getSize(); jointIndex--;) + { + DestructibleActorJointProxy* jointProxy = + DYNAMIC_CAST(DestructibleActorJointProxy*)(mDestructibleActorJointList.getResource(jointIndex)); + PX_ASSERT(jointProxy != NULL); + if (jointProxy != NULL) + { + bool result = jointProxy->impl.updateJoint(); + if (!result) + { + jointProxy->release(); + } + } + } +#if APEX_RUNTIME_FRACTURE + fracture::SimScene* simScene = getDestructibleRTScene(false); + if (simScene != NULL) + { + simScene->preSim(elapsedTime); + } +#endif + + if (mApexScene->isFinalStep()) + { + if (mModule->m_chunkReport) + { + PX_PROFILE_ZONE("DestructibleChunkReport", GetInternalApexSDK()->getContextId()); + if (mModule->m_chunkStateEventCallbackSchedule == DestructibleCallbackSchedule::BeforeTick) + { + for (uint32_t actorWithChunkStateEventIndex = mActorsWithChunkStateEvents.size(); actorWithChunkStateEventIndex--;) + { + ChunkStateEventData data; + DestructibleActorImpl* dactor = mActorsWithChunkStateEvents[actorWithChunkStateEventIndex]; + data.destructible = dactor->getAPI(); + if (dactor->acquireChunkEventBuffer(data.stateEventList, data.stateEventListSize)) + { + mModule->m_chunkReport->onStateChangeNotify(data); + dactor->releaseChunkEventBuffer(); + } + } + //mActorsWithChunkStateEvents.clear(); + } + } + } + + // Update mUsingActiveTransforms, in case the user has changed it (PhysX3 only) +#if USE_ACTIVE_TRANSFORMS_FOR_AWAKE_LIST + SCOPED_PHYSX_LOCK_READ(mApexScene); + mUsingActiveTransforms = mPhysXScene != NULL && (mPhysXScene->getFlags() & PxSceneFlag::eENABLE_ACTIVETRANSFORMS); +#endif +} + +void DestructibleScene::setStructureSupportRebuild(DestructibleStructure* structure, bool rebuild) +{ + if (rebuild) + { + if (mStructureSupportRebuildList.use(structure->ID)) + { + mStructureSupportRebuildList.direct(structure->ID) = structure; + } + else + { + PX_ASSERT(mStructureSupportRebuildList.direct(structure->ID) == structure); + } + } + else + { + if (mStructureSupportRebuildList.free(structure->ID)) + { + mStructureSupportRebuildList.direct(structure->ID) = NULL; + } + else + { + PX_ASSERT(mStructureSupportRebuildList.direct(structure->ID) == NULL); + } + } +} + +void DestructibleScene::setStructureUpdate(DestructibleStructure* structure, bool update) +{ + if (update) + { + if (mStructureUpdateList.use(structure->ID)) + { + mStructureUpdateList.direct(structure->ID) = structure; + } + else + { + PX_ASSERT(mStructureUpdateList.direct(structure->ID) == structure); + } + } + else + { + if (mStructureUpdateList.free(structure->ID)) + { + mStructureUpdateList.direct(structure->ID) = NULL; + } + else + { + PX_ASSERT(mStructureUpdateList.direct(structure->ID) == NULL); + } + } +} + + +void DestructibleScene::setStressSolverTick(DestructibleStructure* structure, bool update) +{ + if (update) + { + if (mStressSolverTickList.use(structure->ID)) + { + mStressSolverTickList.direct(structure->ID) = structure; + } + else + { + PX_ASSERT(mStressSolverTickList.direct(structure->ID) == structure); + } + } + else + { + if (mStressSolverTickList.free(structure->ID)) + { + mStressSolverTickList.direct(structure->ID) = NULL; + } + else + { + PX_ASSERT(mStressSolverTickList.direct(structure->ID) == NULL); + } + } +} + + +void DestructibleScene::fetchResults() +{ + PX_PROFILE_ZONE("DestructibleFetchResults", GetInternalApexSDK()->getContextId()); + + // beforeTick() should have deleted all of the PxActors. It should be safe now to delete the Apex actors + // since there should be no more PhysXObjectDesc which reference this actor. + uint32_t apexActorKillIndex = mApexActorKillList.getSize(); + while (apexActorKillIndex--) + { + DestructibleActorProxy* proxy = DYNAMIC_CAST(DestructibleActorProxy*)(mApexActorKillList.getResource(apexActorKillIndex)); + PX_ASSERT(proxy); + delete proxy; + } + + { + PX_PROFILE_ZONE("DestructibleUpdateRenderMeshBonePoses", GetInternalApexSDK()->getContextId()); + + // Reset instanced mesh buffers + for (uint32_t i = 0; i < mInstancedActors.size(); ++i) + { + DestructibleActorImpl* actor = mInstancedActors[i]; + if (actor->m_listIndex == 0) + { + actor->getDestructibleAsset()->resetInstanceData(); + } + } + + //===SyncParams=== prepare user's chunk motion buffer, if available + UserChunkMotionHandler * callback = NULL; + callback = mModule->getSyncParams().getUserChunkMotionHandler(); + if(NULL != callback) + { + mSyncParams.onPreProcessReadData(*callback); + } + + for (uint32_t i = 0; i < mInstancedActors.size(); ++i) + { + DestructibleActorImpl* actor = mInstancedActors[i]; + actor->fillInstanceBuffers(); + } + + if (mUsingActiveTransforms) + { + // in AT mode, mAwakeActors is only used for temporarily storing actors that need update + // a frame history is kept to prevent wake/sleep event chatter + // TODO: update only the actually moving chunks. [APEX-670] + // with the current mechanism, all actor's chunks are updated regardless of active transforms + + SCOPED_PHYSX_LOCK_READ(mPhysXScene); + for (uint32_t clientNum = 0; clientNum < mSceneClientIDs.size(); ++clientNum) + { + uint32_t transformCount = 0; + const physx::PxActiveTransform* activeTransforms = mPhysXScene->getActiveTransforms(transformCount, mSceneClientIDs[clientNum]); + for (uint32_t i = 0; i < transformCount; ++i) + { + PhysXObjectDescIntl* actorObjDesc = (PhysXObjectDescIntl*)mModule->mSdk->getPhysXObjectInfo(activeTransforms[i].actor); + if (actorObjDesc != NULL) + { + for (uint32_t j = 0; j < actorObjDesc->mApexActors.size(); ++j) + { + DestructibleActorProxy* dActor = (DestructibleActorProxy*)actorObjDesc->mApexActors[j]; + if (dActor != NULL) + { + // ignore duplicate entries on purpose + if (dActor->impl.mActiveFrames == 0) // Hasn't been recorded as active yet + { + dActor->impl.incrementWakeCount(); + } + dActor->impl.mActiveFrames |= 1; // Record as active this frame + } + } + } +#if APEX_RUNTIME_FRACTURE + else + { + nvidia::fracture::SimScene* simScene = getDestructibleRTScene(false); + if (simScene != NULL) + { + physx::PxActor* actor = activeTransforms[i].actor; + if (actor != NULL) + { + physx::PxRigidDynamic* rigidDynamic = actor->is<physx::PxRigidDynamic>(); + if (rigidDynamic != NULL) + { + if (rigidDynamic->getNbShapes() > 0) + { + physx::PxShape* firstShape; + if (rigidDynamic->getShapes(&firstShape, 1, 0) && firstShape != NULL) + { + nvidia::fracture::Convex* convex = (nvidia::fracture::Convex*)simScene->findConvexForShape(*firstShape); + if (simScene->owns(*firstShape)) + { + nvidia::fracture::Compound* compound = (nvidia::fracture::Compound*)convex->getParent(); + // ignore duplicate entries on purpose + if (compound->getDestructibleActor()->mActiveFrames == 0) // Hasn't been recorded as active yet + { + compound->getDestructibleActor()->incrementWakeCount(); + } + compound->getDestructibleActor()->mActiveFrames |= 1; // Record as active this frame + } + } + } + } + } + } + } +#endif + } + } + } + + // Iterate backwards through mAwakeActors, since an IndexBank used-list may have entries freed during iteration (as a result of actor->decrementWakeCount() or actor->resetWakeForEvent()) + for (uint32_t awakeActorNum = mAwakeActors.usedCount(); awakeActorNum--;) + { + DestructibleActorImpl* actor = mDestructibles.direct(mAwakeActors.usedIndices()[awakeActorNum]); + if (mUsingActiveTransforms) + { + if (actor->mActiveFrames == 2) // Active last frame, not active this frame + { + actor->decrementWakeCount(); + if (actor->mAwakeActorCount == 0) + { + actor->mActiveFrames = 0; // The result of the skipped shift & mask, below + continue; + } + } + actor->mActiveFrames = (actor->mActiveFrames << 1) & 3; // Shift up and erase history past last frame + } + + updateActorPose(actor, callback); + actor->resetWakeForEvent(); + + if (actor->getNumVisibleChunks() == 0) + { + if (getModuleDestructible()->m_chunkReport != NULL) + { + if (getModuleDestructible()->m_chunkReport->releaseOnNoChunksVisible(actor->getAPI())) + { + destructibleActorKillList.pushBack(actor->getAPI()); + } + } + } + } + + //===SyncParams=== give the user the chunk motion buffer. chunk motion buffer must be fully populated and locked during this call + if(NULL != callback) + { + mSyncParams.onProcessWriteData(*callback); + } + + //===SyncParams=== done with user's chunk event motion, if available + if(NULL != callback) + { + mSyncParams.onPostProcessReadData(*callback); + } + callback = NULL; + + //===SyncParams=== allow user from changing sync params again. do this just after the last encounter of working with sync params in the program + PX_ASSERT(mSyncParams.lockSyncParams); + mSyncParams.lockSyncParams = false; + +#if 0 + /* Update bone boses in the render mesh, update world bounds */ + for (uint32_t i = 0 ; i < mAwakeActors.size() ; i++) + { + DestructibleActor* actor = DYNAMIC_CAST(DestructibleActor*)(mAwakeActors[ i ]); + if (actor->getStructure()) + { + actor->setRenderTMs(); + } + } +#endif + } + + if (mApexScene->isFinalStep()) + { + if (mModule->m_chunkReport) + { + PX_PROFILE_ZONE("DestructibleChunkReport", GetInternalApexSDK()->getContextId()); + + // Chunk damage reports + for (uint32_t reportNum = 0; reportNum < mDamageEventReportData.size(); ++reportNum) + { + ApexDamageEventReportDataImpl& data = mDamageEventReportData[reportNum]; + if (data.totalNumberOfFractureEvents > 0) + { + mModule->m_chunkReport->onDamageNotify(data); + } + data.clearChunkReports(); + ((DestructibleActorProxy*)data.destructible)->impl.mDamageEventReportIndex = 0xFFFFFFFF; + } + + // Chunk state notifies + if (mModule->m_chunkStateEventCallbackSchedule == DestructibleCallbackSchedule::FetchResults) + { + for (uint32_t actorWithChunkStateEventIndex = mActorsWithChunkStateEvents.size(); actorWithChunkStateEventIndex--;) + { + ChunkStateEventData data; + DestructibleActorImpl* dactor = mActorsWithChunkStateEvents[actorWithChunkStateEventIndex]; + data.destructible = dactor->getAPI(); + if (dactor->acquireChunkEventBuffer(data.stateEventList, data.stateEventListSize)) + { + mModule->m_chunkReport->onStateChangeNotify(data); + dactor->releaseChunkEventBuffer(); + } + } + //mActorsWithChunkStateEvents.clear(); + } + + // Destructible actor wake/sleep reports + if (mOnWakeActors.size()) + { + mModule->m_chunkReport->onDestructibleWake(&mOnWakeActors[0], mOnWakeActors.size()); + } + if (mOnSleepActors.size()) + { + mModule->m_chunkReport->onDestructibleSleep(&mOnSleepActors[0], mOnSleepActors.size()); + } + } + mDamageEventReportData.clear(); + mChunkReportHandles.clear(); + mOnWakeActors.clear(); + mOnSleepActors.clear(); + + // Kill destructibles on death row + for (uint32_t i = 0; i < destructibleActorKillList.size(); ++i) + { + if (destructibleActorKillList[i] != NULL) + { + destructibleActorKillList[i]->release(); + } + } + destructibleActorKillList.resize(0); + } + + if (mModule->m_impactDamageReport) + { + if (mImpactDamageEventData.size() != 0) + { + mModule->m_impactDamageReport->onImpactDamageNotify(&mImpactDamageEventData[0], mImpactDamageEventData.size()); + } + } + mImpactDamageEventData.clear(); + +#if 0 //dead code + // here all scenes have finished beforeTick for sure, so we know all the PxActors have been deleted + // TODO: can that happen: beforeTick, releaseActor, releaseAsset, fetchResults ? that would still cause a problem. + mModule->releaseBufferedConvexMeshes(); +#endif + +#if APEX_RUNTIME_FRACTURE + fracture::SimScene* simScene = getDestructibleRTScene(false); + if (simScene != NULL) + { + simScene->postSim(PX_MAX_F32); + } +#endif + + swapDamageBuffers(); +} + + +void DestructibleScene::visualize() +{ +#ifdef WITHOUT_DEBUG_VISUALIZE +#else + if (!mDestructibleDebugRenderParams->VISUALIZE_DESTRUCTIBLE_ACTOR) + { + return; + } + + using RENDER_DEBUG::DebugColors; + using RENDER_DEBUG::DebugRenderState; + // save the rendering state + const physx::PxMat44& savedPose = *RENDER_DEBUG_IFACE(mDebugRender)->getPoseTyped(); + RENDER_DEBUG_IFACE(mDebugRender)->setIdentityPose(); + RENDER_DEBUG_IFACE(mDebugRender)->pushRenderState(); + if (mDestructibleDebugRenderParams->VISUALIZE_DESTRUCTIBLE_BOUNDS > 0) + { + RENDER_DEBUG_IFACE(mDebugRender)->setCurrentColor(RENDER_DEBUG_IFACE(mDebugRender)->getDebugColor(DebugColors::Red)); + for (uint32_t i = 0 ; i < mActorArray.size() ; i++) + { + DestructibleActorImpl* actor = DYNAMIC_CAST(DestructibleActorImpl*)(mActorArray[ i ]); + PxBounds3 bounds = actor->getBounds(); + RENDER_DEBUG_IFACE(mDebugRender)->debugBound(bounds); + } + } + + if (mDestructibleDebugRenderParams->VISUALIZE_DESTRUCTIBLE_SUPPORT > 0) + { + for (uint32_t structureNum = 0; structureNum < mStructures.usedCount(); ++structureNum) + { + DestructibleStructure* structure = mStructures.getUsed(structureNum); + if (structure) + { + structure->visualizeSupport(mDebugRender); + } + } + } + + // debug visualization + for (uint32_t i = 0 ; i < mActorArray.size() ; i++) + { + DestructibleActorImpl* actor = DYNAMIC_CAST(DestructibleActorImpl*)(mActorArray[ i ]); + const uint16_t* visibleChunkIndexContainer = actor->getVisibleChunks(); + const uint32_t visibleChunkIndexCount = actor->getNumVisibleChunks(); + const PxVec3& eyePos = mApexScene->getEyePosition(); + + for (uint32_t chunkIndex = 0 ; chunkIndex < visibleChunkIndexCount; ++chunkIndex) + { + PxMat44 chunkPose(actor->getChunkPose(visibleChunkIndexContainer[chunkIndex])); + float disToEye = (-eyePos + chunkPose.getPosition()).magnitude(); + + if (visibleChunkIndexCount == 1 && visibleChunkIndexContainer[0] == 0) + { + // visualize actor pose + if (mDestructibleDebugRenderParams->VISUALIZE_DESTRUCTIBLE_ACTOR_POSE && + disToEye < mDestructibleDebugRenderParams->THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_POSE) + { + RENDER_DEBUG_IFACE(mDebugRender)->debugAxes(chunkPose, 1, 1); + } + + // visualize actor name + if (mDestructibleDebugRenderParams->VISUALIZE_DESTRUCTIBLE_ACTOR_NAME && + disToEye < mDestructibleDebugRenderParams->THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_NAME) + { + float shiftDistance = actor->getBounds().getExtents().magnitude(); + PxVec3 shiftDirection = -1 * mApexScene->getViewMatrix(0).column1.getXYZ(); + PxVec3 textLocation = chunkPose.getPosition() + (shiftDistance * shiftDirection); + + RENDER_DEBUG_IFACE(mDebugRender)->addToCurrentState(DebugRenderState::CameraFacing); + RENDER_DEBUG_IFACE(mDebugRender)->debugText(textLocation, "Destructible"); + RENDER_DEBUG_IFACE(mDebugRender)->removeFromCurrentState(DebugRenderState::CameraFacing); + } + } + else + { + // visualize actor pose (fragmented) + if (mDestructibleDebugRenderParams->VISUALIZE_DESTRUCTIBLE_FRAGMENT_POSE && + disToEye < mDestructibleDebugRenderParams->THRESHOLD_DISTANCE_DESTRUCTIBLE_FRAGMENT_POSE) + { +#if 0 + RENDER_DEBUG_IFACE(mDebugRender)->debugAxes(chunkPose, 0.5, 0.7); +#endif //lionel: todo: chunk pose is incorrect + } + } + } + } + + // visualize render mesh actor + for (uint32_t i = 0 ; i < mActorArray.size() ; i++) + { + DestructibleActorImpl* currentActor = NULL; + currentActor = DYNAMIC_CAST(DestructibleActorImpl*)(mActorArray[i]); + PX_ASSERT(currentActor != NULL); + + for (uint32_t meshTypeIndex = 0; meshTypeIndex < DestructibleActorMeshType::Count; ++meshTypeIndex) + { + const RenderMeshActorIntl* currentMeshActor = NULL; + currentMeshActor = static_cast<RenderMeshActorIntl*>(const_cast<RenderMeshActor*>(currentActor->getRenderMeshActor(static_cast<DestructibleActorMeshType::Enum>(meshTypeIndex)))); //lionel: const_cast bad! + if (NULL == currentMeshActor) + { + continue; + } + PX_ASSERT(mDebugRender != NULL); + currentMeshActor->visualize(*mDebugRender, mDebugRenderParams); + } + + // Instancing + if (currentActor->m_listIndex == 0) + { + for (uint32_t j = 0; j < currentActor->getDestructibleAsset()->m_instancedChunkRenderMeshActors.size(); ++j) + { + PX_ASSERT(j < currentActor->getDestructibleAsset()->m_chunkInstanceBufferData.size()); + if (currentActor->getDestructibleAsset()->m_instancedChunkRenderMeshActors[j] != NULL && currentActor->getDestructibleAsset()->m_chunkInstanceBufferData[j].size() > 0) + { + uint32_t count = currentActor->getDestructibleAsset()->m_chunkInstanceBufferData[j].size(); + PxMat33* scaledRotations = ¤tActor->getDestructibleAsset()->m_chunkInstanceBufferData[j][0].scaledRotation; + PxVec3* translations = ¤tActor->getDestructibleAsset()->m_chunkInstanceBufferData[j][0].translation; + + const RenderMeshActorIntl* currentMeshActor = NULL; + currentMeshActor = static_cast<RenderMeshActorIntl*>(const_cast<RenderMeshActor*>(currentActor->getDestructibleAsset()->m_instancedChunkRenderMeshActors[j])); + if (NULL == currentMeshActor) + { + continue; + } + PX_ASSERT(mDebugRender != NULL); + currentMeshActor->visualize(*mDebugRender, mDebugRenderParams, scaledRotations, translations, sizeof(DestructibleAssetImpl::ChunkInstanceBufferDataElement), count); + } + } + } + } + + // restore the rendering state + RENDER_DEBUG_IFACE(mDebugRender)->setPose(savedPose); + RENDER_DEBUG_IFACE(mDebugRender)->popRenderState(); +#endif +} + +// Private interface, used by Destructible* classes + +DestructibleActor* DestructibleScene::getDestructibleAndChunk(const PxShape* shape, int32_t* chunkIndex) const +{ + if (chunkIndex) + { + *chunkIndex = ModuleDestructibleConst::INVALID_CHUNK_INDEX; + } + + if (!mModule->owns(shape->getActor())) + { + return NULL; + } + + DestructibleStructure::Chunk* chunk = getChunk((const PxShape*)shape); + if (chunk == NULL) + { + return NULL; + } + + DestructibleActorImpl* destructible = mDestructibles.direct(chunk->destructibleID); + + if (destructible != NULL) + { + if (chunkIndex) + { + *chunkIndex = (int32_t)chunk->indexInAsset; + } + return destructible->getAPI(); + } + + return NULL; +} + +bool DestructibleScene::removeStructure(DestructibleStructure* structure, bool immediate) +{ + if (structure) + { + if (!immediate) + { + mStructureKillList.pushBack(structure); + } + else + { + for (uint32_t destructibleIndex = structure->destructibles.size(); destructibleIndex--;) + { + DestructibleActorImpl*& destructible = structure->destructibles[destructibleIndex]; + if (destructible) + { + destructible->setStructure(NULL); + mDestructibles.direct(destructible->getID()) = NULL; + mDestructibles.free(destructible->getID()); + destructible = NULL; + } + } + + setStructureUpdate(structure, false); + + mStructures.free(structure->ID); + mStructures.direct(structure->ID) = NULL; + delete structure; + } + return true; + } + + return false; +} + +void DestructibleScene::addActor(PhysXObjectDescIntl& desc, PxRigidDynamic& actor, float unscaledMass, bool isDebris) +{ + uintptr_t& cindex = (uintptr_t&)desc.userData; + + SCOPED_PHYSX_LOCK_READ(actor.getScene()); + + if (actor.getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC && cindex != 0) + { + // Remove from dormant list + const uint32_t index = (uint32_t)~cindex; + if (mDormantActors.free(index)) + { + mDormantActors.direct(index).actor = NULL; + } + cindex = 0; + } + + if (cindex != 0) + { + PX_ASSERT(!"Attempting to add an actor twice.\n"); + return; + } + + // Add to FIFO + cindex = ~(uintptr_t)mActorFIFO.size(); + uint32_t entryFlags = 0; + if (isDebris) + { + entryFlags |= ActorFIFOEntry::IsDebris; + } + mActorFIFO.pushBack(ActorFIFOEntry(&actor, unscaledMass, entryFlags)); + + // Initialize smoothed velocity so as not to get immediate sleeping + ActorFIFOEntry& fifoEntry = mActorFIFO.back(); + fifoEntry.averagedLinearVelocity = mApexScene->getGravity(); + fifoEntry.averagedAngularVelocity = PxVec3(0.0f, 0.0f, PxTwoPi); + + ++mDynamicActorFIFONum; +} + +void DestructibleScene::capDynamicActorCount() +{ + if ((mModule->m_dynamicActorFIFOMax > 0 || mModule->m_chunkFIFOMax > 0) && !mModule->m_sortByBenefit) + { + while (mDynamicActorFIFONum > 0 && ((mModule->m_dynamicActorFIFOMax > 0 && mDynamicActorFIFONum > mModule->m_dynamicActorFIFOMax) || + (mModule->m_chunkFIFOMax > 0 && mTotalChunkCount > mModule->m_chunkFIFOMax))) + { + ActorFIFOEntry& entry = mActorFIFO[mActorFIFO.size() - mDynamicActorFIFONum--]; + if (entry.actor != NULL) + { + destroyActorChunks(*entry.actor, ApexChunkFlag::DESTROYED_FIFO_FULL); + entry.actor = NULL; + } + } + } +} + +void DestructibleScene::removeReferencesToActor(DestructibleActorImpl& destructible) +{ + if (destructible.getStructure() == NULL) + { + return; + } + + mApexScene->lockRead(__FILE__, __LINE__); + + // Remove from FIFO or dormant list + const uint16_t* chunkIndexPtr = destructible.getVisibleChunks(); + const uint16_t* chunkIndexPtrStop = chunkIndexPtr + destructible.getNumVisibleChunks(); + while (chunkIndexPtr < chunkIndexPtrStop) + { + uint16_t chunkIndex = *chunkIndexPtr++; + DestructibleStructure::Chunk& chunk = destructible.getStructure()->chunks[chunkIndex + destructible.getFirstChunkIndex()]; + + PxRigidDynamic* actor = destructible.getStructure()->getChunkActor(chunk); + if (actor == NULL) + { + continue; + } + + if ((chunk.state & ChunkDynamic) != 0) + { + const PhysXObjectDesc* desc = mModule->mSdk->getPhysXObjectInfo(actor); + PX_ASSERT(desc != NULL); + + uint32_t index = ~(uint32_t)(uintptr_t)desc->userData; + + if (!(actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC)) + { + // find the entry in the fifo + if (index < mDynamicActorFIFONum) + { + mActorFIFO[index].actor = NULL; + } + } + else + { + // find the actor in the dormant list + if (mDormantActors.free(index)) + { + mDormantActors.direct(index).actor = NULL; + } + } + } + } + mApexScene->unlockRead(); + + destructible.setPhysXScene(NULL); + + destructible.removeSelfFromStructure(); + + uint32_t referencingActorCount; + PxRigidDynamic** referencingActors = NULL; + while((referencingActors = destructible.getReferencingActors(referencingActorCount)) != NULL) + { + PxRigidDynamic* actor = referencingActors[referencingActorCount - 1]; + PhysXObjectDescIntl* actorObjDesc = (PhysXObjectDescIntl*)mModule->mSdk->getPhysXObjectInfo(actor); + if (actorObjDesc != NULL) + { + for (uint32_t i = actorObjDesc->mApexActors.size(); i--;) + { + if (actorObjDesc->mApexActors[i] == destructible.getAPI()) + { + actorObjDesc->mApexActors.replaceWithLast(i); + } + } + } + destructible.unreferencedByActor(actor); + } + + // Remove from kill list + for (uint32_t killListIndex = mActorKillList.size(); killListIndex--;) + { + bool removeActorFromList = false; + PxRigidDynamic* killListActor = mActorKillList[killListIndex]; + if (killListActor != NULL) + { + PhysXObjectDescIntl* actorObjDesc = (PhysXObjectDescIntl*)mModule->mSdk->getPhysXObjectInfo(killListActor); + if (actorObjDesc != NULL) + { + for (uint32_t i = actorObjDesc->mApexActors.size(); i--;) + { + if (actorObjDesc->mApexActors[i] == destructible.getAPI()) + { + actorObjDesc->mApexActors.replaceWithLast(i); + destructible.unreferencedByActor(killListActor); + } + } + if (actorObjDesc->mApexActors.size() == 0) + { + releasePhysXActor(*killListActor); + removeActorFromList = true; + } + } + else + { + removeActorFromList = true; + } + } + else + { + removeActorFromList = true; + } + + if (removeActorFromList) + { + mActorKillList.replaceWithLast(killListIndex); + } + } + + PX_ASSERT(mDestructibles.usedCount() == 0 ? mActorKillList.size() == 0 : true); + + // Remove from damage and fracture buffers + for (RingBuffer<DamageEvent>::It i(getDamageReadBuffer()); i; ++i) + { + DamageEvent& e = *i; + if (e.destructibleID == destructible.getID()) + { + e.flags |= (uint32_t)DamageEvent::Invalid; + //e.destructibleID = (uint32_t)DestructibleStructure::InvalidID; + } + } + + for (RingBuffer<DamageEvent>::It i(getDamageWriteBuffer()); i; ++i) + { + DamageEvent& e = *i; + if (e.destructibleID == destructible.getID()) + { + e.flags |= (uint32_t)DamageEvent::Invalid; + //e.destructibleID = (uint32_t)DestructibleStructure::InvalidID; + } + } + + for (RingBuffer<FractureEvent>::It i(mFractureBuffer); i; ++i) + { + FractureEvent& e = *i; + if (e.destructibleID == destructible.getID() && e.chunkIndexInAsset < destructible.getDestructibleAsset()->getChunkCount()) + { + e.flags |= (uint32_t)FractureEvent::Invalid; + //e.destructibleID = (uint32_t)DestructibleStructure::InvalidID; + } + } + + for (RingBuffer<FractureEvent>::It i(mDeprioritisedFractureBuffer); i; ++i) + { + FractureEvent& e = *i; + if (e.destructibleID == destructible.getID() && e.chunkIndexInAsset < destructible.getDestructibleAsset()->getChunkCount()) + { + e.flags |= (uint32_t)FractureEvent::Invalid; + //e.destructibleID = (uint32_t)DestructibleStructure::InvalidID; + } + } + + // Remove from scene awake list + mAwakeActors.free(destructible.getID()); + + // Remove from instanced actors list, if it's in one + if (destructible.getDestructibleAsset()->mParams->chunkInstanceInfo.arraySizes[0] || destructible.getDestructibleAsset()->mParams->scatterMeshAssets.arraySizes[0]) + { + for (uint32_t i = 0; i < mInstancedActors.size(); ++i) + { + if (mInstancedActors[i] == &destructible) + { + mInstancedActors.replaceWithLast(i); + break; + } + } + } + + // Remove from damage report list + for (uint32_t damageReportIndex = 0; damageReportIndex < mDamageEventReportData.size(); ++damageReportIndex) + { + ApexDamageEventReportDataImpl& damageReport = mDamageEventReportData[damageReportIndex]; + if (damageReport.destructible == destructible.getAPI()) + { + damageReport.destructible = NULL; + damageReport.clearChunkReports(); + } + } + + // Remove from chunk state event list + for (uint32_t actorWithChunkStateEventIndex = mActorsWithChunkStateEvents.size(); actorWithChunkStateEventIndex--;) + { + if (mActorsWithChunkStateEvents[actorWithChunkStateEventIndex] == &destructible) + { + mActorsWithChunkStateEvents.replaceWithLast(actorWithChunkStateEventIndex); + } + } +} + +bool DestructibleScene::destroyActorChunks(PxRigidDynamic& actor, uint32_t chunkFlag) +{ + PhysXObjectDescIntl* actorObjDesc = (PhysXObjectDescIntl*) mModule->mSdk->getPhysXObjectInfo(&actor); + if (!actorObjDesc) + { + return false; + } + uintptr_t& cindex = (uintptr_t&)actorObjDesc->userData; + if (cindex == 0) + { + return false; + } + + SCOPED_PHYSX_LOCK_READ(actor.getScene()); + + // First collect a list of invariant destructible and chunk IDs + physx::Array<IntPair> chunks; + for (uint32_t i = actor.getNbShapes(); i--;) + { + PxShape* shape; + actor.getShapes(&shape, 1, i); + DestructibleStructure::Chunk* chunk = getChunk(shape); + PX_ASSERT(chunk != NULL); + if (chunk != NULL && chunk->isFirstShape(shape)) // BRG OPTIMIZE + { + getChunkReportData(*chunk, chunkFlag); + if (chunk->state & ChunkVisible) + { + IntPair chunkIDs; + chunkIDs.set((int32_t)chunk->destructibleID, (int32_t)chunk->indexInAsset); + chunks.pushBack(chunkIDs); + } + } + } + + // Now release the list of chunks + for (uint32_t i = 0; i < chunks.size(); ++i) + { + const IntPair& chunkIDs = chunks[i]; + DestructibleActorImpl* dactor = mDestructibles.direct((uint32_t)chunkIDs.i0); + if (dactor != NULL && dactor->getStructure() != NULL) + { + dactor->getStructure()->removeChunk(dactor->getStructure()->chunks[dactor->getFirstChunkIndex()+(uint16_t)chunkIDs.i1]); + dactor->getStructure()->removePxActorIslandReferences(actor); + if (dactor->getStructure()->actorForStaticChunks == &actor) + { + dactor->getStructure()->actorForStaticChunks = NULL; + } + } + } + + for (uint32_t i = actorObjDesc->mApexActors.size(); i--;) + { + const DestructibleActor* dActor = static_cast<const DestructibleActor*>(actorObjDesc->mApexActors[i]); + if (dActor != NULL) + { + ((DestructibleActorProxy*)dActor)->impl.unreferencedByActor(&actor); + } + } + + if (cindex != 0) // Destroying all associated chunks should have set this to 0, above + { + if (actor.getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC) + { + // Dormant actor + const uint32_t index = (uint32_t)~cindex; + if (mDormantActors.free(index)) + { + mDormantActors.direct(index).actor = NULL; + } + } + else + { + mActorFIFO[(uint32_t)~cindex].actor = NULL; + cindex = 0; + } + } + + schedulePxActorForDelete(*actorObjDesc); + return true; +} + +void DestructibleScene::releasePhysXActor(PxRigidDynamic& actor) +{ + PX_PROFILE_ZONE("DestructibleScene::releasePhysXActor", GetInternalApexSDK()->getContextId()); + + const HashMap<physx::PxActor*, uint32_t>::Entry* entry = mActorsToAddIndexMap.find(&actor); + if (entry != NULL) + { + uint32_t index = entry->second; + mActorsToAdd.replaceWithLast(index); + if (index < mActorsToAdd.size()) + { + mActorsToAddIndexMap[mActorsToAdd[index]] = index; + } + mActorsToAddIndexMap.erase(entry->first); + } + + // handle the case where an actor was given a force but then immediately released (not sure this is possible) + mForcesToAddToActorsMap.erase(&actor); + + { + SCOPED_PHYSX_LOCK_READ(actor.getScene()); + for (uint32_t shapeN = 0; shapeN < actor.getNbShapes(); ++shapeN) + { + PxShape* shape; + actor.getShapes(&shape, 1, shapeN); + PhysXObjectDescIntl* shapeObjDesc = (PhysXObjectDescIntl*)mModule->mSdk->getPhysXObjectInfo(shape); + if (shapeObjDesc != NULL) + { + DestructibleStructure::Chunk* chunk = (DestructibleStructure::Chunk*)shapeObjDesc->userData; + if (chunk != NULL) + { + // safety net if for any reason the chunk has not been disassociated from the shape + PX_ALWAYS_ASSERT(); + chunk->clearShapes(); + } + + mModule->mSdk->releaseObjectDesc(shape); + } + } + } + + for ( uint32_t damageReportIndex = 0; damageReportIndex < mDamageEventReportData.size(); ++damageReportIndex ) + { + ApexDamageEventReportDataImpl& damageReport = mDamageEventReportData[damageReportIndex]; + + if ( damageReport.impactDamageActor == &actor ) + { + damageReport.impactDamageActor = NULL; + } + } + + if (getModuleDestructible()->m_destructiblePhysXActorReport != NULL) + { + getModuleDestructible()->m_destructiblePhysXActorReport->onPhysXActorRelease(actor); + } + + + // make sure the actor is not referenced by any destructible + const PhysXObjectDescIntl* desc = static_cast<const PhysXObjectDescIntl*>(GetApexSDK()->getPhysXObjectInfo(&actor)); + if (desc != NULL) + { + const uint32_t dActorCount = desc->mApexActors.size(); + for (uint32_t i = 0; i < dActorCount; ++i) + { + const DestructibleActor* dActor = static_cast<const DestructibleActor*>(desc->mApexActors[i]); + if (dActor != NULL) + { + if (desc->mApexActors[i]->getOwner()->getObjTypeID() == DestructibleAssetImpl::getAssetTypeID()) + { + DestructibleActorImpl& destructibleActor = const_cast<DestructibleActorImpl&>(static_cast<const DestructibleActorProxy*>(dActor)->impl); + destructibleActor.unreferencedByActor(&actor); + } + } + } + } + + + mModule->mSdk->releaseObjectDesc(&actor); + SCOPED_PHYSX_LOCK_WRITE(actor.getScene()); + actor.release(); +} + +bool DestructibleScene::scheduleChunkShapesForDelete(DestructibleStructure::Chunk& chunk) +{ + DestructibleActorImpl* destructible = mDestructibles.direct(chunk.destructibleID); + + if ((chunk.state & ChunkVisible) == 0) + { +// PX_ASSERT(!"Cannot schedule shape for release from invisible chunk.\n"); + chunk.clearShapes(); + ChunkClearDescendents chunkOp(int32_t(chunk.indexInAsset + destructible->getFirstChunkIndex())); + forSubtree(chunk, chunkOp, true); + return true; + } + + if (chunk.isDestroyed()) + { + return false; + } + + PxRigidDynamic* actor = destructible->getStructure()->getChunkActor(chunk); + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + + PhysXObjectDescIntl* actorObjDesc = (PhysXObjectDescIntl*)mModule->mSdk->getPhysXObjectInfo(actor); + if (!actorObjDesc) + { + PX_ASSERT(!"Cannot schedule actor for release that is not owned by APEX.\n"); + return false; + } + bool owned = false; + for (uint32_t i = 0; i < actorObjDesc->mApexActors.size(); ++i) + { + if (actorObjDesc->mApexActors[i] && actorObjDesc->mApexActors[i]->getOwner()->getObjTypeID() == DestructibleAssetImpl::mAssetTypeID) + { + owned = true; + break; + } + } + if (!owned && actorObjDesc->mApexActors.size()) + { + PX_ASSERT(!"Cannot schedule actor for release that is not owned by this module.\n"); + return false; + } + +#if USE_DESTRUCTIBLE_RWLOCK + DestructibleScopedWriteLock destructibleWriteLock(*destructible); +#endif + + if (getRenderLockMode() == RenderLockMode::PER_ACTOR_RENDER_LOCK) + { + destructible->renderDataLock(); + } + +#if USE_CHUNK_RWLOCK + DestructibleStructure::ChunkScopedWriteLock chunkWriteLock(chunk); +#endif + + if (mTotalChunkCount > 0) + { + --mTotalChunkCount; + } + + physx::Array<PxShape*>& shapes = destructible->getStructure()->getChunkShapes(chunk); + for (uint32_t i = 0; i < shapes.size(); ++i) + { + PxShape* shape = shapes[i]; + + const PhysXObjectDescIntl* shapeObjDesc = (const PhysXObjectDescIntl*)mModule->mSdk->getPhysXObjectInfo(shape); + if (!shapeObjDesc) + { + PX_ASSERT(!"Cannot schedule object for release that is not owned by APEX.\n"); + continue; + } + + mModule->mSdk->releaseObjectDesc(shape); + SCOPED_PHYSX_LOCK_WRITE(mPhysXScene); + ((physx::PxRigidActor*)actor)->detachShape(*shape); + } + + if (mTotalChunkCount > 0) + { + --mTotalChunkCount; + } + + if (actor->getNbShapes() == 0) + { + PhysXObjectDescIntl* actorObjDesc = (PhysXObjectDescIntl*)mModule->mSdk->getPhysXObjectInfo(actor); + if (actorObjDesc != NULL) + { + for (uint32_t i = actorObjDesc->mApexActors.size(); i--;) + { + const DestructibleActor* dActor = static_cast<const DestructibleActor*>(actorObjDesc->mApexActors[i]); + actorObjDesc->mApexActors.replaceWithLast(i); + ((DestructibleActorProxy*)dActor)->impl.unreferencedByActor(actor); + } + } + destructible->unreferencedByActor(actor); + + if (actorObjDesc != NULL) + { + uintptr_t& cindex = (uintptr_t&)actorObjDesc->userData; + if (actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC) + { + if (cindex != 0) + { + // Dormant actor + const uint32_t index = (uint32_t)~cindex; + if (mDormantActors.free(index)) + { + mDormantActors.direct(index).actor = NULL; + } + } + destructible->getStructure()->removePxActorIslandReferences(*actor); + if (destructible->getStructure()->actorForStaticChunks == actor) + { + destructible->getStructure()->actorForStaticChunks = NULL; + } + schedulePxActorForDelete(*actorObjDesc); + } + else// if(0 != (uintptr_t&)actorObjDesc->userData) + { + PX_ASSERT(cindex != 0); + PX_ASSERT(mActorFIFO[(uint32_t)~cindex].actor == NULL || mActorFIFO[(uint32_t)~cindex].actor == actor); + cindex = 0; + } + } + } + else if (!(actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC)) + { + if (actor->getNbShapes() > 0) + { + const uintptr_t cindex = (uintptr_t)actorObjDesc->userData; + if (cindex != 0) + { + PX_ASSERT(mActorFIFO[(uint32_t)~cindex].actor == NULL || mActorFIFO[(uint32_t)~cindex].actor == actor); + ActorFIFOEntry& FIFOEntry = mActorFIFO[(uint32_t)~cindex]; + FIFOEntry.unscaledMass -= destructible->getChunkMass(chunk.indexInAsset); + if (FIFOEntry.unscaledMass <= 0.0f) + { + FIFOEntry.unscaledMass = 1.0f; // This should only occur if the last shape is deleted. In this case, the mass won't matter. + } + FIFOEntry.flags |= ActorFIFOEntry::MassUpdateNeeded; + } + } + } + chunk.clearShapes(); + ChunkClearDescendents chunkOp(int32_t(chunk.indexInAsset + destructible->getFirstChunkIndex())); + forSubtree(chunk, chunkOp, true); + + chunk.state &= ~(uint32_t)ChunkVisible; + + if (getRenderLockMode() == RenderLockMode::PER_ACTOR_RENDER_LOCK) + { + destructible->renderDataUnLock(); + } + + return true; +} + +bool DestructibleScene::schedulePxActorForDelete(PhysXObjectDescIntl& actorDesc) +{ + bool inScene = false; + bool isKinematic = false; + if (mPhysXScene) + { + mPhysXScene->lockRead(); + inScene = ((PxRigidDynamic*)actorDesc.mPhysXObject)->getScene() != NULL; + isKinematic = ((PxRigidDynamic*)actorDesc.mPhysXObject)->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC; + mPhysXScene->unlockRead(); + } + if (inScene && !isKinematic) + { + mPhysXScene->lockWrite(); + ((PxRigidDynamic*)actorDesc.mPhysXObject)->wakeUp(); + mPhysXScene->unlockWrite(); + } + PX_ASSERT(mActorKillList.find((PxRigidDynamic*)actorDesc.mPhysXObject) == mActorKillList.end()); + mActorKillList.pushBack((PxRigidDynamic*)actorDesc.mPhysXObject); + return true; +} + +void DestructibleScene::applyRadiusDamage(float damage, float momentum, const PxVec3& position, float radius, bool falloff) +{ + // Apply scene-based damage actor-based damage. Those will split off islands. + DamageEvent& damageEvent = getDamageWriteBuffer().pushFront(); + damageEvent.damage = damage; + damageEvent.momentum = momentum; + damageEvent.position = position; + damageEvent.direction = PxVec3(0.0f); // not used + damageEvent.radius = radius; + damageEvent.chunkIndexInAsset = ModuleDestructibleConst::INVALID_CHUNK_INDEX; + damageEvent.flags = DamageEvent::UseRadius; + if (falloff) + { + damageEvent.flags |= DamageEvent::HasFalloff; + } +} + + +bool DestructibleScene::isActorCreationRateExceeded() +{ + return mNumActorsCreatedThisFrame >= mModule->m_maxActorsCreateablePerFrame; +} + +bool DestructibleScene::isFractureBufferProcessRateExceeded() +{ + return mNumFracturesProcessedThisFrame >= mModule->m_maxFracturesProcessedPerFrame; +} + +void DestructibleScene::addToAwakeList(DestructibleActorImpl& actor) +{ + if (mAwakeActors.use(actor.getID())) + { + if (getModuleDestructible()->m_chunkReport != NULL) // Only use the list if there's a report + { + mOnWakeActors.pushBack(actor.getAPI()); + } + return; + } + + APEX_INTERNAL_ERROR("Destructible actor already present in awake actors list"); +} + +void DestructibleScene::removeFromAwakeList(DestructibleActorImpl& actor) +{ + + if (mAwakeActors.free(actor.getID())) + { + if (getModuleDestructible()->m_chunkReport != NULL) // Only use the list if there's a report + { + mOnSleepActors.pushBack(actor.getAPI()); + } + return; + } + + APEX_INTERNAL_ERROR("Destructible actor not found in awake actors list, size %d", mAwakeActors.usedCount()); +} + +bool DestructibleScene::setMassScaling(float massScale, float scaledMassExponent) +{ + if (massScale > 0.0f && scaledMassExponent > 0.0f && scaledMassExponent <= 1.0f) + { + mMassScale = massScale; + mMassScaleInv = 1.0f / mMassScale; + mScaledMassExponent = scaledMassExponent; + mScaledMassExponentInv = 1.0f / scaledMassExponent; + return true; + } + + return false; +} + +void DestructibleScene::invalidateBounds(const PxBounds3* bounds, uint32_t boundsCount) +{ + PX_ASSERT(bounds); + m_invalidBounds.reserve(m_invalidBounds.size() + boundsCount); + for (uint32_t i = 0; i < boundsCount; ++i) + { + m_invalidBounds.pushBack(bounds[i]); + } +} + +void DestructibleScene::setDamageApplicationRaycastFlags(nvidia::DestructibleActorRaycastFlags::Enum flags) +{ + m_damageApplicationRaycastFlags = flags; +} + + +void DestructibleScene::processFractureBuffer() +{ + PX_PROFILE_ZONE("DestructibleProcessFractureBuffer", GetInternalApexSDK()->getContextId()); + + // We need to use the render lock because the last frame's TMs are accessed in this method and in URR + bool freeSceneRenderLock = false; + if (mFractureBuffer.size() > 0 && getRenderLockMode() == RenderLockMode::PER_MODULE_SCENE_RENDER_LOCK) + { + lockModuleSceneRenderLock(); + freeSceneRenderLock = true; + } + + DestructibleActorImpl* lastDestructible = NULL; + for (; + (mFractureBuffer.size() > 0) && (!isFractureBufferProcessRateExceeded() && !isActorCreationRateExceeded()); + mFractureBuffer.popFront()) + { + FractureEvent& fractureEvent = mFractureBuffer.front(); + PX_ASSERT(0 == (FractureEvent::SyncDirect & fractureEvent.flags) && (0 == (FractureEvent::SyncDerived & fractureEvent.flags)) && (0 == (FractureEvent::Manual & fractureEvent.flags))); + + if (fractureEvent.flags & FractureEvent::Invalid) + { + continue; + } + + PX_ASSERT(fractureEvent.destructibleID < mDestructibles.capacity()); + DestructibleActorImpl* destructible = mDestructibles.direct(fractureEvent.destructibleID); + if (destructible && destructible->getStructure()) + { + if (destructible->mDamageEventReportIndex == 0xffffffff && mModule->m_chunkReport != NULL) + { + destructible->mDamageEventReportIndex = mDamageEventReportData.size(); + ApexDamageEventReportDataImpl& damageEventReport = mDamageEventReportData.insert(); + damageEventReport.setDestructible(destructible); + damageEventReport.hitDirection = fractureEvent.hitDirection; + damageEventReport.impactDamageActor = fractureEvent.impactDamageActor; + damageEventReport.hitPosition = fractureEvent.position; + damageEventReport.appliedDamageUserData = fractureEvent.appliedDamageUserData; + } + PX_ASSERT(mModule->m_chunkReport == NULL || destructible->mDamageEventReportIndex < mDamageEventReportData.size()); + + // Avoid cycling lock/unlock render lock on the same actor + if (getRenderLockMode() == RenderLockMode::PER_ACTOR_RENDER_LOCK && + destructible != lastDestructible) + { + if (lastDestructible != NULL) + { + lastDestructible->renderDataUnLock(); + } + destructible->renderDataLock(); + } + + destructible->getStructure()->fractureChunk(fractureEvent); + ++mNumFracturesProcessedThisFrame; + lastDestructible = destructible; + } + } + + if (freeSceneRenderLock && + getRenderLockMode() == RenderLockMode::PER_MODULE_SCENE_RENDER_LOCK) + { + unlockModuleSceneRenderLock(); + } + else if(lastDestructible != NULL && + getRenderLockMode() == RenderLockMode::PER_ACTOR_RENDER_LOCK) + { + lastDestructible->renderDataUnLock(); + } +} + + +void DestructibleScene::processFractureBuffer(const physx::Array<SyncParams::UserFractureEvent> * userSource) +{ + // if we still have pending local fractures, we push any new incoming fractures into the deprioritised fracture buffer + if(mFractureBuffer.size() > 0) + { + if(NULL != userSource) + { + for(physx::Array<SyncParams::UserFractureEvent>::ConstIterator iter = userSource->begin(); iter != userSource->end(); ++iter) + { + FractureEvent & fractureEvent = mSyncParams.interpret(*iter); + PX_ASSERT(mSyncParams.assertUserFractureEventOk(fractureEvent, *this)); + PX_ASSERT(0 == (FractureEvent::SyncDirect & fractureEvent.flags)); + fractureEvent.flags |= FractureEvent::SyncDirect; + mDeprioritisedFractureBuffer.pushBack() = fractureEvent; + } + } + } + // process deprioritised fractures only if local fractures have been processed, and any new incoming fractures only after clearing the backlog + else + { + // process fractures from the sync buffer +#define DEPRIORITISED_CONDITION (mDeprioritisedFractureBuffer.size() > 0) + PX_ASSERT(0 == mFractureBuffer.size()); + bool processingDeprioritised = true; + const uint32_t userSourceCount = (NULL != userSource) ? userSource->size() : 0; + uint32_t userSourceIndex = 0; + for (; + (DEPRIORITISED_CONDITION || (userSourceIndex < userSourceCount)) && (!isFractureBufferProcessRateExceeded() && !isActorCreationRateExceeded()); + processingDeprioritised ? mDeprioritisedFractureBuffer.popFront() : unfortunateCompilerWorkaround(++userSourceIndex)) + { + processingDeprioritised = DEPRIORITISED_CONDITION; +#undef DEPRIORITISED_CONDITION + FractureEvent & fractureEvent = processingDeprioritised ? mDeprioritisedFractureBuffer.front() : mSyncParams.interpret((*userSource)[userSourceIndex]); + PX_ASSERT(!processingDeprioritised ? mSyncParams.assertUserFractureEventOk(fractureEvent, *this) :true); + if(!processingDeprioritised) + { + PX_ASSERT(0 == (FractureEvent::SyncDirect & fractureEvent.flags)); + fractureEvent.flags |= FractureEvent::SyncDirect; + } + + const bool usingEditFeature = false; + if(usingEditFeature) + { + if(!processingDeprioritised) + { + const DestructibleActorImpl::SyncParams & actorParams = mDestructibles.direct(fractureEvent.destructibleID)->getSyncParams(); + mSyncParams.interceptEdit(fractureEvent, actorParams); + } + } + + if(0 != (FractureEvent::Invalid & fractureEvent.flags)) + { + continue; + } + + PX_ASSERT(fractureEvent.destructibleID < mDestructibles.capacity()); + DestructibleActorImpl * destructible = mDestructibles.direct(fractureEvent.destructibleID); + if(NULL != destructible && NULL != destructible->getStructure()) + { + // set damage event report data and fracture event chunk report data + if(0xFFFFFFFF == destructible->mDamageEventReportIndex && NULL != mModule->m_chunkReport) + { + destructible->mDamageEventReportIndex = mDamageEventReportData.size(); + ApexDamageEventReportDataImpl & damageEventReport = mDamageEventReportData.insert(); + damageEventReport.setDestructible(destructible); + damageEventReport.hitDirection = fractureEvent.hitDirection; + damageEventReport.appliedDamageUserData = fractureEvent.appliedDamageUserData; + } + + // perform the fracturing + destructible->getStructure()->fractureChunk(fractureEvent); + ++mNumFracturesProcessedThisFrame; + } + } + + // if we still have any incoming fractures unprocessed, we push them into the deprioritised fracture buffer + if(NULL != userSource ? userSourceIndex < userSourceCount : false) + { + for(; userSourceIndex < userSourceCount; ++userSourceIndex) + { + FractureEvent & fractureEvent = mSyncParams.interpret((*userSource)[userSourceIndex]); + PX_ASSERT(mSyncParams.assertUserFractureEventOk(fractureEvent, *this)); + PX_ASSERT(0 == (FractureEvent::SyncDirect & fractureEvent.flags)); + fractureEvent.flags |= FractureEvent::SyncDirect; + mDeprioritisedFractureBuffer.pushBack() = fractureEvent; + } + } + } + + // Move fracture event from Deferred fracture buffer to Deprioritised fracture buffer + if(mDeferredFractureBuffer.size() > 0) + { + mDeprioritisedFractureBuffer.reserve(mDeprioritisedFractureBuffer.size() + mDeferredFractureBuffer.size()); + do + { + mDeprioritisedFractureBuffer.pushBack() = mDeferredFractureBuffer.front(); + mDeferredFractureBuffer.popFront(); + } + while(mDeferredFractureBuffer.size() > 0); + } +} + +void DestructibleScene::processDamageColoringBuffer() +{ + for (; (mSyncDamageEventCoreDataBuffer.size() > 0) && (!isFractureBufferProcessRateExceeded() && !isActorCreationRateExceeded()); mSyncDamageEventCoreDataBuffer.popFront()) + { + SyncDamageEventCoreDataParams& syncDamageEventCoreDataParams = mSyncDamageEventCoreDataBuffer.front(); + + PX_ASSERT(syncDamageEventCoreDataParams.destructibleID < mDestructibles.capacity()); + DestructibleActorImpl * destructible = mDestructibles.direct(syncDamageEventCoreDataParams.destructibleID); + if (NULL != destructible && destructible->useDamageColoring()) + { + destructible->applyDamageColoring_immediate( syncDamageEventCoreDataParams.chunkIndexInAsset, + syncDamageEventCoreDataParams.position, + syncDamageEventCoreDataParams.damage, + syncDamageEventCoreDataParams.radius ); + } + } +} + + +void DestructibleScene::calculateDamageBufferCostProfiles(nvidia::RingBuffer<DamageEvent> & subjectDamageBuffer) +{ + physx::Array<uint8_t*> trail; + physx::Array<uint8_t> undo; + + for (RingBuffer<DamageEvent>::It i(subjectDamageBuffer); i; ++i) + { + DamageEvent& e = *i; + + if (e.flags & DamageEvent::Invalid) + { + continue; + } + + // Calculate costs and benefits for this event + float realCost = 0; + float realBenefit = 0; + for (uint32_t depth = 0; depth <= e.getMaxDepth(); ++depth) + { + float depthCost = realCost; // Cost & benefit at depth include only real events at lower depths + float depthBenefit = realBenefit; + physx::Array<FractureEvent>& fractures = e.fractures[depth]; + for (uint32_t j = 0; j < fractures.size(); ++j) + { + FractureEvent& fractureEvent = fractures[j]; + float eventCost = 0; + float eventBenefit = 0; + uint32_t oldTrailSize = trail.size(); + calculatePotentialCostAndBenefit(eventCost, eventBenefit, trail, undo, fractureEvent); + depthCost += eventCost; // Cost & benefit at depth include virtual events at this depth + depthBenefit += eventBenefit; + if ((fractureEvent.flags & FractureEvent::Virtual) == 0) + { + // Add real cost + realCost += eventCost; + realBenefit += eventBenefit; + } + else + { + // Undo chunk temporary state changes from virtual event + uint8_t** trailMark = trail.begin() + oldTrailSize; + uint8_t** trailEnd = trail.end(); + uint8_t* undoEnd = undo.end(); + while (trailEnd-- > trailMark) + { + PX_ASSERT(undoEnd > undo.begin()); + *(*trailEnd) = (uint8_t)(((**trailEnd)&~(uint8_t)ChunkTempMask) | (*--undoEnd)); + } + trail.resize((uint32_t)(trailMark - trail.begin())); + } + undo.reset(); + } + e.cost[depth] = depthCost; + e.benefit[depth] = depthBenefit; + } + + e.processDepth = e.getMaxDepth(); + + // Cover trail + for (uint8_t** statePtr = trail.begin(); statePtr < trail.end(); ++statePtr) + { + *(*statePtr) &= ~(uint8_t)ChunkTempMask; + } + trail.reset(); + } +} + + +void DestructibleScene::processEventBuffers() +{ + //===SyncParams=== prevent user from changing sync params during this phase. do this just before the first encounter of working with sync params in the program + //PX_ASSERT(!mSyncParams.lockSyncParams); + mSyncParams.lockSyncParams = true; + + //===SyncParams=== prepare user's damage event buffer, if available + UserDamageEventHandler * callback = NULL; + callback = mModule->getSyncParams().getUserDamageEventHandler(); + const physx::Array<SyncParams::UserDamageEvent> * userSource = NULL; + if(NULL != callback) + { + mSyncParams.onPreProcessReadData(*callback, userSource); + } + + //process damage buffer's damageEvents + nvidia::RingBuffer<DamageEvent> userDamageBuffer; + const nvidia::RingBuffer<DamageEvent> * const prePopulateAddress = &userDamageBuffer; + PX_ASSERT(0 == userDamageBuffer.size()); + generateFractureProfilesInDamageBuffer(userDamageBuffer, userSource); + PX_ASSERT((NULL != userSource) ? (0 != userDamageBuffer.size()) : (0 == userDamageBuffer.size())); + userSource = NULL; + const nvidia::RingBuffer<DamageEvent> * const postPopulateAddress = &userDamageBuffer; + PX_ASSERT(prePopulateAddress == postPopulateAddress); + PX_UNUSED(prePopulateAddress); + PX_UNUSED(postPopulateAddress); + + calculateDamageBufferCostProfiles(getDamageReadBuffer()); + + //===SyncParams=== + if(0 != userDamageBuffer.size()) + { + calculateDamageBufferCostProfiles(userDamageBuffer); + } + + //===SyncParams=== give the user the damage event buffer. damage event buffer must be fully populated and locked during this call + if(NULL != callback) + { + mSyncParams.onProcessWriteData(*callback, getDamageReadBuffer()); + } + + //pop damage buffer, push fracture buffer. note that local fracture buffer may be 'contaminated' with non-local fractureEvents, which are derivatives of the user's damageEvents + fillFractureBufferFromDamage((0 != userDamageBuffer.size()) ? &userDamageBuffer : NULL); + userDamageBuffer.clear(); + + //===SyncParams=== done with user's damage event buffer, if available + if(NULL != callback) + { + mSyncParams.onPostProcessReadData(*callback); + } + callback = NULL; +} + +void DestructibleScene::generateFractureProfilesInDamageBuffer(nvidia::RingBuffer<DamageEvent> & userDamageBuffer, const physx::Array<SyncParams::UserDamageEvent> * userSource /*= NULL*/) +{ + +#define LOCAL_CONDITION (eventN < getDamageReadBuffer().size()) + bool processingLocal = true; + for (uint32_t eventN = 0 , userEventN = 0, userEventCount = (NULL != userSource) ? userSource->size() : 0; + LOCAL_CONDITION || (userEventN < userEventCount); + processingLocal ? ++eventN : ++userEventN) + { + processingLocal = LOCAL_CONDITION; +#undef LOCAL_CONDITION + //===SyncParams=== + DamageEvent& damageEvent = processingLocal ? getDamageReadBuffer()[eventN] : mSyncParams.interpret((*userSource)[userEventN]); + PX_ASSERT(!processingLocal ? mSyncParams.assertUserDamageEventOk(damageEvent, *this) : true); + const bool usingEditFeature = false; + if(usingEditFeature) + { + if(!processingLocal) + { + const DestructibleActorImpl::SyncParams & actorParams = mDestructibles.direct(damageEvent.destructibleID)->getSyncParams(); + mSyncParams.interceptEdit(damageEvent, actorParams); + } + } + + for (uint32_t i = DamageEvent::MaxDepth + 1; i--;) + { + damageEvent.fractures[i].reset(); + } + + if (damageEvent.flags & DamageEvent::Invalid) + { + continue; + } + +#if APEX_RUNTIME_FRACTURE + if ((damageEvent.flags & DamageEvent::IsFromImpact) == 0) + { + // TODO: Remove this, and properly process the damage events + for (uint32_t i = 0; i < mDestructibles.usedCount(); ++i) + { + nvidia::fracture::Actor* rtActor = mDestructibles.getUsed(i)->getRTActor(); + if (rtActor != NULL && rtActor->patternFracture(damageEvent)) + { + break; + } + } + } +#endif + + if (damageEvent.destructibleID == (uint32_t)DestructibleActorImpl::InvalidID) + { + // Scene-based damage. Must find destructibles. + PxSphereGeometry sphere(damageEvent.radius); + + PxOverlapBuffer ovBuffer(&mOverlapHits[0], MAX_SHAPE_COUNT); + mPhysXScene->lockRead(); + mPhysXScene->overlap(sphere, PxTransform(damageEvent.position), ovBuffer); + uint32_t nbHits = ovBuffer.getNbAnyHits(); + //nbHits = nbHits >= 0 ? nbHits : MAX_SHAPE_COUNT; //Ivan: it is always true and should be removed + + if (nbHits) + { + qsort(&mOverlapHits[0], nbHits, sizeof(PxOverlapHit), compareOverlapHitShapePointers); + DestructibleActorImpl* lastDestructible = NULL; + for (uint32_t i = 0; i < nbHits; ++i) + { + DestructibleActorImpl* overlapDestructible = NULL; + DestructibleStructure::Chunk* chunk = getChunk((const PxShape*)mOverlapHits[i].shape); + if (chunk != NULL) + { + overlapDestructible = mDestructibles.direct(chunk->destructibleID); + } + + if (overlapDestructible != lastDestructible) + { + if (overlapDestructible->getStructure() != NULL) + { + // Expand damage buffer + DamageEvent& newEvent = processingLocal ? getDamageReadBuffer().pushBack() : userDamageBuffer.pushBack(); + newEvent = processingLocal ? getDamageReadBuffer()[eventN] : userDamageBuffer[userEventN]; // Need to use indexed access again; damageEvent may now be invalid if the buffer resized + newEvent.destructibleID = overlapDestructible->getID(); + const uint32_t maxLOD = overlapDestructible->getDestructibleAsset()->getDepthCount() > 0 ? overlapDestructible->getDestructibleAsset()->getDepthCount() - 1 : 0; + newEvent.minDepth = PxMin(overlapDestructible->getLOD(), maxLOD); + newEvent.maxDepth = damageEvent.minDepth; + } + lastDestructible = overlapDestructible; + } + } + } + + mPhysXScene->unlockRead(); + } + else + { + // Actor-based damage + DestructibleActorImpl* destructible = mDestructibles.direct(damageEvent.destructibleID); + if (destructible == NULL) + { + continue; + } + + if (getRenderLockMode() == RenderLockMode::PER_ACTOR_RENDER_LOCK) + { + destructible->renderDataLock(); + } + + if(!processingLocal) + { + PX_ASSERT(0 == (DamageEvent::SyncDirect & damageEvent.flags)); + damageEvent.flags |= DamageEvent::SyncDirect; + } + const uint32_t maxLOD = destructible->getDestructibleAsset()->getDepthCount() > 0 ? destructible->getDestructibleAsset()->getDepthCount() - 1 : 0; + damageEvent.minDepth = PxMin(destructible->getLOD(), maxLOD); + damageEvent.maxDepth = damageEvent.minDepth; + if ((damageEvent.flags & DamageEvent::UseRadius) == 0) + { + destructible->applyDamage_immediate(damageEvent); + } + else + { + destructible->applyRadiusDamage_immediate(damageEvent); + } + if (getRenderLockMode() == RenderLockMode::PER_ACTOR_RENDER_LOCK) + { + destructible->renderDataUnLock(); + } + } + + //===SyncParams=== + if(!processingLocal) + { + PX_ASSERT(0 != (DamageEvent::SyncDirect & damageEvent.flags)); + userDamageBuffer.pushBack() = damageEvent; + } + } +} + +void DestructibleScene::fillFractureBufferFromDamage(nvidia::RingBuffer<DamageEvent> * userDamageBuffer /*= NULL*/) +{ +#define LOCAL_CONDITION (getDamageReadBuffer().size() > 0) + bool processingLocal = true; + for (uint32_t userEventN = 0, userEventCount = (NULL != userDamageBuffer) ? userDamageBuffer->size() : 0; + LOCAL_CONDITION || (userEventN < userEventCount); + processingLocal ? getDamageReadBuffer().popFront() : unfortunateCompilerWorkaround(++userEventN)) + { + processingLocal = LOCAL_CONDITION; +#undef LOCAL_CONDITION + //===SyncParams=== + DamageEvent& damageEvent = processingLocal ? getDamageReadBuffer().front() : (*userDamageBuffer)[userEventN]; + + if (damageEvent.flags & DamageEvent::Invalid) + { + continue; + } + for (uint32_t depth = 0; depth <= damageEvent.getProcessDepth(); ++depth) + { + const bool atProcessDepth = depth == damageEvent.getProcessDepth(); + physx::Array<FractureEvent>& buffer = damageEvent.fractures[depth]; + for (uint32_t i = 0; i < buffer.size(); ++i) + { + FractureEvent& fractureEvent = buffer[i]; + if (atProcessDepth || (fractureEvent.flags & FractureEvent::Virtual) == 0) + { + fractureEvent.hitDirection = damageEvent.direction; + fractureEvent.impactDamageActor = damageEvent.impactDamageActor; + fractureEvent.position = damageEvent.position; + fractureEvent.appliedDamageUserData = damageEvent.appliedDamageUserData; + + //===SyncParams=== + PX_ASSERT(0 == (FractureEvent::DeleteChunk & fractureEvent.flags)); + if(mDestructibles.direct(damageEvent.destructibleID)->mInDeleteChunkMode) + { + fractureEvent.flags |= FractureEvent::DeleteChunk; + } + + if(!processingLocal) + { + PX_ASSERT(0 != (FractureEvent::SyncDerived & fractureEvent.flags)); + mDeprioritisedFractureBuffer.pushBack() = fractureEvent; + } + else + { + PX_ASSERT(0 == (FractureEvent::SyncDirect & fractureEvent.flags) && (0 == (FractureEvent::SyncDerived & fractureEvent.flags)) && (0 == (FractureEvent::Manual & fractureEvent.flags))); + mFractureBuffer.pushBack() = fractureEvent; + } + } + } + } + } +} + +static StatsInfo DestructionStatsData[] = +{ + {"VisibleDestructibleChunkCount", StatDataType::INT, {{0}} }, + {"DynamicDestructibleChunkIslandCount", StatDataType::INT, {{0}} }, + {"NumberOfShapes", StatDataType::INT, {{0}} }, + {"NumberOfAwakeShapes", StatDataType::INT, {{0}} }, + {"RbThroughput(Mpair/sec)", StatDataType::FLOAT, {{0}} }, +}; + +void DestructibleScene::createModuleStats(void) +{ + mModuleSceneStats.numApexStats = NumberOfStats; + mModuleSceneStats.ApexStatsInfoPtr = (StatsInfo*)PX_ALLOC(sizeof(StatsInfo) * NumberOfStats, PX_DEBUG_EXP("StatsInfo")); + + for (uint32_t i = 0; i < NumberOfStats; i++) + { + mModuleSceneStats.ApexStatsInfoPtr[i] = DestructionStatsData[i]; + } +} + +void DestructibleScene::destroyModuleStats(void) +{ + mModuleSceneStats.numApexStats = 0; + if (mModuleSceneStats.ApexStatsInfoPtr) + { + PX_FREE_AND_RESET(mModuleSceneStats.ApexStatsInfoPtr); + } +} + +void DestructibleScene::setStatValue(int32_t index, StatValue dataVal) +{ + if (mModuleSceneStats.ApexStatsInfoPtr) + { + mModuleSceneStats.ApexStatsInfoPtr[index].StatCurrentValue = dataVal; + } +} + +SceneStats* DestructibleScene::getStats() +{ + PX_PROFILE_ZONE("DestructibleScene::getStats", GetInternalApexSDK()->getContextId()); + { // CPU/GPU agnositic stats + unsigned totalVisibleChunkCount = 0; + unsigned totalDynamicIslandCount = 0; + for (unsigned i = 0; i < mStructures.usedCount(); ++i) + { + DestructibleStructure* s = mStructures.getUsed(i); + for (unsigned j = 0; j < s->destructibles.size(); ++j) + { + DestructibleActorImpl* a = s->destructibles[j]; + const unsigned visibleChunkCount = a->getNumVisibleChunks(); + totalVisibleChunkCount += visibleChunkCount; + physx::PxRigidDynamic** buffer; + unsigned bufferSize; + if (a->acquirePhysXActorBuffer(buffer, bufferSize, DestructiblePhysXActorQueryFlags::Dynamic)) + { + totalDynamicIslandCount += bufferSize; + a->releasePhysXActorBuffer(); + } + } + } + +#if 0 // Issue warnings if these don't align with updated values + if (mTotalChunkCount != totalVisibleChunkCount) + { + APEX_DEBUG_WARNING("mTotalChunkCount = %d, actual total visible chunk count = %d.\n", mTotalChunkCount, totalVisibleChunkCount); + } + if (mDynamicActorFIFONum != totalDynamicIslandCount) + { + APEX_DEBUG_WARNING("mDynamicActorFIFONum = %d, actual total dynamic chunk island count = %d.\n", mDynamicActorFIFONum, totalDynamicIslandCount); + } + if (mModule->m_chunkFIFOMax > 0 && mTotalChunkCount > mModule->m_chunkFIFOMax) + { + APEX_DEBUG_WARNING("mTotalChunkCount = %d, mModule->m_chunkFIFOMax = %d.\n", mTotalChunkCount, mModule->m_chunkFIFOMax); + } + if (mModule->m_dynamicActorFIFOMax > 0 && mDynamicActorFIFONum > mModule->m_dynamicActorFIFOMax) + { + APEX_DEBUG_WARNING("mDynamicActorFIFONum = %d, mModule->m_dynamicActorFIFOMax = %d.\n", mDynamicActorFIFONum, mModule->m_dynamicActorFIFOMax); + } +#endif + + StatValue dataVal; + + dataVal.Int = (int)totalVisibleChunkCount - mPreviousVisibleDestructibleChunkCount; + mPreviousVisibleDestructibleChunkCount = (int)totalVisibleChunkCount; + setStatValue(VisibleDestructibleChunkCount, dataVal); + + dataVal.Int = (int)totalDynamicIslandCount - mPreviousDynamicDestructibleChunkIslandCount; + mPreviousDynamicDestructibleChunkIslandCount = (int)totalDynamicIslandCount; + setStatValue(DynamicDestructibleChunkIslandCount, dataVal); + } + + { + StatValue dataVal; + dataVal.Int = 0; + setStatValue(NumberOfShapes, dataVal); + setStatValue(NumberOfAwakeShapes, dataVal); + setStatValue(RbThroughput, dataVal); + } + + return &mModuleSceneStats; +} + +/////////////////////////////////////////////////////////////////////////// + +bool DestructibleScene::ChunkLoadState::execute(DestructibleStructure* structure, DestructibleStructure::Chunk& chunk) +{ + DestructibleScene& scene = *structure->dscene; + DestructibleActorImpl& destructible = *scene.mDestructibles.direct(chunk.destructibleID); + + const uint16_t chunkIndex = chunk.indexInAsset; + const uint16_t parentIndex = destructible.getDestructibleAsset()->getChunkParentIndex(chunkIndex); + const bool chunkDynamic = destructible.getInitialChunkDynamic(chunkIndex); + const bool chunkVisible = destructible.getInitialChunkVisible(chunkIndex); + const bool chunkDestroyed = destructible.getInitialChunkDestroyed(chunkIndex); + bool chunkRecurse = true; + + // Destroy the chunk if necessary + if (chunkDestroyed && (!chunk.isDestroyed() || chunkVisible)) + { + structure->removeChunk(chunk); + structure->setSupportInvalid(true); + chunkRecurse = true; + } + // Create the chunk actor or append the chunk shapes to the island's actor + else if (chunkVisible && chunk.getShapeCount() == 0) + { + PxRigidDynamic* chunkActor = NULL; + bool chunkActorCreated = false; + + // Visible chunks not in an island require their own PxActor + if (chunk.islandID == (uint32_t)DestructibleStructure::InvalidID) + { + chunk.state &= ~(uint8_t)ChunkVisible; + chunkActor = scene.createRoot(chunk, destructible.getInitialChunkGlobalPose(chunkIndex), chunkDynamic, NULL, false); + chunkActorCreated = true; + } + else + { + // Check if the island actor has already been created + PxRigidDynamic* actor = NULL; + if (!chunkDynamic && structure->actorForStaticChunks != NULL) + { + actor = structure->actorForStaticChunks; + chunk.islandID = structure->actorToIsland[actor]; + } + else + { + actor = structure->islandToActor[chunk.islandID]; + } + if (NULL == actor) + { + // Create the island's actor + chunk.state &= ~(uint8_t)ChunkVisible; + actor = scene.createRoot(chunk, destructible.getInitialChunkGlobalPose(chunkIndex), chunkDynamic, NULL, false); + structure->islandToActor[chunk.islandID] = actor; + scene.setStructureUpdate(structure, true); // islandToActor needs to be cleared in DestructibleStructure::tick + if (!chunkDynamic) + { + structure->actorForStaticChunks = actor; + } + chunkActorCreated = true; + } + else + { + // Append the chunk shapes to the existing island actor + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + PxTransform relTM = actor->getGlobalPose().transformInv(destructible.getInitialChunkGlobalPose(chunkIndex)); + + chunk.state &= ~(uint8_t)ChunkVisible; + if (scene.appendShapes(chunk, chunkDynamic, &relTM, actor)) + { + PhysXObjectDescIntl* objDesc = scene.mModule->mSdk->getGenericPhysXObjectInfo(actor); + if(objDesc->mApexActors.find(destructible.getAPI()) == objDesc->mApexActors.end()) + { + objDesc->mApexActors.pushBack(destructible.getAPI()); + destructible.referencedByActor(actor); + } + } + } + chunkActor = actor; + } + + PX_ASSERT(!chunk.isDestroyed() && NULL != chunkActor); + if (!chunk.isDestroyed() && NULL != chunkActor) + { + // BRG - must decouple this now since we have "dormant" kinematic chunks + // which are chunks that have been freed but turned kinematic for "hard" sleeping +// PX_ASSERT(chunkDynamic != chunkActor->readBodyFlag(BF_KINEMATIC)); + + SCOPED_PHYSX_LOCK_WRITE(scene.mApexScene); + SCOPED_PHYSX_LOCK_READ(scene.mApexScene); + + destructible.setChunkVisibility(chunkIndex, true); + + // Only set shape local poses on newly created actors (appendShapes properly positions otherwise) + if (chunkActorCreated) + { + for (uint32_t i = 0; i < chunk.getShapeCount(); ++i) + { + chunk.getShape(i)->setLocalPose(destructible.getInitialChunkLocalPose(chunkIndex)); + } + } + + // Initialize velocities for newly created dynamic actors + if (chunkActorCreated && chunkDynamic) + { + chunkActor->setLinearVelocity( destructible.getInitialChunkLinearVelocity( chunkIndex)); + chunkActor->setAngularVelocity(destructible.getInitialChunkAngularVelocity(chunkIndex)); + } + + // Don't recurse visible chunks + chunkRecurse = false; + if (parentIndex != DestructibleAssetImpl::InvalidChunkIndex) + { + structure->chunks[parentIndex].flags |= ChunkMissingChild; + } + } + structure->setSupportInvalid(true); + } + + return chunkRecurse; +} + + +//////////////////////////////////////////////////////////////// +// PhysX3 dependent methods +//////////////////////////////////////////////////////////////// + +PxRigidDynamic* DestructibleScene::createRoot(DestructibleStructure::Chunk& chunk, const PxTransform& pose, bool dynamic, PxTransform* relTM, bool fromInitialData) +{ + // apan2 need verify 3.0 (createRoot) + PX_PROFILE_ZONE("DestructibleCreateRoot", GetInternalApexSDK()->getContextId()); + + DestructibleActorImpl* destructible = mDestructibles.direct(chunk.destructibleID); + + PxRigidDynamic* actor = NULL; + if (!chunk.isDestroyed()) + { + actor = destructible->getStructure()->getChunkActor(chunk); + } + + if ((chunk.state & ChunkVisible) != 0) + { + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + PhysXObjectDesc* actorObjDesc = (PhysXObjectDesc*)mModule->mSdk->getPhysXObjectInfo(actor); + PX_ASSERT(actor && actorObjDesc && actor->getNbShapes() >= 1); + if (destructible->getStructure()->chunkIsSolitary(chunk)) + { + bool actorIsDynamic = (chunk.state & ChunkDynamic) != 0; + if (dynamic == actorIsDynamic) + { + return actor; // nothing to do + } + if (!dynamic) + { + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + actor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); + actorObjDesc->userData = NULL; + return actor; + } +#if 0 // XXX \todo: why doesn't this work? + else + { + actor->clearBodyFlag(BF_KINEMATIC); + addActor(*actorDesc, *actor); + return; + } +#endif + } + scheduleChunkShapesForDelete(chunk); + } + + const uint32_t firstHullIndex = destructible->getDestructibleAsset()->getChunkHullIndexStart(chunk.indexInAsset); + const uint32_t hullCount = destructible->getDestructibleAsset()->getChunkHullIndexStop(chunk.indexInAsset) - firstHullIndex; + PxConvexMeshGeometry* convexShapeDescs = (PxConvexMeshGeometry*)PxAlloca(sizeof(PxConvexMeshGeometry) * hullCount); + + DestructibleAssetParametersNS::Chunk_Type* source = destructible->getDestructibleAsset()->mParams->chunks.buf + chunk.indexInAsset; + + // Whether or not this chunk can be damaged by an impact + const bool takesImpactDamage = destructible->takesImpactDamageAtDepth(source->depth); + + // Get user-defined descriptors, modify as needed + + // Create a new actor + PhysX3DescTemplateImpl physX3Template; + destructible->getPhysX3Template(physX3Template); + + const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = destructible->getBehaviorGroup(chunk.indexInAsset); + + PxRigidDynamic* newActor = NULL; + PxTransform poseActor(pose); + if (!fromInitialData) + poseActor.p -= poseActor.rotate(destructible->getDestructibleAsset()->getChunkPositionOffset(chunk.indexInAsset)); + + poseActor.q.normalize(); + + newActor = mPhysXScene->getPhysics().createRigidDynamic(poseActor); + + PX_ASSERT(newActor && "creating actor failed"); + if (!newActor) + return NULL; + + physX3Template.apply(newActor); + + if (dynamic && destructible->getDestructibleParameters().dynamicChunksDominanceGroup < 32) + { + newActor->setDominanceGroup(destructible->getDestructibleParameters().dynamicChunksDominanceGroup); + } + + newActor->setActorFlag(PxActorFlag::eSEND_SLEEP_NOTIFIES, true); + newActor->setMaxDepenetrationVelocity(behaviorGroup.maxDepenetrationVelocity); + + // Shape(s): + for (uint32_t hullIndex = 0; hullIndex < hullCount; ++hullIndex) + { + PxConvexMeshGeometry& convexShapeDesc = convexShapeDescs[hullIndex]; + PX_PLACEMENT_NEW(&convexShapeDesc, PxConvexMeshGeometry); + convexShapeDesc.convexMesh = destructible->getConvexMesh(hullIndex + firstHullIndex); + PX_ASSERT(convexShapeDesc.convexMesh != NULL); + convexShapeDesc.scale.scale = destructible->getScale(); + // Divide out the cooking scale to get the proper scaling + const PxVec3 cookingScale = getModuleDestructible()->getChunkCollisionHullCookingScale(); + convexShapeDesc.scale.scale.x /= cookingScale.x; + convexShapeDesc.scale.scale.y /= cookingScale.y; + convexShapeDesc.scale.scale.z /= cookingScale.z; + if ((convexShapeDesc.scale.scale - PxVec3(1.0f)).abs().maxElement() < 10 * PX_EPS_F32) + { + convexShapeDesc.scale.scale = PxVec3(1.0f); + } + + PxShape* shape; + + PxTransform localPose; + if (relTM != NULL) + { + localPose = *relTM; + localPose.p += destructible->getScale().multiply(destructible->getDestructibleAsset()->getChunkPositionOffset(chunk.indexInAsset)); + } + else + { + localPose = PxTransform(destructible->getDestructibleAsset()->getChunkPositionOffset(chunk.indexInAsset)); + } + + shape = newActor->createShape(convexShapeDesc, + physX3Template.materials.begin(), + static_cast<uint16_t>(physX3Template.materials.size()), + static_cast<physx::PxShapeFlags>(physX3Template.shapeFlags)); + PX_ASSERT(shape); + if (!shape) + { + APEX_INTERNAL_ERROR("Failed to create the PhysX shape."); + return NULL; + } + shape->setLocalPose(localPose); + physX3Template.apply(shape); + + if (behaviorGroup.groupsMask.useGroupsMask) + { + physx::PxFilterData filterData(behaviorGroup.groupsMask.bits0, + behaviorGroup.groupsMask.bits1, + behaviorGroup.groupsMask.bits2, + behaviorGroup.groupsMask.bits3); + shape->setSimulationFilterData(filterData); + shape->setQueryFilterData(filterData); + } + else if (dynamic && destructible->getDestructibleParameters().useDynamicChunksGroupsMask) + { + // Override the filter data + shape->setSimulationFilterData(destructible->getDestructibleParameters().dynamicChunksFilterData); + shape->setQueryFilterData(destructible->getDestructibleParameters().dynamicChunksFilterData); + } + + // apan2 + physx::PxPairFlags pairFlag = (physx::PxPairFlags)physX3Template.contactReportFlags; + if (takesImpactDamage) + { + pairFlag /* |= PxPairFlag::eNOTIFY_CONTACT_FORCES */ + |= PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS + | PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND + | PxPairFlag::eNOTIFY_CONTACT_POINTS; + + } + + if (behaviorGroup.materialStrength > 0.0f) + { + pairFlag |= PxPairFlag::eMODIFY_CONTACTS; + } + + if (mApexScene->getApexPhysX3Interface()) + mApexScene->getApexPhysX3Interface()->setContactReportFlags(shape, pairFlag, destructible->getAPI(), chunk.indexInAsset); + + } + + // Calculate mass + const float actorMass = destructible->getChunkMass(chunk.indexInAsset); + const float scaledMass = scaleMass(actorMass); + + if (!dynamic) + { + // Make kinematic if the chunk is not dynamic + newActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); + } + else + { + newActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, false); + } + + if (takesImpactDamage) + { + // Set contact report threshold if the actor can take impact damage + newActor->setContactReportThreshold(destructible->getContactReportThreshold(behaviorGroup)); + } + + // Actor: + if (takesImpactDamage && behaviorGroup.materialStrength > 0.0f) + { + newActor->setContactReportThreshold(behaviorGroup.materialStrength); + } + + if (newActor) + { + // apan2 + // bodyDesc.apply(newActor); + PxRigidBodyExt::setMassAndUpdateInertia(*newActor, scaledMass); + newActor->setAngularDamping(0.05f); + + ++mNumActorsCreatedThisFrame; + ++mTotalChunkCount; + + PhysXObjectDescIntl* actorObjDesc = mModule->mSdk->createObjectDesc(destructible->getAPI(), newActor); + actorObjDesc->userData = 0; + destructible->setActorObjDescFlags(actorObjDesc, source->depth); + + if (!(newActor->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)) + { + bool isDebris = destructible->getDestructibleParameters().debrisDepth >= 0 + && source->depth >= destructible->getDestructibleParameters().debrisDepth; + addActor(*actorObjDesc, *newActor, actorMass, isDebris); + } + + // Set the PxShape for the chunk and all descendants + const uint32_t shapeCount = newActor->getNbShapes(); + PX_ALLOCA(shapeArray, physx::PxShape*, shapeCount); + newActor->getShapes(shapeArray, shapeCount); + + chunk.setShapes(shapeArray, shapeCount); + chunk.state |= (uint32_t)ChunkVisible; + if (dynamic) + { + chunk.state |= (uint32_t)ChunkDynamic; + // New visible dynamic chunk, add to visible dynamic chunk shape counts + destructible->increaseVisibleDynamicChunkShapeCount(hullCount); + if (source->depth <= destructible->getDestructibleParameters().essentialDepth) + { + destructible->increaseEssentialVisibleDynamicChunkShapeCount(hullCount); + } + } + + // Create and store an island ID for the root actor + if (actor != NULL || chunk.islandID == DestructibleStructure::InvalidID) + { + chunk.islandID = destructible->getStructure()->newPxActorIslandReference(chunk, *newActor); + } + + VisibleChunkSetDescendents chunkOp(chunk.indexInAsset + destructible->getFirstChunkIndex(), dynamic); + forSubtree(chunk, chunkOp, true); + + physx::Array<PxShape*>& shapes = destructible->getStructure()->getChunkShapes(chunk); + for (uint32_t i = shapes.size(); i--;) + { + PxShape* shape = shapes[i]; + PhysXObjectDescIntl* shapeObjDesc = mModule->mSdk->createObjectDesc(destructible->getAPI(), shape); + shapeObjDesc->userData = &chunk; + } + + { + mActorsToAddIndexMap[newActor] = mActorsToAdd.size(); + mActorsToAdd.pushBack(newActor); + + // TODO do we really need this? + SCOPED_PHYSX_LOCK_WRITE(mPhysXScene); + if (!(newActor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC)) // cannot call 'wake-up' on kinematic bodies + { + float initWakeCounter = mPhysXScene->getWakeCounterResetValue(); + newActor->setWakeCounter(initWakeCounter); + } + } + + destructible->referencedByActor(newActor); // Must be done after adding to scene, since sleeping is checked + } + + // Add to static root list if static + if (!dynamic) + { + destructible->getStaticRoots().use(chunk.indexInAsset); + } + + if (newActor && getModuleDestructible()->m_destructiblePhysXActorReport != NULL) + { + getModuleDestructible()->m_destructiblePhysXActorReport->onPhysXActorCreate(*newActor); + } + + return newActor; +} + +void DestructibleScene::addForceToAddActorsMap(physx::PxActor* actor, const ActorForceAtPosition& force) +{ + mForcesToAddToActorsMap[actor] = force; +} + +void DestructibleScene::addActorsToScene() +{ + PX_PROFILE_ZONE("DestructibleAddActorsToScene", GetInternalApexSDK()->getContextId()); + + if (mActorsToAdd.empty() || mPhysXScene == NULL) + return; + + { + SCOPED_PHYSX_LOCK_WRITE(mPhysXScene); + mPhysXScene->addActors(&mActorsToAdd[0], mActorsToAdd.size()); + + { + PX_PROFILE_ZONE("DestructibleAddForcesToNewSceneActors", GetInternalApexSDK()->getContextId()); + for (HashMap<physx::PxActor*, ActorForceAtPosition>::Iterator iter = mForcesToAddToActorsMap.getIterator(); !iter.done(); iter++) + { + PxActor* const actor = iter->first; + ActorForceAtPosition& forceToAdd = iter->second; + if (actor->getScene()) + { + PxRigidDynamic* rigidDynamic = actor->is<physx::PxRigidDynamic>(); + if (rigidDynamic && !(rigidDynamic->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC)) + { + if (!forceToAdd.force.isZero()) + { + PxRigidBody* rigidBody = actor->is<physx::PxRigidBody>(); + if (rigidBody) + { + if (forceToAdd.usePosition) + { + PxRigidBodyExt::addForceAtPos(*rigidBody, forceToAdd.force, forceToAdd.pos, forceToAdd.mode, forceToAdd.wakeup); + } + else + { + rigidBody->addForce(forceToAdd.force, forceToAdd.mode, forceToAdd.wakeup); + } + } + } + else + { + // No force, but we will apply the wakeup flag + if (forceToAdd.wakeup) + { + rigidDynamic->wakeUp(); + } + else + { + rigidDynamic->putToSleep(); + } + } + } + } + } + mForcesToAddToActorsMap.clear(); + } + } + + mActorsToAdd.clear(); + mActorsToAddIndexMap.clear(); +} + + +bool DestructibleScene::appendShapes(DestructibleStructure::Chunk& chunk, bool dynamic, PxTransform* relTM, PxRigidDynamic* actor) +{ + // PX_PROFILE_ZONE(DestructibleAppendShape, GetInternalApexSDK()->getContextId()); + + if (chunk.state & ChunkVisible) + { + return true; + } + + if (chunk.isDestroyed() && actor == NULL) + { + return false; + } + + DestructibleActorImpl* destructible = mDestructibles.direct(chunk.destructibleID); + + if (actor == NULL) + { + actor = destructible->getStructure()->getChunkActor(chunk); + relTM = NULL; + } + + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + const uint32_t oldActorShapeCount = actor->getNbShapes(); + + PhysX3DescTemplateImpl physX3Template; + + destructible->getPhysX3Template(physX3Template); + + DestructibleAssetParametersNS::Chunk_Type* source = destructible->getDestructibleAsset()->mParams->chunks.buf + chunk.indexInAsset; + const bool takesImpactDamage = destructible->takesImpactDamageAtDepth(source->depth); + + // Shape(s): + for (uint32_t hullIndex = destructible->getDestructibleAsset()->getChunkHullIndexStart(chunk.indexInAsset); hullIndex < destructible->getDestructibleAsset()->getChunkHullIndexStop(chunk.indexInAsset); ++hullIndex) + { + PxConvexMeshGeometry convexShapeDesc; + convexShapeDesc.convexMesh = destructible->getConvexMesh(hullIndex); + // Make sure we can get a collision mesh + if (!convexShapeDesc.convexMesh) + { + return false; + } + convexShapeDesc.scale.scale = destructible->getScale(); + // Divide out the cooking scale to get the proper scaling + const PxVec3 cookingScale = getModuleDestructible()->getChunkCollisionHullCookingScale(); + convexShapeDesc.scale.scale.x /= cookingScale.x; + convexShapeDesc.scale.scale.y /= cookingScale.y; + convexShapeDesc.scale.scale.z /= cookingScale.z; + if ((convexShapeDesc.scale.scale - PxVec3(1.0f)).abs().maxElement() < 10 * PX_EPS_F32) + { + convexShapeDesc.scale.scale = PxVec3(1.0f); + } + + PxTransform localPose; + if (relTM != NULL) + { + localPose = *relTM; + localPose.p += destructible->getScale().multiply(destructible->getDestructibleAsset()->getChunkPositionOffset(chunk.indexInAsset)); + } + else + { + localPose = destructible->getStructure()->getChunkLocalPose(chunk); + } + + PxShape* newShape = NULL; + + { + { + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + newShape = actor->createShape(convexShapeDesc, + physX3Template.materials.begin(), + static_cast<uint16_t>(physX3Template.materials.size()), + static_cast<physx::PxShapeFlags>(physX3Template.shapeFlags)); + newShape->setLocalPose(localPose); + + PX_ASSERT(newShape); + if (!newShape) + { + APEX_INTERNAL_ERROR("Failed to create the PhysX shape."); + return false; + } + physX3Template.apply(newShape); + } + + const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = destructible->getBehaviorGroup(chunk.indexInAsset); + if (behaviorGroup.groupsMask.useGroupsMask) + { + physx::PxFilterData filterData(behaviorGroup.groupsMask.bits0, + behaviorGroup.groupsMask.bits1, + behaviorGroup.groupsMask.bits2, + behaviorGroup.groupsMask.bits3); + newShape->setSimulationFilterData(filterData); + newShape->setQueryFilterData(filterData); + } + else if (dynamic && destructible->getDestructibleParameters().useDynamicChunksGroupsMask) + { + // Override the filter data + newShape->setSimulationFilterData(destructible->getDestructibleParameters().dynamicChunksFilterData); + newShape->setQueryFilterData(destructible->getDestructibleParameters().dynamicChunksFilterData); + } + + physx::PxPairFlags pairFlag = (physx::PxPairFlags)physX3Template.contactReportFlags; + + if (takesImpactDamage) + { + pairFlag /* |= PxPairFlag::eNOTIFY_CONTACT_FORCES */ + |= PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS + | PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND + | PxPairFlag::eNOTIFY_CONTACT_POINTS; + } + + if (behaviorGroup.materialStrength > 0.0f) + { + pairFlag |= PxPairFlag::eMODIFY_CONTACTS; + } + + if (mApexScene->getApexPhysX3Interface()) + mApexScene->getApexPhysX3Interface()->setContactReportFlags(newShape, pairFlag, destructible->getAPI(), chunk.indexInAsset); + } + + PhysXObjectDescIntl* shapeObjDesc = mModule->mSdk->createObjectDesc(destructible->getAPI(), newShape); + shapeObjDesc->userData = &chunk; + } + + ++mTotalChunkCount; + chunk.state |= (uint8_t)ChunkVisible; + if (dynamic) + { + chunk.state |= (uint8_t)ChunkDynamic; + // New visible dynamic chunk, add to visible dynamic chunk shape counts + const uint32_t hullCount = destructible->getDestructibleAsset()->getChunkHullCount(chunk.indexInAsset); + destructible->increaseVisibleDynamicChunkShapeCount(hullCount); + if (destructible->getDestructibleAsset()->mParams->chunks.buf[chunk.indexInAsset].depth <= destructible->getDestructibleParameters().essentialDepth) + { + destructible->increaseEssentialVisibleDynamicChunkShapeCount(hullCount); + } + } + + // Retrieve the island ID associated with the parent PxActor + chunk.islandID = destructible->getStructure()->actorToIsland[actor]; + + const uint32_t shapeCount = actor->getNbShapes(); + PX_ALLOCA(shapeArray, physx::PxShape*, shapeCount); + { + actor->getShapes(shapeArray, shapeCount); + } + + chunk.setShapes(shapeArray + oldActorShapeCount, shapeCount - oldActorShapeCount); + VisibleChunkSetDescendents chunkOp(chunk.indexInAsset + destructible->getFirstChunkIndex(), dynamic); + forSubtree(chunk, chunkOp, true); + + // Update the mass + { + PhysXObjectDescIntl* actorObjDesc = (PhysXObjectDescIntl*)mModule->mSdk->getPhysXObjectInfo(actor); + const uintptr_t cindex = (uintptr_t)actorObjDesc->userData; + if (cindex != 0) + { + // In the FIFO, trigger mass update + PX_ASSERT(mActorFIFO[(uint32_t)~cindex].actor == actor); + ActorFIFOEntry& FIFOEntry = mActorFIFO[(uint32_t)~cindex]; + FIFOEntry.unscaledMass += destructible->getChunkMass(chunk.indexInAsset); + bool isKinematic = false; + { + isKinematic = actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC; + } + if (!isKinematic) + { + FIFOEntry.flags |= ActorFIFOEntry::MassUpdateNeeded; + } + } + } + + if ((chunk.state & ChunkDynamic) == 0) + { + destructible->getStaticRoots().use(chunk.indexInAsset); + } + + return true; +} + +bool DestructibleScene::testWorldOverlap(const ConvexHullImpl& convexHull, const PxTransform& tm, const PxVec3& scale, float padding, const PxFilterData* groupsMask) +{ + physx::PxScene* physxSceneToUse = m_worldSupportPhysXScene != NULL ? m_worldSupportPhysXScene : mPhysXScene; + if (physxSceneToUse == NULL) + { + return false; + } + + PxMat44 scaledTM(tm); + scaledTM.scale(PxVec4(scale, 1.f)); + PxBounds3 worldBounds = convexHull.getBounds(); + PxBounds3Transform(worldBounds, scaledTM); + PX_ASSERT(!worldBounds.isEmpty()); + worldBounds.fattenFast(padding); + + PxBoxGeometry box(worldBounds.getExtents()); + PxQueryFilterData filterData; + filterData.flags = PxQueryFlag::eSTATIC; + if (groupsMask) + filterData.data = *groupsMask; + SCOPED_PHYSX_LOCK_READ(physxSceneToUse); + PxOverlapBuffer ovBuffer(&mOverlapHits[0], MAX_SHAPE_COUNT); + physxSceneToUse->overlap(box, PxTransform(worldBounds.getCenter()), ovBuffer, filterData, NULL); + uint32_t nbHit = ovBuffer.getNbAnyHits(); + //nbHit = nbHit >= 0 ? nbHit : MAX_SHAPE_COUNT; //Ivan: it is always true and should be removed + for (uint32_t i = 0; i < nbHit; i++) + { + if (convexHull.intersects(*mOverlapHits[i].shape, tm, scale, padding)) + { + return true; + } + } + return false; +} + + +} +} // end namespace nvidia + diff --git a/APEX_1.4/module/destructible/src/DestructibleSceneSyncParams.cpp b/APEX_1.4/module/destructible/src/DestructibleSceneSyncParams.cpp new file mode 100644 index 00000000..baf42ff6 --- /dev/null +++ b/APEX_1.4/module/destructible/src/DestructibleSceneSyncParams.cpp @@ -0,0 +1,1284 @@ +/* + * 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. + */ + + +#include "DestructibleScene.h" + +namespace nvidia +{ +namespace destructible +{ + +/*** SyncParams ***/ +namespace destructibleDLL +{ + const char * debugMessage = NULL; + + bool error(const char * message) + { + APEX_INTERNAL_ERROR(message); + if(NULL == debugMessage) + { + debugMessage = message; + } + return true; + } +}; //namespace destructibleDLL + +// only if, for safety, non-logical use of 'if' +// typically to replace assert-if combos +// 'else' after an 'oif' cannot (shouldn't) be used, by design + +// if(A) {B} => A is sufficient for B => if(X) {B} is possible +// oif(A) {B} => A is necessary for B => B is only possible if at least A +// iff(A) {B} => A is both necessary and sufficient for B => bi-directional (A <=> B) +#if 1 +#define oif(condition, message) if((condition) ? 0 : 1) { \ + PX_ASSERT((condition) && message); \ + destructibleDLL::error(message); \ + } else +#else +#define oif(empty0, empty1) +#endif // developer debug mode + +#define STEP_BY(start, stepSize) static_cast<void*>(reinterpret_cast<char*>(static_cast<void*>(start)) + (stepSize)) +#define STEP_BY_K(start, stepSize) static_cast<const void*>(reinterpret_cast<const char*>(static_cast<const void*>(start)) + (stepSize)) + +typedef DestructibleScene::SyncParams SyncParams; + +const char * SyncParams::errorMissingUserActorID = "actor is not marked for sync"; +const char * SyncParams::errorMissingFlagReadDamageEvents = "actor is not marked for reading damage events"; +const char * SyncParams::errorMissingFlagReadFractureEvents = "actor is not marked for reading fracture events"; +const char * SyncParams::errorMissingFlagReadChunkMotion = "actor is not marked for reading chunk motion"; +const char * SyncParams::errorOutOfBoundsActorChunkIndex = "chunk index exceed chunk count for actor"; +const char * SyncParams::errorOutOfBoundsStructureChunkIndex = "chunk index exceed chunk count for structure"; +const char * SyncParams::errorOverrunBuffer = "user buffer is overrun - may contain invalid data and/or invalid size"; + +SyncParams::SyncParams(const ModuleDestructibleImpl::SyncParams & moduleParams_) +:ditchStaleBuffers(false) +,lockSyncParams(false) +,moduleParams(moduleParams_) +,damageEventWriteSource(NULL) +,fractureEventWriteSource(NULL) +{ + PX_ASSERT(NULL != &moduleParams); + PX_ASSERT(segmentSizeChecker.empty()); + PX_ASSERT(damageEventReadSource.empty()); + PX_ASSERT(fractureEventReadSource.empty()); + PX_ASSERT(chunksWithUserControlledChunk.empty()); + ::memset(static_cast<void*>(&damageEventUserInstance), 0x00, sizeof(damageEventUserInstance)); + ::memset(static_cast<void*>(&damageEventImplInstance), 0x00, sizeof(damageEventImplInstance)); + ::memset(static_cast<void*>(&fractureEventUserInstance), 0x00, sizeof(fractureEventUserInstance)); + ::memset(static_cast<void*>(&fractureEventImplInstance), 0x00, sizeof(fractureEventImplInstance)); +} + +SyncParams::~SyncParams() +{ + PX_ASSERT(chunksWithUserControlledChunk.empty()); + PX_ASSERT(fractureEventReadSource.empty()); + PX_ASSERT(damageEventReadSource.empty()); + PX_ASSERT(segmentSizeChecker.empty()); + PX_ASSERT(NULL == fractureEventWriteSource); + PX_ASSERT(NULL == damageEventWriteSource); +} + +bool SyncParams::setSyncActor(uint32_t entryIndex, DestructibleActorImpl * entry, DestructibleActorImpl *& erasedEntry) +{ + bool validEntry = false; + erasedEntry = NULL; + const bool reservedIndex = (0 == entryIndex); + if(!reservedIndex) + { + //set up syncActorRecord if necessary + if(syncActorRecord.getActorContainer().size() <= entryIndex) + { + syncActorRecord.onRebuild(entryIndex + 1); + } + + //update syncActorRecord if appropriate + const bool validIndex = (!reservedIndex && (syncActorRecord.getActorContainer().size() > entryIndex)); + if(validIndex) + { + //determine type of operation + const bool addEntry = (NULL != entry && NULL == syncActorRecord.getActorContainer()[entryIndex]); + const bool removeEntry = (NULL == entry && NULL != syncActorRecord.getActorContainer()[entryIndex]); + const bool replaceEntry = (NULL != entry && NULL != syncActorRecord.getActorContainer()[entryIndex] && entry != syncActorRecord.getActorContainer()[entryIndex]); + const bool sameEntry = (NULL != entry && NULL != syncActorRecord.getActorContainer()[entryIndex] && entry == syncActorRecord.getActorContainer()[entryIndex]); + const bool emptyEntry = (NULL == entry && NULL == syncActorRecord.getActorContainer()[entryIndex]); + PX_ASSERT(addEntry ? (!removeEntry && !replaceEntry && !sameEntry && !emptyEntry) : removeEntry ? (!replaceEntry && !sameEntry && !emptyEntry) : replaceEntry ? (!sameEntry && !emptyEntry) : sameEntry? (!emptyEntry) : emptyEntry); + + //update output arguments before update to syncActorRecord's containers + if(addEntry || removeEntry || replaceEntry) + { + validEntry = true; + if(removeEntry || replaceEntry) + { + erasedEntry = syncActorRecord.getActorContainer()[entryIndex]; + } + } + else + { + PX_ASSERT(sameEntry || emptyEntry); + PX_UNUSED(sameEntry); + PX_UNUSED(emptyEntry); + PX_ASSERT(!"invalid use of function!"); + } + + //update syncActorRecord's containers + if(validEntry) + { + //update index container + if(addEntry) + { + PX_ASSERT(syncActorRecord.getActorContainer().size() > entryIndex); + syncActorRecord.indexContainer.pushBack(entryIndex); + } + if(removeEntry) + { + bool found = false; + for(uint32_t index = 0; index < syncActorRecord.getIndexContainer().size(); ++index) + { + if(entryIndex == syncActorRecord.getIndexContainer()[index]) + { + if(syncActorRecord.getIndexContainer().size() == (index + 1)) + syncActorRecord.indexContainer.popBack(); + else + syncActorRecord.indexContainer[index] = syncActorRecord.indexContainer.popBack(); + found = true; + break; + } + } + PX_VERIFY(found); + } + + //update actor container + if(addEntry || removeEntry || replaceEntry) + { + PX_ASSERT(syncActorRecord.getActorContainer().size() > entryIndex); + syncActorRecord.actorContainer[entryIndex] = entry; + } + } + } + } + PX_ASSERT(syncActorRecord.getActorContainer().empty() ? true : NULL == syncActorRecord.getActorContainer()[0]); + PX_ASSERT(NULL != erasedEntry ? validEntry : true); + return validEntry; +} + +DestructibleActorImpl * SyncParams::getSyncActor(uint32_t entryIndex) const +{ + DestructibleActorImpl * found = NULL; + if((0 != entryIndex) && (syncActorRecord.getActorContainer().size() > entryIndex)) + { + found = syncActorRecord.getActorContainer()[entryIndex]; + PX_ASSERT(NULL != found); + } + return found; +} + +uint32_t SyncParams::getUserActorID(uint32_t destructibleID) const +{ + uint32_t userActorID = 0; + const physx::Array<uint32_t> & indexContainer = syncActorRecord.getIndexContainer(); + const physx::Array<DestructibleActorImpl*> & actorContainer = syncActorRecord.getActorContainer(); + const uint32_t indexContainerSize = indexContainer.size(); + for(uint32_t index = 0; index < indexContainerSize; ++index) + { + const DestructibleActorImpl & currentActor = *(actorContainer[indexContainer[index]]); + PX_ASSERT(NULL != ¤tActor); + if(currentActor.getID() == destructibleID) + { + const DestructibleActorImpl::SyncParams & actorParams = currentActor.getSyncParams(); + userActorID = actorParams.getUserActorID(); + PX_ASSERT(0 != userActorID); + break; + } + } + return userActorID; +} + +void SyncParams::onPreProcessReadData(UserDamageEventHandler & callback, const physx::Array<UserDamageEvent> *& userSource) +{ + PX_ASSERT(NULL != &callback); + userSource = NULL; + const DamageEventHeader * bufferStart = processReadBuffer<UserDamageEventHandler, DamageEventHeader, DamageEventUnit>(callback); + if(NULL != bufferStart) + { + loadDataForRead(bufferStart, userSource); + } +} + +void SyncParams::onPreProcessReadData(UserFractureEventHandler & callback, const physx::Array<UserFractureEvent> *& userSource) +{ + PX_ASSERT(NULL != &callback); + userSource = NULL; + const FractureEventHeader * bufferStart = processReadBuffer<UserFractureEventHandler, FractureEventHeader, FractureEventUnit>(callback); + if(NULL != bufferStart) + { + loadDataForRead(bufferStart, userSource); + } +} + +void SyncParams::onPreProcessReadData(UserChunkMotionHandler & callback) +{ + PX_ASSERT(NULL != &callback); + const ChunkTransformHeader * bufferStart = processReadBuffer<UserChunkMotionHandler, ChunkTransformHeader, ChunkTransformUnit>(callback); + if(NULL != bufferStart) + { + loadDataForRead(bufferStart); + } +} + +DamageEvent & SyncParams::interpret(const UserDamageEvent & userDamageEvent_) +{ + PX_ASSERT(NULL != &userDamageEvent_); + const DestructibleActorImpl & actorAlias = *(userDamageEvent_.actorAlias); + PX_ASSERT(NULL != &actorAlias); + const DamageEventUnit & userDamageEvent = *(userDamageEvent_.get()); + PX_ASSERT(NULL != &userDamageEvent); + const bool isRadiusDamage = (ModuleDestructibleConst::INVALID_CHUNK_INDEX == static_cast<int32_t>(userDamageEvent.chunkIndex)) ? 0 != (DamageEvent::UseRadius & userDamageEvent.damageEventFlags) : false; + bool validUserArguments = false; + oif(((userDamageEvent.chunkIndex < actorAlias.getDestructibleAsset()->getChunkCount()) || isRadiusDamage), SyncParams::errorOutOfBoundsActorChunkIndex) + { + oif(((userDamageEvent.chunkIndex + actorAlias.getFirstChunkIndex()) < actorAlias.getStructure()->chunks.size()) || isRadiusDamage, SyncParams::errorOutOfBoundsStructureChunkIndex) + { + validUserArguments = true; + } + } + damageEventImplInstance.resetFracturesInternal(); + damageEventImplInstance.destructibleID = actorAlias.getID(); + damageEventImplInstance.damage = userDamageEvent.damage; + damageEventImplInstance.momentum = userDamageEvent.momentum; + damageEventImplInstance.radius = userDamageEvent.radius; + damageEventImplInstance.position = userDamageEvent.position; + damageEventImplInstance.direction = userDamageEvent.direction; + damageEventImplInstance.chunkIndexInAsset = (int32_t)userDamageEvent.chunkIndex; + damageEventImplInstance.flags = userDamageEvent.damageEventFlags; + if(!validUserArguments) + { + damageEventImplInstance.flags |= DamageEvent::Invalid; + } + return damageEventImplInstance; +} + +FractureEvent & SyncParams::interpret(const UserFractureEvent & userFractureEvent_) +{ + PX_ASSERT(NULL != &userFractureEvent_); + const DestructibleActorImpl & actorAlias = *(userFractureEvent_.actorAlias); + PX_ASSERT(NULL != &actorAlias); + const FractureEventUnit & userFractureEvent = *(userFractureEvent_.get()); + PX_ASSERT(NULL != &userFractureEvent); + bool validUserArguments = false; + oif(userFractureEvent.chunkIndex < actorAlias.getDestructibleAsset()->getChunkCount(), SyncParams::errorOutOfBoundsActorChunkIndex) + { + oif((userFractureEvent.chunkIndex + actorAlias.getFirstChunkIndex()) < actorAlias.getStructure()->chunks.size(), SyncParams::errorOutOfBoundsStructureChunkIndex) + { + validUserArguments = true; + } + } + fractureEventImplInstance.position = userFractureEvent.position; + fractureEventImplInstance.chunkIndexInAsset = userFractureEvent.chunkIndex; + fractureEventImplInstance.impulse = userFractureEvent.impulse; + fractureEventImplInstance.destructibleID = actorAlias.getID(); + fractureEventImplInstance.flags = userFractureEvent.fractureEventFlags; + fractureEventImplInstance.hitDirection = userFractureEvent.direction; + if(!validUserArguments) + { + fractureEventImplInstance.flags |= FractureEvent::Invalid; + } + return fractureEventImplInstance; +} + +void SyncParams::interceptEdit(DamageEvent & damageEvent, const DestructibleActorImpl::SyncParams & actorParams) const +{ + PX_ASSERT(NULL != &damageEvent); + PX_ASSERT(NULL != &actorParams); + typedef bool DestructibleActorSyncStateLocal; + const DestructibleActorSyncStateLocal * actorSyncState = NULL; + PX_UNUSED(actorParams); + if(NULL != actorSyncState) + { + PX_ASSERT(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::ReadDamageEvents)); + //if(actorSyncState->useChunkDeletionMode) + { + PX_ASSERT(0 == (DamageEvent::DeleteChunkModeUnused & damageEvent.flags)); + damageEvent.flags |= DamageEvent::DeleteChunkModeUnused; + } + } +} + +void SyncParams::interceptEdit(FractureEvent & fractureEvent, const DestructibleActorImpl::SyncParams & actorParams) const +{ + PX_ASSERT(NULL != &fractureEvent); + PX_ASSERT(NULL != &actorParams); + typedef bool DestructibleActorSyncStateLocal; + const DestructibleActorSyncStateLocal * actorSyncState = NULL; + PX_UNUSED(actorParams); + if(NULL != actorSyncState) + { + PX_ASSERT(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::ReadFractureEvents)); + //if(actorSyncState->useChunkDeletionMode) + { + PX_ASSERT(0 == (FractureEvent::DeleteChunk & fractureEvent.flags)); + fractureEvent.flags |= FractureEvent::DeleteChunk; + } + } +} + +void SyncParams::onPostProcessReadData(UserDamageEventHandler & callback) +{ + postProcessReadData(callback); +} + +void SyncParams::onPostProcessReadData(UserFractureEventHandler & callback) +{ + postProcessReadData(callback); +} + +void SyncParams::onPostProcessReadData(UserChunkMotionHandler & callback) +{ + postProcessReadData(callback); +} + +void SyncParams::onProcessWriteData(UserDamageEventHandler & callback, const RingBuffer<DamageEvent> & localSource) +{ + PX_ASSERT(NULL != &callback); + PX_ASSERT(NULL != &localSource); + const uint32_t unitCount = loadDataForWrite(localSource); + if(0 != unitCount) + { + const uint32_t bufferSize = processWriteBuffer<UserDamageEventHandler, DamageEventHeader, DamageEventUnit>(callback); + PX_ASSERT(0 != bufferSize); + if(0 != bufferSize) + { + unloadDataForWrite(callback); + } + } +} + +void SyncParams::onProcessWriteData(UserFractureEventHandler & callback, const RingBuffer<FractureEvent> & localSource) +{ + PX_ASSERT(NULL != &callback); + PX_ASSERT(NULL != &localSource); + const uint32_t unitCount = loadDataForWrite(localSource); + if(0 != unitCount) + { + const uint32_t bufferSize = processWriteBuffer<UserFractureEventHandler, FractureEventHeader, FractureEventUnit>(callback); + PX_ASSERT(0 != bufferSize); + if(0 != bufferSize) + { + unloadDataForWrite(callback); + } + } +} + +void SyncParams::onProcessWriteData(UserChunkMotionHandler & callback) +{ + PX_ASSERT(NULL != &callback); + loadDataForWrite(callback); + const uint32_t bufferSize = processWriteBuffer<UserChunkMotionHandler, ChunkTransformHeader, ChunkTransformUnit>(callback); + if(0 != bufferSize) + { + unloadDataForWrite(callback); + } +} + +void SyncParams::loadDataForRead(const DamageEventHeader * bufferStart, const physx::Array<UserDamageEvent> *& userSource) +{ + PX_ASSERT(damageEventReadSource.empty()); + userSource = NULL; + for(const DamageEventHeader * currentHeader = bufferStart; NULL != currentHeader; currentHeader = currentHeader->next) + { + const uint32_t uniformBufferCount = currentHeader->damageEventCount; + const DamageEventUnit * uniformBufferStart = currentHeader->damageEventBufferStart; + PX_ASSERT(!((0 == uniformBufferCount) ^ (NULL == uniformBufferStart))); + if(0 != uniformBufferCount && NULL != uniformBufferStart) + { + const DestructibleActorImpl * currentActor = NULL; + currentActor = getSyncActor(currentHeader->userActorID); + oif(NULL != currentActor, SyncParams::errorMissingUserActorID) + { + const DestructibleActorImpl::SyncParams & actorParams = currentActor->getSyncParams(); + PX_UNUSED(actorParams); + oif(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::ReadDamageEvents), SyncParams::errorMissingFlagReadDamageEvents) + { + for(uint32_t index = 0; index < uniformBufferCount; ++index) + { + damageEventReadSource.pushBack(UserDamageEvent(currentActor, uniformBufferStart + index)); + } + } + } + } + } + userSource = &damageEventReadSource; +} + +void SyncParams::loadDataForRead(const FractureEventHeader * bufferStart, const physx::Array<UserFractureEvent> *& userSource) +{ + PX_ASSERT(fractureEventReadSource.empty()); + userSource = NULL; + for(const FractureEventHeader * currentHeader = bufferStart; NULL != currentHeader; currentHeader = currentHeader->next) + { + const uint32_t uniformBufferCount = currentHeader->fractureEventCount; + const FractureEventUnit * uniformBufferStart = currentHeader->fractureEventBufferStart; + PX_ASSERT(!((0 == uniformBufferCount) ^ (NULL == uniformBufferStart))); + if(0 != uniformBufferCount && NULL != uniformBufferStart) + { + const DestructibleActorImpl * currentActor = NULL; + currentActor = getSyncActor(currentHeader->userActorID); + oif(NULL != currentActor, SyncParams::errorMissingUserActorID) + { + const DestructibleActorImpl::SyncParams & actorParams = currentActor->getSyncParams(); + PX_UNUSED(actorParams); + oif(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::ReadFractureEvents), SyncParams::errorMissingFlagReadFractureEvents) + { + for(uint32_t index = 0; index < uniformBufferCount; ++index) + { + fractureEventReadSource.pushBack(UserFractureEvent(currentActor, uniformBufferStart + index)); + } + } + } + } + } + userSource = &fractureEventReadSource; +} + +void SyncParams::loadDataForRead(const ChunkTransformHeader * bufferStart) +{ + for(const ChunkTransformHeader * currentHeader = bufferStart; NULL != currentHeader; currentHeader = currentHeader->next) + { + const uint32_t uniformBufferCount = currentHeader->chunkTransformCount; + const ChunkTransformUnit * uniformBufferStart = currentHeader->chunkTransformBufferStart; + PX_ASSERT(!((0 == uniformBufferCount) ^ (NULL == uniformBufferStart))); + if(0 != uniformBufferCount && NULL != uniformBufferStart) + { + const DestructibleActorImpl * currentActor = NULL; + currentActor = getSyncActor(currentHeader->userActorID); + oif(NULL != currentActor, SyncParams::errorMissingUserActorID) + { + const DestructibleActorImpl::SyncParams & actorParams = currentActor->getSyncParams(); + PX_UNUSED(actorParams); + oif(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::ReadChunkTransform), SyncParams::errorMissingFlagReadChunkMotion) + { + for(uint32_t index = 0; index < uniformBufferCount; ++index) + { + const ChunkTransformUnit * currentControlledChunk = uniformBufferStart + index; + PX_ASSERT(NULL != currentControlledChunk); + const uint32_t currentChunkIndex = currentControlledChunk->chunkIndex; + oif(currentChunkIndex < currentActor->getDestructibleAsset()->getChunkCount(), SyncParams::errorOutOfBoundsActorChunkIndex) + { + oif((currentChunkIndex + currentActor->getFirstChunkIndex()) < currentActor->getStructure()->chunks.size(), SyncParams::errorOutOfBoundsStructureChunkIndex) + { + DestructibleStructure::Chunk & currentLocalChunk = const_cast<DestructibleStructure*>(currentActor->getStructure())->chunks[currentChunkIndex + currentActor->getFirstChunkIndex()]; + if((0 != (currentLocalChunk.state & ChunkVisible)) && (0 != (currentLocalChunk.state & ChunkDynamic))) + { + //PX_ASSERT(NULL == currentLocalChunk.controlledChunk); // could be overwritten since the same index could be in the buffer (due to lag or whatever) in the same cycle. so overwriting with the last is ok. hooray! + currentLocalChunk.controlledChunk = static_cast<const ControlledChunk*>(currentControlledChunk); + chunksWithUserControlledChunk.pushBack(¤tLocalChunk); + } + else + { + //PX_ASSERT(!"we need a way to let the user know that these chunks are abandoned!"); + } + } + } + } + } + } + } + } +} + +bool SyncParams::unloadDataForRead(const UserDamageEventHandler &) +{ + const bool dataExist = !damageEventReadSource.empty(); + if(dataExist) + { + damageEventReadSource.clear(); + } + return dataExist; +} + +bool SyncParams::unloadDataForRead(const UserFractureEventHandler &) +{ + const bool dataExist = !fractureEventReadSource.empty(); + if(dataExist) + { + fractureEventReadSource.clear(); + } + return dataExist; +} + +bool SyncParams::unloadDataForRead(const UserChunkMotionHandler &) +{ + //unloadDataForRead() is unloaded in actor->setRenderTMs() + const bool dataExist = !chunksWithUserControlledChunk.empty(); + PX_ASSERT(assertControlledChunkContainerOk()); + chunksWithUserControlledChunk.clear(); + return dataExist; +} + +template<typename Callback, typename Header, typename Unit> const Header * SyncParams::processReadBuffer(Callback & callback) const +{ + const Header * bufferStartWritten = NULL; + PX_ASSERT(NULL != &callback); + Header * bufferStartRetrieved = NULL; + uint32_t bufferSizeRetrieved = 0; + bool continuePointerSwizzling = false; + int32_t headerCount = 0; + do + { + callback.onPreProcessReadBegin(bufferStartRetrieved, bufferSizeRetrieved, continuePointerSwizzling); + if(NULL != bufferStartRetrieved && 0 != bufferSizeRetrieved) + { + const int32_t currentHeaderCount = writeUserBufferPointers<Header, Unit>(bufferStartRetrieved, bufferSizeRetrieved); + PX_ASSERT(currentHeaderCount > 0); + headerCount += currentHeaderCount; + } + } + while(continuePointerSwizzling); + callback.onPreProcessReadDone((uint32_t)headerCount); + bufferStartRetrieved = NULL; + bufferSizeRetrieved = 0; + callback.onReadBegin(bufferStartWritten); + return bufferStartWritten; +} + +template<typename Header, typename Unit> int32_t SyncParams::writeUserBufferPointers(Header * bufferStart, const uint32_t bufferSize) const +{ + int32_t headerCount = 0; + if(NULL != bufferStart && 0 != bufferSize) + { + uint32_t sizeProcessed = 0; + for(Header * currentHeader = bufferStart; NULL != currentHeader; currentHeader = currentHeader->next) + { + PX_ASSERT(NULL != currentHeader); + const uint32_t uniformBufferCount = getUniformBufferCount<Unit>(*currentHeader); + const uint32_t segmentSize = moduleParams.getSize<Header>() + (uniformBufferCount * moduleParams.getSize<Unit>()); + sizeProcessed += segmentSize; + PX_ASSERT(sizeProcessed <= bufferSize); + oif(sizeProcessed <= bufferSize, SyncParams::errorOverrunBuffer) + { + getUniformBufferStartMutable<Unit>(*currentHeader) = (0 == uniformBufferCount) ? NULL : static_cast<Unit*>(STEP_BY(currentHeader, moduleParams.getSize<Header>())); + currentHeader->next = (sizeProcessed == bufferSize) ? NULL : static_cast<Header*>(STEP_BY(currentHeader, segmentSize)); + ++headerCount; + } + } + PX_ASSERT(sizeProcessed == bufferSize); + headerCount = (sizeProcessed == bufferSize) ? headerCount : -1; + } + return headerCount; +} + +template<typename Callback> void SyncParams::postProcessReadData(Callback & callback) +{ + PX_ASSERT(NULL != &callback); + const bool dataExist = unloadDataForRead(callback); + if(dataExist || NULL != destructibleDLL::debugMessage) + { + callback.onReadDone(destructibleDLL::debugMessage); + } + destructibleDLL::debugMessage = NULL; +} + +uint32_t SyncParams::loadDataForWrite(const RingBuffer<DamageEvent> & localSource) +{ + PX_ASSERT(NULL != &localSource); + PX_ASSERT(NULL == damageEventWriteSource); + uint32_t unitCount = 0; + DestructibleActorImpl * currentActor = NULL; + for(uint32_t index = 0; index < localSource.size(); ++index) + { + const DamageEvent & currentDamageEvent = localSource[index]; + currentActor = getSyncActor(getUserActorID(currentDamageEvent.destructibleID)); + if(NULL != currentActor) + { + DestructibleActorImpl::SyncParams & actorParams = currentActor->getSyncParamsMutable(); + if(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::CopyDamageEvents)) + { + if(0 == (DamageEvent::Invalid & currentDamageEvent.flags) && !currentDamageEvent.isFromImpact()) + { + if(!interceptLoad(currentDamageEvent, *currentActor)) + { + actorParams.pushDamageBufferIndex(index); + ++unitCount; + } + } + } + } + } + damageEventWriteSource = (0 == unitCount) ? NULL : &localSource; + return unitCount; +} + +uint32_t SyncParams::loadDataForWrite(const RingBuffer<FractureEvent> & localSource) +{ + PX_ASSERT(NULL != &localSource); + PX_ASSERT(NULL == fractureEventWriteSource); + uint32_t unitCount = 0; + DestructibleActorImpl * currentActor = NULL; + for(uint32_t index = 0; index < localSource.size(); ++index) + { + const FractureEvent & currentFractureEvent = localSource[index]; + currentActor = getSyncActor(getUserActorID(currentFractureEvent.destructibleID)); + if(NULL != currentActor) + { + DestructibleActorImpl::SyncParams & actorParams = currentActor->getSyncParamsMutable(); + if(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::CopyFractureEvents)) + { + if(0 == (FractureEvent::Invalid & currentFractureEvent.flags) && (0 == (FractureEvent::DamageFromImpact & currentFractureEvent.flags))) + { + if(!interceptLoad(currentFractureEvent, *currentActor)) + { + actorParams.pushFractureBufferIndex(index); + ++unitCount; + } + } + } + } + } + fractureEventWriteSource = (0 == unitCount) ? NULL : &localSource; + return unitCount; +} + +uint32_t SyncParams::loadDataForWrite(const UserChunkMotionHandler &) +{ + //loadDataForWrite() is loaded in actor->setRenderTMs() + return 0; +} + +void SyncParams::unloadDataForWrite(const UserDamageEventHandler &) +{ + PX_ASSERT(NULL != damageEventWriteSource); + damageEventWriteSource = NULL; + const physx::Array<uint32_t> & indexContainer = syncActorRecord.getIndexContainer(); + const physx::Array<DestructibleActorImpl*> & actorContainer = syncActorRecord.getActorContainer(); + const uint32_t indexContainerSize = indexContainer.size(); + for(uint32_t index = 0; index < indexContainerSize; ++index) + { + DestructibleActorImpl & currentActor = *(actorContainer[indexContainer[index]]); + PX_ASSERT(NULL != ¤tActor); + DestructibleActorImpl::SyncParams & actorParams = currentActor.getSyncParamsMutable(); + actorParams.clear<DamageEventUnit>(); + } +} + +void SyncParams::unloadDataForWrite(const UserFractureEventHandler &) +{ + PX_ASSERT(NULL != fractureEventWriteSource); + fractureEventWriteSource = NULL; + const physx::Array<uint32_t> & indexContainer = syncActorRecord.getIndexContainer(); + const physx::Array<DestructibleActorImpl*> & actorContainer = syncActorRecord.getActorContainer(); + const uint32_t indexContainerSize = indexContainer.size(); + for(uint32_t index = 0; index < indexContainerSize; ++index) + { + DestructibleActorImpl & currentActor = *(actorContainer[indexContainer[index]]); + PX_ASSERT(NULL != ¤tActor); + DestructibleActorImpl::SyncParams & actorParams = currentActor.getSyncParamsMutable(); + actorParams.clear<FractureEventUnit>(); + } +} + +void SyncParams::unloadDataForWrite(const UserChunkMotionHandler &) +{ + const physx::Array<uint32_t> & indexContainer = syncActorRecord.getIndexContainer(); + const physx::Array<DestructibleActorImpl*> & actorContainer = syncActorRecord.getActorContainer(); + const uint32_t indexContainerSize = indexContainer.size(); + for(uint32_t index = 0; index < indexContainerSize; ++index) + { + DestructibleActorImpl & currentActor = *(actorContainer[indexContainer[index]]); + PX_ASSERT(NULL != ¤tActor); + DestructibleActorImpl::SyncParams & actorParams = currentActor.getSyncParamsMutable(); + actorParams.clear<ChunkTransformUnit>(); + } +} + +template<typename Callback, typename Header, typename Unit> uint32_t SyncParams::processWriteBuffer(Callback & callback) +{ + uint32_t bufferSizeWritten = 0; + PX_ASSERT(NULL != &callback); + Header * bufferStartRequested = NULL; + const uint32_t bufferSizeRequested = getBufferSizeRequired<Header, Unit>(); + if(0 != bufferSizeRequested) + { + uint32_t headerCount = 0; + callback.onWriteBegin(bufferStartRequested, bufferSizeRequested); + if(NULL != bufferStartRequested) + { + bufferSizeWritten = writeUserBuffer<Header, Unit>(bufferStartRequested, headerCount); + PX_ASSERT(bufferSizeWritten == bufferSizeRequested); + callback.onWriteDone(headerCount); + } + } + return bufferSizeWritten; +} + +template<typename Header, typename Unit> uint32_t SyncParams::getBufferSizeRequired() const +{ + uint32_t bufferSizeRequired = 0; + PX_ASSERT(segmentSizeChecker.empty()); + const physx::Array<uint32_t> & indexContainer = syncActorRecord.getIndexContainer(); + const physx::Array<DestructibleActorImpl*> & actorContainer = syncActorRecord.getActorContainer(); + const uint32_t indexContainerSize = indexContainer.size(); + for(uint32_t index = 0; index < indexContainerSize; ++index) + { + const DestructibleActorImpl & currentActor = *(actorContainer[indexContainer[index]]); + PX_ASSERT(NULL != ¤tActor); + const DestructibleActorImpl::SyncParams & actorParams = currentActor.getSyncParams(); + if(0 != actorParams.getCount<Unit>()) + { + const uint32_t segmentSize = getSegmentSizeRequired<Header, Unit>(actorParams); + bufferSizeRequired += segmentSize; + segmentSizeChecker.pushBack(segmentSize); + } + } + return bufferSizeRequired; +} + +template<typename Header, typename Unit> uint32_t SyncParams::getSegmentSizeRequired(const DestructibleActorImpl::SyncParams & actorParams) const +{ + uint32_t sizeRequired = 0; + sizeRequired += actorParams.getCount<Unit>() * moduleParams.getSize<Unit>(); + if(0 != sizeRequired) + { + sizeRequired += moduleParams.getSize<Header>(); + } + return sizeRequired; +} + +template<typename Header, typename Unit> uint32_t SyncParams::writeUserBuffer(Header * bufferStart, uint32_t & headerCount) +{ + PX_ASSERT(NULL != bufferStart); + headerCount = 0; + uint32_t bufferSizeWritten = 0; + if(NULL != bufferStart) + { + uint32_t segmentSizeCheckerIndex = 0; + Header * currentSegmentHeader = bufferStart; + const physx::Array<uint32_t> & indexContainer = syncActorRecord.getIndexContainer(); + const physx::Array<DestructibleActorImpl*> & actorContainer = syncActorRecord.getActorContainer(); + const uint32_t indexContainerSize = indexContainer.size(); + for(uint32_t index = 0; index < indexContainerSize; ++index) + { + const DestructibleActorImpl & currentActor = *(actorContainer[indexContainer[index]]); + PX_ASSERT(NULL != ¤tActor); + const DestructibleActorImpl::SyncParams & actorParams = currentActor.getSyncParams(); + if(0 != actorParams.getCount<Unit>()) + { + PX_ASSERT(segmentSizeChecker.size() > segmentSizeCheckerIndex); + const uint32_t segmentSizeWritten = writeUserSegment<Header, Unit>(currentSegmentHeader, (segmentSizeChecker.size() - 1) == segmentSizeCheckerIndex, actorParams); + PX_ASSERT(0 != segmentSizeWritten); + bufferSizeWritten += segmentSizeWritten; + currentSegmentHeader = static_cast<Header*>(STEP_BY(currentSegmentHeader, segmentSizeWritten)); + PX_ASSERT(segmentSizeWritten == segmentSizeChecker[segmentSizeCheckerIndex]); + ++segmentSizeCheckerIndex; + } + } + headerCount = segmentSizeChecker.size(); + segmentSizeChecker.clear(); + } + return bufferSizeWritten; +} + +template<typename Header, typename Unit> uint32_t SyncParams::writeUserSegment(Header * header, bool isLast, const DestructibleActorImpl::SyncParams & actorParams) +{ + //write header + PX_ASSERT(NULL != header); + const uint32_t headerSize = moduleParams.getSize<Header>(); + header->userActorID = actorParams.getUserActorID(); + getUniformBufferCountMutable<Unit>(*header) = actorParams.getCount<Unit>(); + const uint32_t uniformBufferCount = getUniformBufferCount<Unit>(*header); + getUniformBufferStartMutable<Unit>(*header) = (0 == uniformBufferCount) ? NULL : static_cast<Unit*>(STEP_BY(header, headerSize)); + const uint32_t uniformBufferSize = uniformBufferCount * moduleParams.getSize<Unit>(); + header->next = isLast ? NULL : static_cast<Header*>(STEP_BY(header, headerSize + uniformBufferSize)); + + //write uniform buffers + uint32_t sizeWritten = 0; + Unit * uniformBufferStart = getUniformBufferStart<Unit>(*header); + sizeWritten += (NULL == uniformBufferStart) ? 0 : writeUserUniformBuffer<Unit>(uniformBufferStart, actorParams); + PX_ASSERT(0 != sizeWritten); + sizeWritten += headerSize; + PX_ASSERT(headerSize != sizeWritten); + return sizeWritten; +} + +template<> uint32_t SyncParams::writeUserUniformBuffer<DamageEventUnit>(DamageEventUnit * bufferStart, const DestructibleActorImpl::SyncParams & actorParams) +{ + PX_ASSERT(NULL != bufferStart); + PX_ASSERT(NULL != damageEventWriteSource); + uint32_t sizeWritten = 0; + const uint32_t count = actorParams.getCount<DamageEventUnit>(); + const physx::Array<uint32_t> & damageBufferIndices = actorParams.getDamageBufferIndices(); + for(uint32_t index = 0 ; index < count; ++index) + { + PX_ASSERT(damageEventWriteSource->size() > damageBufferIndices[index]); + DamageEventUnit * const source = interpret((*damageEventWriteSource)[damageBufferIndices[index]]); + const bool usingEditFeature = false; + if(usingEditFeature) + { + interceptEdit(*source, actorParams); + } + const uint32_t stride = moduleParams.getSize<DamageEventUnit>(); + ::memcpy(STEP_BY(bufferStart, stride * index), static_cast<const void*>(source), stride); + sizeWritten += stride; + } + return sizeWritten; +} + +template<> uint32_t SyncParams::writeUserUniformBuffer<FractureEventUnit>(FractureEventUnit * bufferStart, const DestructibleActorImpl::SyncParams & actorParams) +{ + PX_ASSERT(NULL != bufferStart); + PX_ASSERT(NULL != fractureEventWriteSource); + uint32_t sizeWritten = 0; + const uint32_t count = actorParams.getCount<FractureEventUnit>(); + const physx::Array<uint32_t> & fractureBufferIndices = actorParams.getFractureBufferIndices(); + for(uint32_t index = 0 ; index < count; ++index) + { + PX_ASSERT(fractureEventWriteSource->size() > fractureBufferIndices[index]); + FractureEventUnit * const source = interpret((*fractureEventWriteSource)[fractureBufferIndices[index]]); + const bool usingEditFeature = false; + if(usingEditFeature) + { + interceptEdit(*source, actorParams); + } + const uint32_t stride = moduleParams.getSize<FractureEventUnit>(); + ::memcpy(STEP_BY(bufferStart, stride * index), static_cast<const void*>(source), stride); + sizeWritten += stride; + } + return sizeWritten; +} + +template<> uint32_t SyncParams::writeUserUniformBuffer<ChunkTransformUnit>(ChunkTransformUnit * bufferStart, const DestructibleActorImpl::SyncParams & actorParams) +{ + PX_ASSERT(NULL != bufferStart); + uint32_t sizeWritten = 0; + const uint32_t count = actorParams.getCount<ChunkTransformUnit>(); + if(0 != count) + { + PX_ASSERT(assertCachedChunkContainerOk(actorParams)); + sizeWritten = count * moduleParams.getSize<ChunkTransformUnit>(); + ::memcpy(static_cast<void*>(bufferStart), static_cast<const void*>(&(actorParams.getCachedChunkTransforms()[0])), sizeWritten); + } + return sizeWritten; +} + +bool SyncParams::interceptLoad(const DamageEvent & damageEvent, const DestructibleActorImpl & syncActor) const +{ + PX_ASSERT(NULL != &damageEvent); + PX_ASSERT(NULL != &syncActor); + const DestructibleActorImpl::SyncParams & actorParams = syncActor.getSyncParams(); + PX_ASSERT(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::CopyDamageEvents)); + const int32_t chunkArrayCount = (int32_t)syncActor.getDestructibleAsset()->getChunkCount(); + PX_UNUSED(chunkArrayCount); + PX_ASSERT(chunkArrayCount > 0); + PX_ASSERT(ModuleDestructibleConst::INVALID_CHUNK_INDEX == static_cast<int32_t>(damageEvent.chunkIndexInAsset) ? true : (0 <= damageEvent.chunkIndexInAsset) && (chunkArrayCount > damageEvent.chunkIndexInAsset)); + PX_ASSERT(ModuleDestructibleConst::INVALID_CHUNK_INDEX == static_cast<int32_t>(damageEvent.chunkIndexInAsset) ? 0 != (DamageEvent::UseRadius & damageEvent.flags) : true); + const uint16_t chunkDepth = uint16_t((ModuleDestructibleConst::INVALID_CHUNK_INDEX == static_cast<int32_t>(damageEvent.chunkIndexInAsset)) ? 0 : static_cast<const DestructibleAssetParameters*>(syncActor.getDestructibleAsset()->getAssetNvParameterized())->chunks.buf[damageEvent.chunkIndexInAsset].depth); + return + NULL == actorParams.getActorSyncState() ? false : + actorParams.getActorSyncState()->damageEventFilterDepth < chunkDepth ? true : + false; +} + +bool SyncParams::interceptLoad(const FractureEvent & fractureEvent, const DestructibleActorImpl & syncActor) const +{ + PX_ASSERT(NULL != &fractureEvent); + PX_ASSERT(NULL != &syncActor); + const DestructibleActorImpl::SyncParams & actorParams = syncActor.getSyncParams(); + PX_ASSERT(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::CopyFractureEvents)); + const uint32_t chunkArrayCount = syncActor.getDestructibleAsset()->getChunkCount(); + PX_UNUSED(chunkArrayCount); + PX_ASSERT(chunkArrayCount > 0); + const uint16_t chunkDepth = static_cast<const DestructibleAssetParameters*>(syncActor.getDestructibleAsset()->getAssetNvParameterized())->chunks.buf[fractureEvent.chunkIndexInAsset].depth; + return + NULL == actorParams.getActorSyncState() ? false : + actorParams.getActorSyncState()->fractureEventFilterDepth < chunkDepth ? true : + false; +} + +DamageEventUnit * SyncParams::interpret(const DamageEvent & damageEvent) +{ + PX_ASSERT(NULL != &damageEvent); + PX_ASSERT(ModuleDestructibleConst::INVALID_CHUNK_INDEX == static_cast<int32_t>(damageEvent.chunkIndexInAsset) ? 0 != (DamageEvent::UseRadius & damageEvent.flags) : true); + PX_ASSERT(0 == (DamageEvent::Invalid & damageEvent.flags)); + damageEventUserInstance.chunkIndex = static_cast<uint32_t>(damageEvent.chunkIndexInAsset); + damageEventUserInstance.damageEventFlags = damageEvent.flags; + damageEventUserInstance.damage = damageEvent.damage; + damageEventUserInstance.momentum = damageEvent.momentum; + damageEventUserInstance.radius = damageEvent.radius; + damageEventUserInstance.position = damageEvent.position; + damageEventUserInstance.direction = damageEvent.direction; + return &damageEventUserInstance; +} + +FractureEventUnit * SyncParams::interpret(const FractureEvent & fractureEvent) +{ + PX_ASSERT(NULL != &fractureEvent); + PX_ASSERT(0 == (FractureEvent::Invalid & fractureEvent.flags)); + fractureEventUserInstance.chunkIndex = fractureEvent.chunkIndexInAsset; + fractureEventUserInstance.fractureEventFlags = fractureEvent.flags; + fractureEventUserInstance.position = fractureEvent.position; + fractureEventUserInstance.direction = fractureEvent.hitDirection; + fractureEventUserInstance.impulse = fractureEvent.impulse; + return &fractureEventUserInstance; +} + +void SyncParams::interceptEdit(DamageEventUnit & nxApexDamageEventUnit, const DestructibleActorImpl::SyncParams & actorParams) const +{ + PX_ASSERT(NULL != &nxApexDamageEventUnit); + PX_ASSERT(NULL != &actorParams); + typedef bool DestructibleActorSyncStateSource; + const DestructibleActorSyncStateSource * actorSyncState = NULL; + PX_UNUSED(actorParams); + if(NULL != actorSyncState) + { + PX_ASSERT(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::CopyDamageEvents)); + //if(actorSyncState->useChunkDeletionMode) + { + PX_ASSERT(0 == (DamageEvent::DeleteChunkModeUnused & nxApexDamageEventUnit.damageEventFlags)); + nxApexDamageEventUnit.damageEventFlags |= DamageEvent::DeleteChunkModeUnused; + } + } +} + +void SyncParams::interceptEdit(FractureEventUnit & nxApexFractureEventUnit, const DestructibleActorImpl::SyncParams & actorParams) const +{ + PX_ASSERT(NULL != &nxApexFractureEventUnit); + PX_ASSERT(NULL != &actorParams); + typedef bool DestructibleActorSyncStateSource; + const DestructibleActorSyncStateSource * actorSyncState = NULL; + PX_UNUSED(actorParams); + if(NULL != actorSyncState) + { + PX_ASSERT(actorParams.isSyncFlagSet(DestructibleActorSyncFlags::CopyFractureEvents)); + //if(actorSyncState->useChunkDeletionMode) + { + PX_ASSERT(0 == (FractureEvent::DeleteChunk & nxApexFractureEventUnit.fractureEventFlags)); + nxApexFractureEventUnit.fractureEventFlags |= FractureEvent::DeleteChunk; + } + } +} + +template<> uint32_t SyncParams::getUniformBufferCount<DamageEventUnit>(const DamageEventHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.damageEventCount; +} + +template<> uint32_t SyncParams::getUniformBufferCount<FractureEventUnit>(const FractureEventHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.fractureEventCount; +} + +template<> uint32_t SyncParams::getUniformBufferCount<ChunkTransformUnit>(const ChunkTransformHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.chunkTransformCount; +} + +template<> uint32_t & SyncParams::getUniformBufferCountMutable<DamageEventUnit>(DamageEventHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.damageEventCount; +} + +template<> uint32_t & SyncParams::getUniformBufferCountMutable<FractureEventUnit>(FractureEventHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.fractureEventCount; +} + +template<> uint32_t & SyncParams::getUniformBufferCountMutable<ChunkTransformUnit>(ChunkTransformHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.chunkTransformCount; +} + +template<> DamageEventUnit * SyncParams::getUniformBufferStart<DamageEventUnit>(const DamageEventHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.damageEventBufferStart; +} + +template<> FractureEventUnit * SyncParams::getUniformBufferStart<FractureEventUnit>(const FractureEventHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.fractureEventBufferStart; +} + +template<> ChunkTransformUnit * SyncParams::getUniformBufferStart<ChunkTransformUnit>(const ChunkTransformHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.chunkTransformBufferStart; +} + +template<> DamageEventUnit *& SyncParams::getUniformBufferStartMutable<DamageEventUnit>(DamageEventHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.damageEventBufferStart; +} + +template<> FractureEventUnit *& SyncParams::getUniformBufferStartMutable<FractureEventUnit>(FractureEventHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.fractureEventBufferStart; +} + +template<> ChunkTransformUnit *& SyncParams::getUniformBufferStartMutable<ChunkTransformUnit>(ChunkTransformHeader & header) const +{ + PX_ASSERT(NULL != &header); + return header.chunkTransformBufferStart; +} + +SyncParams::SyncActorRecord::SyncActorRecord() +{ + PX_ASSERT(indexContainer.empty()); + PX_ASSERT(actorContainer.empty()); +} + +SyncParams::SyncActorRecord::~SyncActorRecord() +{ + PX_ASSERT(assertActorContainerOk()); + actorContainer.clear(); + PX_ASSERT(actorContainer.empty()); + PX_ASSERT(indexContainer.empty()); +} + +const physx::Array<uint32_t> & SyncParams::SyncActorRecord::getIndexContainer() const +{ + return indexContainer; +} + +const physx::Array<DestructibleActorImpl*> & SyncParams::SyncActorRecord::getActorContainer() const +{ + return actorContainer; +} + +void SyncParams::SyncActorRecord::onRebuild(const uint32_t & newCount) +{ + PX_ASSERT((1 != newCount) && (actorContainer.size() != newCount)); + //expand + if(newCount > actorContainer.size()) + { + if(actorContainer.empty()) + { + PX_ASSERT(indexContainer.empty()); + actorContainer.resize(newCount, NULL); + } + else + { + if(indexContainer.empty()) + { + while(!actorContainer.empty()) + { + PX_ASSERT(NULL == actorContainer.back()); + actorContainer.popBack(); + } + actorContainer.resize(newCount, NULL); + } + else + { + const bool duh = true; + if(duh) + { + while(actorContainer.size() < newCount) + { + actorContainer.pushBack(NULL); + } + } + else + { + //save + physx::Array<DestructibleActorImpl*> temp; + for(physx::Array<uint32_t>::ConstIterator kIter = indexContainer.begin(); kIter != indexContainer.end(); ++kIter) + { + PX_ASSERT(actorContainer.size() > *kIter); + temp.pushBack(actorContainer[*kIter]); + PX_ASSERT(NULL != temp.back()); + } + + //reset + actorContainer.clear(); + actorContainer.resize(newCount, NULL); + + //reload + PX_ASSERT(temp.size() == indexContainer.size()); + physx::Array<uint32_t>::Iterator iter = indexContainer.end(); + while(indexContainer.begin() != iter--) + { + PX_ASSERT(actorContainer.size() > *iter); + actorContainer[*iter] = temp.popBack(); + } + iter = NULL; + PX_ASSERT(temp.empty()); + } + } + } + PX_ASSERT(actorContainer.size() > 1); + } + //contract + else + { + PX_ASSERT(!"contracting actorContainer is not allowed by design!"); + /* + contracting is not allowed because of the need to delete entries internally should the removed indexes contain valid entries, without informing the user. + moreover, this does not improve search performance, since we use indexing to find our entries. + in fact, we incur a cost for performing the contraction, and removing the entries + */ +#if 0 + PX_ASSERT(actorContainer.size() > 1); + //search for affected (non-NULL) entries in the actorContainer OR search for affected indices in the indexContainer + //reset the entry's (actor's) sync params. inform the user if possible + //copy the actorContainer's entries that would still be in range, resize the actorContainer to newCount, then copy these entries back in + //search the indexContainer for these entries, and remove them +#endif + } +} + +bool SyncParams::SyncActorRecord::assertActorContainerOk() const +{ + for(physx::Array<DestructibleActorImpl*>::ConstIterator kIter = actorContainer.begin(); kIter != actorContainer.end(); ++kIter) + { + PX_ASSERT(NULL == (*kIter)); + } + return true; +} + +SyncParams::ActorEventPair::ActorEventPair(const DestructibleActorImpl * actorAlias_, const DamageEventUnit * userDamageEvent_) +:actorAlias(actorAlias_) +,userDamageEvent(userDamageEvent_) +{ + PX_ASSERT(NULL != actorAlias); + PX_ASSERT(NULL != userDamageEvent); +} + +SyncParams::ActorEventPair::ActorEventPair(const DestructibleActorImpl * actorAlias_, const FractureEventUnit * userFractureEvent_) +:actorAlias(actorAlias_) +,userFractureEvent(userFractureEvent_) +{ + PX_ASSERT(NULL != actorAlias); + PX_ASSERT(NULL != userFractureEvent); +} + +SyncParams::ActorEventPair::~ActorEventPair() +{ + userFractureEvent = NULL; + PX_ASSERT(NULL == userDamageEvent); + actorAlias = NULL; +} + +SyncParams::UserDamageEvent::UserDamageEvent(const DestructibleActorImpl * actorAlias_, const DamageEventUnit * userDamageEvent_) +:ActorEventPair(actorAlias_, userDamageEvent_) +{ +} + +const DamageEventUnit * SyncParams::UserDamageEvent::get() const +{ + return userDamageEvent; +} + +SyncParams::UserDamageEvent::~UserDamageEvent() +{ +} + +SyncParams::UserFractureEvent::UserFractureEvent(const DestructibleActorImpl * actorAlias_, const FractureEventUnit * userFractureEvent_) +:ActorEventPair(actorAlias_, userFractureEvent_) +{ +} + +const FractureEventUnit * SyncParams::UserFractureEvent::get() const +{ + return userFractureEvent; +} + +SyncParams::UserFractureEvent::~UserFractureEvent() +{ +} + +bool SyncParams::assertUserDamageEventOk(const DamageEvent & damageEvent, const DestructibleScene & scene) const +{ + PX_ASSERT(NULL != &damageEvent); + PX_ASSERT(NULL != &scene); + PX_ASSERT(damageEvent.destructibleID < scene.mDestructibles.usedCount()); + const DestructibleActorImpl * actor = NULL; + actor = scene.mDestructibles.direct(damageEvent.destructibleID); + PX_ASSERT(NULL != actor); + const DestructibleStructure * structure = NULL; + structure = actor->getStructure(); + PX_VERIFY(NULL != structure); + const bool isRadiusDamage = (ModuleDestructibleConst::INVALID_CHUNK_INDEX == static_cast<int32_t>(damageEvent.chunkIndexInAsset)) && (0 != (DamageEvent::UseRadius & damageEvent.flags)); + PX_UNUSED(isRadiusDamage); + PX_ASSERT((damageEvent.chunkIndexInAsset >= 0) || isRadiusDamage); + PX_ASSERT((static_cast<uint32_t>(damageEvent.chunkIndexInAsset) < structure->chunks.size()) || isRadiusDamage); + return true; +} + +bool SyncParams::assertUserFractureEventOk(const FractureEvent & fractureEvent, const DestructibleScene & scene) const +{ + PX_ASSERT(NULL != &fractureEvent); + PX_ASSERT(NULL != &scene); + PX_ASSERT(fractureEvent.destructibleID < scene.mDestructibles.usedCount()); + const DestructibleActorImpl * actor = NULL; + actor = scene.mDestructibles.direct(fractureEvent.destructibleID); + PX_ASSERT(NULL != actor); + const DestructibleStructure * structure = NULL; + structure = actor->getStructure(); + PX_VERIFY(NULL != structure); + PX_ASSERT(fractureEvent.chunkIndexInAsset < structure->chunks.size()); + return true; +} + +bool SyncParams::assertCachedChunkContainerOk(const DestructibleActorImpl::SyncParams & actorParams) const +{ + const uint32_t count = actorParams.getCount<ChunkTransformUnit>(); + const physx::Array<CachedChunk> & cachedChunkTransforms = actorParams.getCachedChunkTransforms(); + for(uint32_t index = 0 ; index < count; ++index) + { + PX_ASSERT(moduleParams.getSize<ChunkTransformUnit>() == sizeof(cachedChunkTransforms[index])); + PX_ASSERT(getSyncActor(actorParams.getUserActorID())->getStructure()->chunks.size() > cachedChunkTransforms[index].chunkIndex); + PX_UNUSED(cachedChunkTransforms); + } + return true; +} + +bool SyncParams::assertControlledChunkContainerOk() const +{ + for(physx::Array<DestructibleStructure::Chunk*>::ConstIterator kIter = chunksWithUserControlledChunk.begin(); kIter != chunksWithUserControlledChunk.end(); ++kIter) + { + PX_ASSERT(NULL == (*kIter)->controlledChunk); + } + return true; +} + +const DestructibleScene::SyncParams & DestructibleScene::getSyncParams() const +{ + return mSyncParams; +} + +DestructibleScene::SyncParams & DestructibleScene::getSyncParamsMutable() +{ + return const_cast<DestructibleScene::SyncParams&>(getSyncParams()); +} + +#undef STEP_BY_K +#undef STEP_BY +#undef oif + +} // namespace destructible +} // namespace nvidia + +#if 0 + PX_ASSERT(physx::string::stricmp(targetShapes[0]->getActor().getClassName(), "PxRigidDynamic") == 0); + physx::PxRigidDynamic * aliasRigidActor = NULL; + aliasRigidActor = (static_cast<physx::PxRigidDynamic*>(&targetShapes[0]->getActor())); + aliasRigidActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); + aliasRigidActor->moveKinematic(sourceShapeActorGlobalPose); +#endif //lioneltest diff --git a/APEX_1.4/module/destructible/src/DestructibleStructure.cpp b/APEX_1.4/module/destructible/src/DestructibleStructure.cpp new file mode 100644 index 00000000..4116948d --- /dev/null +++ b/APEX_1.4/module/destructible/src/DestructibleStructure.cpp @@ -0,0 +1,2414 @@ +/* + * 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. + */ + + +#include "ApexDefs.h" +#include "Apex.h" +#include "DestructibleStructure.h" +#include "DestructibleScene.h" +#include "ModuleDestructibleImpl.h" +#include "ModulePerfScope.h" +#include "PsIOStream.h" +#include <PxPhysics.h> +#include <PxScene.h> +#include "PxConvexMeshGeometry.h" + +#if APEX_USE_PARTICLES +#include "EmitterActor.h" +#include "EmitterGeoms.h" +#endif + +#include "RenderDebugInterface.h" +#include "DestructibleActorProxy.h" + +#include "DestructibleStructureStressSolver.h" + +#if APEX_RUNTIME_FRACTURE +#include "SimScene.h" +#endif + +#include "ApexMerge.h" + +namespace nvidia +{ +namespace destructible +{ +using namespace physx; + +// Local definitions + +#define REDUCE_DAMAGE_TO_CHILD_CHUNKS 1 + +// DestructibleStructure methods + +DestructibleStructure::DestructibleStructure(DestructibleScene* inScene, uint32_t inID) : + dscene(inScene), + ID(inID), + supportDepthChunksNotExternallySupportedCount(0), + supportInvalid(false), + actorForStaticChunks(NULL), + stressSolver(NULL) +{ +} + +DestructibleStructure::~DestructibleStructure() +{ + if(NULL != stressSolver) + { + PX_DELETE(stressSolver); + stressSolver = NULL; + dscene->setStressSolverTick(this, false); + } + + for (uint32_t destructibleIndex = destructibles.size(); destructibleIndex--;) + { + DestructibleActorImpl* destructible = destructibles[destructibleIndex]; + if (destructible) + { + destructible->setStructure(NULL); + dscene->mDestructibles.direct(destructible->getID()) = NULL; + dscene->mDestructibles.free(destructible->getID()); + } + } + + dscene->setStructureSupportRebuild(this, false); + dscene->setStructureUpdate(this, false); + + for (uint32_t i = 0; i < chunks.size(); ++i) + { + Chunk& chunk = chunks[i]; + if ((chunk.state & ChunkVisible) != 0) + { + physx::Array<PxShape*>& shapeArray = getChunkShapes(chunk); + for (uint32_t i = shapeArray.size(); i--;) + { + PxShape* shape = shapeArray[i]; + dscene->mModule->mSdk->releaseObjectDesc(shape); + physx::PxRigidDynamic* actor = shape->getActor()->is<PxRigidDynamic>(); + actor->detachShape(*shape); + if (dscene->mTotalChunkCount > 0) + { + --dscene->mTotalChunkCount; + } + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + if (actor->getNbShapes() == 0) + { + dscene->releasePhysXActor(*actor); + } + } + } + chunk.clearShapes(); +#if USE_CHUNK_RWLOCK + if (chunk.lock) + { + chunk.lock->~shdfnd::ReadWriteLock(); + PX_FREE(chunk.lock); + } + chunk.lock = NULL; +#endif + } + + actorToIsland.clear(); + islandToActor.clear(); + + dscene = NULL; + ID = (uint32_t)InvalidID; +} + +bool DestructibleStructure::addActors(const physx::Array<DestructibleActorImpl*>& destructiblesToAdd) +{ + PX_PROFILE_ZONE("DestructibleAddActors", GetInternalApexSDK()->getContextId()); + + // use the scene lock to protect chunk data for + // multi-threaded obbSweep calls on destructible actors + // (different lock would be good, but mixing locks can cause deadlocks) + SCOPED_PHYSX_LOCK_WRITE(dscene->mApexScene); + + const uint32_t oldDestructibleCount = destructibles.size(); + + const uint32_t destructibleCount = oldDestructibleCount + destructiblesToAdd.size(); + destructibles.resize(destructibleCount); + uint32_t totalAddedChunkCount = 0; + for (uint32_t destructibleIndex = oldDestructibleCount; destructibleIndex < destructibleCount; ++destructibleIndex) + { + DestructibleActorImpl* destructible = destructiblesToAdd[destructibleIndex - oldDestructibleCount]; + destructibles[destructibleIndex] = destructible; + totalAddedChunkCount += destructible->getDestructibleAsset()->getChunkCount(); + } + + const uint32_t oldChunkCount = chunks.size(); + const uint32_t chunkCount = oldChunkCount + totalAddedChunkCount; + chunks.resize(chunkCount); + + ApexSDKIntl* sdk = dscene->mModule->mSdk; + + // Fix chunk pointers in shapes that may have been moved because of the resize() operation + for (uint32_t chunkIndex = 0; chunkIndex < oldChunkCount; ++chunkIndex) + { + Chunk& chunk = chunks[chunkIndex]; + if ((chunk.state & ChunkVisible) != 0) + { + physx::Array<PxShape*>& shapeArray = getChunkShapes(chunk); + for (uint32_t i = shapeArray.size(); i--;) + { + PxShape* shape = shapeArray[i]; + if (shape != NULL) + { + PhysXObjectDescIntl* objDesc = sdk->getGenericPhysXObjectInfo(shape); + if (objDesc != NULL) + { + objDesc->userData = &chunk; + } + } + } + } + } + + uint32_t chunkIndex = oldChunkCount; + for (uint32_t destructibleIndex = oldDestructibleCount; destructibleIndex < destructibleCount; ++destructibleIndex) + { + DestructibleActorImpl* destructible = destructiblesToAdd[destructibleIndex - oldDestructibleCount]; + + const bool formsExtendedStructures = !destructible->isInitiallyDynamic() && destructible->formExtendedStructures(); + + if (!formsExtendedStructures) + { + PX_ASSERT(destructibleCount == 1); // All dynamic destructibles must be in their own structure + } + + destructible->setStructure(this); + PX_VERIFY(dscene->mDestructibles.useNextFree(destructible->getIDRef())); + dscene->mDestructibles.direct(destructible->getID()) = destructible; + + //PxVec3 destructibleScale = destructible->getScale(); + + destructible->setFirstChunkIndex(chunkIndex); + for (uint32_t i = 0; i < destructible->getDestructibleAsset()->getChunkCount(); ++i) + { + destructible->initializeChunk(i, chunks[chunkIndex++]); + } + // This should be done after all chunks are initialized, since it will traverse all chunks + Chunk& root = chunks[destructible->getFirstChunkIndex()]; + PX_ASSERT(root.isDestroyed()); // ensure shape pointer is still NULL + + // Create a new static actor if this is the first actor + if (destructibleIndex == 0) + { + // Disable visibility before creation + root.state &= ~(uint8_t)ChunkVisible; + PxRigidDynamic* rootActor = dscene->createRoot(root, PxTransform(destructible->getInitialGlobalPose()), destructible->isInitiallyDynamic()); + if (!destructible->isInitiallyDynamic() || destructible->initializedFromState()) + { + actorForStaticChunks = rootActor; + } + } + // Otherwise, append the new destructible actor's root chunk shapes to the existing root chunk's actor + // If the new destructible is initialized from state, defer chunk loading to ChunkLoadState + else if (!destructible->initializedFromState()) + { + DestructibleActorImpl* firstDestructible = dscene->mDestructibles.direct(chunks[0].destructibleID); + PxTransform relTM(firstDestructible->getInitialGlobalPose().inverseRT() * destructible->getInitialGlobalPose()); + if (actorForStaticChunks) + { + dscene->appendShapes(root, destructible->isInitiallyDynamic(), &relTM, actorForStaticChunks); + PhysXObjectDescIntl* objDesc = sdk->getGenericPhysXObjectInfo(actorForStaticChunks); + PX_ASSERT(objDesc->mApexActors.find(destructible->getAPI()) == objDesc->mApexActors.end()); + objDesc->mApexActors.pushBack(destructible->getAPI()); + destructible->referencedByActor(actorForStaticChunks); + } + else + { + // Disable visibility before creation + root.state &= ~(uint8_t)ChunkVisible; + PxRigidDynamic* rootActor = dscene->createRoot(root, PxTransform(destructible->getInitialGlobalPose()), destructible->isInitiallyDynamic()); + actorForStaticChunks = rootActor; + } + } + + destructible->setRelativeTMs(); + if (destructible->initializedFromState()) + { + DestructibleScene::ChunkLoadState chunkLoadState(*dscene); + dscene->forSubtree(root, chunkLoadState, false); + } + + destructible->setChunkVisibility(0, destructible->getInitialChunkVisible(root.indexInAsset)); + // init bounds + destructible->setRenderTMs(); + } + + dscene->setStructureSupportRebuild(this, true); + + return true; +} + +struct Ptr_LT +{ + PX_INLINE bool operator()(void* a, void* b) const + { + return a < b; + } +}; + +bool DestructibleStructure::removeActor(DestructibleActorImpl* destructibleToRemove) +{ + PX_PROFILE_ZONE("DestructibleRemoveActor", GetInternalApexSDK()->getContextId()); + + // use the scene lock to protect chunk data for + // multi-threaded obbSweep calls on destructible actors + // (different lock would be good, but mixing locks can cause deadlocks) + SCOPED_PHYSX_LOCK_WRITE(dscene->mApexScene); + + if (destructibleToRemove->getStructure() != this) + { + return false; // Destructible not in structure + } + + const uint32_t oldDestructibleCount = destructibles.size(); + + uint32_t destructibleIndex = 0; + for (; destructibleIndex < oldDestructibleCount; ++destructibleIndex) + { + if (destructibles[destructibleIndex] == destructibleToRemove) + { + break; + } + } + + if (destructibleIndex == oldDestructibleCount) + { + return false; // Destructible not in structure + } + + // Remove chunks (releases shapes) and ensure we dissociate from their actors. + // Note: if we're not in a structure, releasing shapes will always release the actors, which releases the actorObjDesc, thus dissociating us. + // But if we're in a structure, some other destructible might have shapes in the actor, and we won't get dissociated. This is why we must + // Go through the trouble of ensuring dissociation here. + physx::Array<void*> dissociatedActors; + uint32_t visibleChunkCount = destructibleToRemove->getNumVisibleChunks(); // Do it this way in case removeChunk doesn't work for some reason + while (visibleChunkCount--) + { + const uint16_t chunkIndex = destructibleToRemove->getVisibleChunks()[destructibleToRemove->getNumVisibleChunks()-1]; + DestructibleStructure::Chunk& chunk = chunks[chunkIndex + destructibleToRemove->getFirstChunkIndex()]; + PxRigidDynamic* actor = getChunkActor(chunk); + if (actor != NULL) + { + dissociatedActors.pushBack(actor); + } + removeChunk(chunk); + } + + // Now sort the actor pointers so we only deal with each once + const uint32_t dissociatedActorCount = dissociatedActors.size(); + if (dissociatedActorCount > 1) + { + nvidia::sort<void*, Ptr_LT>(&dissociatedActors[0], dissociatedActors.size(), Ptr_LT()); + } + + // Run through the sorted list + void* lastActor = NULL; + for (uint32_t actorNum = 0; actorNum < dissociatedActorCount; ++actorNum) + { + void* nextActor = dissociatedActors[actorNum]; + if (nextActor != lastActor) + { + PhysXObjectDescIntl* actorObjDesc = dscene->mModule->mSdk->getGenericPhysXObjectInfo(nextActor); + if (actorObjDesc != NULL) + { + for (uint32_t i = actorObjDesc->mApexActors.size(); i--;) + { + if (actorObjDesc->mApexActors[i] == destructibleToRemove->getAPI()) + { + actorObjDesc->mApexActors.replaceWithLast(i); + destructibleToRemove->unreferencedByActor((PxRigidDynamic*)nextActor); + } + } + if (actorObjDesc->mApexActors.size() == 0) + { + dscene->releasePhysXActor(*static_cast<PxRigidDynamic*>(nextActor)); + } + } + lastActor = nextActor; + } + } + + // Also check the actor for static chunks + if (actorForStaticChunks != NULL) + { + PhysXObjectDescIntl* actorObjDesc = dscene->mModule->mSdk->getGenericPhysXObjectInfo(actorForStaticChunks); + if (actorObjDesc != NULL) + { + for (uint32_t i = actorObjDesc->mApexActors.size(); i--;) + { + if (actorObjDesc->mApexActors[i] == destructibleToRemove->getAPI()) + { + actorObjDesc->mApexActors.replaceWithLast(i); + destructibleToRemove->unreferencedByActor(actorForStaticChunks); + } + } + if (actorObjDesc->mApexActors.size() == 0) + { + dscene->releasePhysXActor(*static_cast<PxRigidDynamic*>(actorForStaticChunks)); + } + } + } + + const uint32_t destructibleToRemoveFirstChunkIndex = destructibleToRemove->getFirstChunkIndex(); + const uint32_t destructibleToRemoveChunkCount = destructibleToRemove->getDestructibleAsset()->getChunkCount(); + const uint32_t destructibleToRemoveChunkIndexStop = destructibleToRemoveFirstChunkIndex + destructibleToRemoveChunkCount; + + destructibleToRemove->setStructure(NULL); + + // Compact destructibles array + for (; destructibleIndex < oldDestructibleCount-1; ++destructibleIndex) + { + destructibles[destructibleIndex] = destructibles[destructibleIndex+1]; + const uint32_t firstChunkIndex = destructibles[destructibleIndex]->getFirstChunkIndex(); + PX_ASSERT(firstChunkIndex >= destructibleToRemoveChunkCount); + destructibles[destructibleIndex]->setFirstChunkIndex(firstChunkIndex - destructibleToRemoveChunkCount); + } + destructibles.resize(oldDestructibleCount-1); + + // Compact chunks array + chunks.removeRange(destructibleToRemoveFirstChunkIndex, destructibleToRemoveChunkCount); + const uint32_t chunkCount = chunks.size(); + + ApexSDKIntl* sdk = dscene->mModule->mSdk; + + // Fix chunk pointers in shapes that may have been moved because of the removeRange() operation + for (uint32_t chunkIndex = destructibleToRemoveFirstChunkIndex; chunkIndex < chunkCount; ++chunkIndex) + { + Chunk& chunk = chunks[chunkIndex]; + if (chunk.visibleAncestorIndex != (int32_t)InvalidChunkIndex) + { + chunk.visibleAncestorIndex -= destructibleToRemoveChunkCount; + } + for (uint32_t i = chunk.shapes.size(); i--;) + { + PxShape* shape = chunk.shapes[i]; + if (shape != NULL) + { + PhysXObjectDescIntl* objDesc = sdk->getGenericPhysXObjectInfo(shape); + if (objDesc != NULL) + { + objDesc->userData = &chunk; + } + } + } + } + + // Remove obsolete support info + uint32_t newSupportChunkNum = 0; + PX_ASSERT(supportDepthChunksNotExternallySupportedCount <= supportDepthChunks.size()); + for (uint32_t supportChunkNum = 0; supportChunkNum < supportDepthChunksNotExternallySupportedCount; ++supportChunkNum) + { + const uint32_t supportChunkIndex = supportDepthChunks[supportChunkNum]; + if (supportChunkIndex < destructibleToRemoveFirstChunkIndex) + { + // This chunk index will not be affected + supportDepthChunks[newSupportChunkNum++] = supportChunkIndex; + } + else + if (supportChunkIndex >= destructibleToRemoveChunkIndexStop) + { + // This chunk index will be affected + supportDepthChunks[newSupportChunkNum++] = supportChunkIndex - destructibleToRemoveChunkCount; + } + } + + const uint32_t newSupportDepthChunksNotExternallySupportedCount = newSupportChunkNum; + + for (uint32_t supportChunkNum = supportDepthChunksNotExternallySupportedCount; supportChunkNum < supportDepthChunks.size(); ++supportChunkNum) + { + const uint32_t supportChunkIndex = supportDepthChunks[supportChunkNum]; + if (supportChunkIndex < destructibleToRemoveFirstChunkIndex) + { + // This chunk index will not be affected + supportDepthChunks[newSupportChunkNum++] = supportChunkIndex; + } + else + if (supportChunkIndex >= destructibleToRemoveChunkIndexStop) + { + // This chunk index will be affected + supportDepthChunks[newSupportChunkNum++] = supportChunkIndex - destructibleToRemoveChunkCount; + } + } + + supportDepthChunksNotExternallySupportedCount = newSupportDepthChunksNotExternallySupportedCount; + supportDepthChunks.resize(newSupportChunkNum); + + dscene->setStructureSupportRebuild(this, true); + + return true; +} + + +void DestructibleStructure::updateIslands() +{ + PX_PROFILE_ZONE("DestructibleStructureUpdateIslands", GetInternalApexSDK()->getContextId()); + + // islandToActor is used within a single frame to reconstruct deserialized islands. + // After that frame, there are no guarantees on island recreation within + // a single structure between multiple actors. Thus we reset it each frame. + if (islandToActor.size()) + { + islandToActor.clear(); + } + + if (supportInvalid) + { + separateUnsupportedIslands(); + } +} + + +void DestructibleStructure::tickStressSolver(float deltaTime) +{ + PX_PROFILE_ZONE("DestructibleStructureTickStressSolver", GetInternalApexSDK()->getContextId()); + + PX_ASSERT(stressSolver != NULL); + if (stressSolver == NULL) + return; + + if(stressSolver->isPhysxBasedSim) + { + if(stressSolver->isCustomEnablesSimulating) + { + stressSolver->physcsBasedStressSolverTick(); + } + } + else + { + stressSolver->onTick(deltaTime); + if (supportInvalid) + { + stressSolver->onResolve(); + } + } +} + +PX_INLINE uint32_t colorFromUInt(uint32_t x) +{ + x = (x % 26) + 1; + uint32_t rIndex = x / 9; + x -= rIndex * 9; + uint32_t gIndex = x / 3; + uint32_t bIndex = x - gIndex * 3; + uint32_t r = (rIndex << 7) - (uint32_t)(rIndex != 0); + uint32_t g = (gIndex << 7) - (uint32_t)(gIndex != 0); + uint32_t b = (bIndex << 7) - (uint32_t)(bIndex != 0); + return 0xFF000000 | r << 16 | g << 8 | b; +} + +void DestructibleStructure::visualizeSupport(RenderDebugInterface* debugRender) +{ +#ifdef WITHOUT_DEBUG_VISUALIZE + PX_UNUSED(debugRender); +#else + + // apparently if this method is called before an actor is ever stepped bad things can happen + if (firstOverlapIndices.size() == 0) + { + return; + } + + for (uint32_t i = 0; i < supportDepthChunks.size(); ++i) + { + uint32_t chunkIndex = supportDepthChunks[i]; + Chunk& chunk = chunks[chunkIndex]; + PxRigidDynamic* chunkActor = dscene->chunkIntact(chunk); + if (chunkActor != NULL) + { + SCOPED_PHYSX_LOCK_READ(chunkActor->getScene()); + PhysXObjectDesc* actorObjDesc = (PhysXObjectDesc*) dscene->mModule->mSdk->getPhysXObjectInfo(chunkActor); + uint32_t color = colorFromUInt((uint32_t)(-(intptr_t)actorObjDesc->userData)); + RENDER_DEBUG_IFACE(debugRender)->setCurrentColor(color); + PxVec3 actorCentroid = (chunkActor->getGlobalPose() * PxTransform(chunk.localSphereCenter)).p; + const PxVec3 chunkCentroid = !chunk.isDestroyed() ? getChunkWorldCentroid(chunk) : actorCentroid; + const uint32_t firstOverlapIndex = firstOverlapIndices[chunkIndex]; + const uint32_t stopOverlapIndex = firstOverlapIndices[chunkIndex + 1]; + for (uint32_t j = firstOverlapIndex; j < stopOverlapIndex; ++j) + { + uint32_t overlapChunkIndex = overlaps[j]; + if (overlapChunkIndex > chunkIndex) + { + Chunk& overlapChunk = chunks[overlapChunkIndex]; + PxRigidDynamic* overlapChunkActor = dscene->chunkIntact(overlapChunk); + if (overlapChunkActor == chunkActor || + (overlapChunkActor != NULL && + chunkActor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC && + overlapChunkActor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC)) + { + PxVec3 actorCentroid = (overlapChunkActor->getGlobalPose() * PxTransform(overlapChunk.localSphereCenter)).p; + const PxVec3 overlapChunkCentroid = !overlapChunk.isDestroyed() ? getChunkWorldCentroid(overlapChunk) : actorCentroid; + // Draw line from chunkCentroid to overlapChunkCentroid + RENDER_DEBUG_IFACE(debugRender)->debugLine(chunkCentroid, overlapChunkCentroid); + } + } + } + if (chunk.flags & ChunkExternallySupported) + { + // Draw mark at chunkCentroid + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + if (destructible) + { + PxBounds3 bounds = destructible->getDestructibleAsset()->getChunkShapeLocalBounds(chunk.indexInAsset); + PxMat44 tm; + if (chunk.isDestroyed()) + { + tm = PxMat44(chunkActor->getGlobalPose()); + } + else + { + tm = PxMat44(getChunkGlobalPose(chunk)); + } + tm.scale(PxVec4(destructible->getScale(), 1.f)); + PxBounds3Transform(bounds, tm); + RENDER_DEBUG_IFACE(debugRender)->debugBound(bounds); + } + } + } + } +#endif +} + +uint32_t DestructibleStructure::damageChunk(Chunk& chunk, const PxVec3& position, const PxVec3& direction, bool fromImpact, float damage, float damageRadius, + physx::Array<FractureEvent> outputs[], uint32_t& possibleDeleteChunks, float& totalDeleteChunkRelativeDamage, + uint32_t& maxDepth, uint32_t depth, uint16_t stopDepth, float padding) +{ + if (depth > DamageEvent::MaxDepth || depth > (uint32_t)stopDepth) + { + return 0; + } + + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + + if (depth > destructible->getLOD()) + { + return 0; + } + + physx::Array<FractureEvent>& output = outputs[depth]; + + const DestructibleAssetParametersNS::Chunk_Type& source = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk.indexInAsset]; + + if (source.flags & DestructibleAssetImpl::UnfracturableChunk) + { + return 0; + } + + if (chunk.isDestroyed()) + { + return 0; + } + + const DestructibleParameters& destructibleParameters = destructible->getDestructibleParameters(); + + const uint32_t originalEventBufferSize = output.size(); + + const bool hasChildren = source.numChildren != 0 && depth < destructible->getLOD(); + + // Support legacy behavior + const bool useLegacyChunkOverlap = destructible->getUseLegacyChunkBoundsTesting(); + const bool useLegacyDamageSpread = destructible->getUseLegacyDamageRadiusSpread(); + + // Get behavior group + const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = destructible->getBehaviorGroupImp(source.behaviorGroupIndex); + + // Get radial info from behavior group + float minRadius = 0.0f; + float maxRadius = 0.0f; + float falloff = 1.0f; + if (!useLegacyDamageSpread) + { + // New behavior + minRadius = behaviorGroup.damageSpread.minimumRadius; + falloff = behaviorGroup.damageSpread.falloffExponent; + + if (!fromImpact) + { + maxRadius = minRadius + damageRadius*behaviorGroup.damageSpread.radiusMultiplier; + } + else + { + maxRadius = behaviorGroup.damageToRadius; + if (behaviorGroup.damageThreshold > 0) + { + maxRadius *= damage / behaviorGroup.damageThreshold; + } + } + } + else + { + // Legacy behavior + if (damageRadius == 0.0f) + { + maxRadius = destructible->getLinearSize() * behaviorGroup.damageToRadius; + if (behaviorGroup.damageThreshold > 0) + { + maxRadius *= damage / behaviorGroup.damageThreshold; + } + } + else + { + maxRadius = damageRadius; + } + } + + float overlapDistance = PX_MAX_F32; + if (!useLegacyChunkOverlap) + { + destructible->getDestructibleAsset()->chunkAndSphereInProximity(chunk.indexInAsset, destructible->getChunkPose(chunk.indexInAsset), destructible->getScale(), position, maxRadius, padding, &overlapDistance); + } + else + { + PxVec3 disp = getChunkWorldCentroid(chunk) - position; + float dist = disp.magnitude(); + overlapDistance = dist - maxRadius; + padding = 0.0f; // Note we're overriding the function parameter here, as it didn't exist in the old (legacy) code + if (!hasChildren) // Test against bounding sphere for smallest chunks + { + overlapDistance -= chunk.localSphereRadius; + } + } + + uint32_t fractureCount = 0; + + const float recipRadiusRange = maxRadius > minRadius ? 1.0f/(maxRadius - minRadius) : 0.0f; + + const bool canFracture = + source.depth >= (uint16_t)destructibleParameters.minimumFractureDepth && // At or deeper than minimum fracture depth + (source.flags & DestructibleAssetImpl::DescendantUnfractureable) == 0 && // Some descendant cannot be fractured + (source.flags & DestructibleAssetImpl::UndamageableChunk) == 0 && // This chunk is not to be fractured (though a descendant may be) + (useLegacyChunkOverlap || source.depth >= destructible->getSupportDepth()); // If we're using the new chunk overlap tests, we will only fracture at or deeper than the support depth + + const bool canCrumble = (destructibleParameters.flags & DestructibleParametersFlag::CRUMBLE_SMALLEST_CHUNKS) != 0 && (source.flags & DestructibleAssetImpl::UncrumbleableChunk) == 0; + + const bool forceCrumbleOrRTFracture = + source.depth < (uint16_t)destructibleParameters.minimumFractureDepth && // minimum fracture depth deeper than this chunk + !hasChildren && // leaf chunk + (canCrumble || (destructibleParameters.flags & DestructibleParametersFlag::CRUMBLE_VIA_RUNTIME_FRACTURE) != 0); // set to crumble or RT fracture + + if (canFracture || forceCrumbleOrRTFracture) + { + uint32_t virtualEventFlag = 0; + for (uint32_t it = 0; it < 2; ++it) // Try once as a real event, then possibly as a virtual event + { + if (overlapDistance < padding) // Overlap distance can change + { + float damageFraction = 1; + if (!useLegacyDamageSpread) + { + const float radius = maxRadius + overlapDistance; + if (radius > minRadius && recipRadiusRange > 0.0f) + { + if (radius < maxRadius) + { + damageFraction = PxPow( (maxRadius - radius)*recipRadiusRange, falloff); + } + else + { + damageFraction = 0.0f; + } + } + } + else + { + if (falloff > 0.0f && maxRadius > 0.0f) + { + damageFraction -= PxMax((maxRadius + overlapDistance) / maxRadius, 0.0f); + } + } + const float oldChunkDamage = chunk.damage; + float effectiveDamage = damageFraction * damage; + chunk.damage += effectiveDamage; + + if ((chunk.damage >= behaviorGroup.damageThreshold) || (fromImpact && (behaviorGroup.materialStrength > 0)) || forceCrumbleOrRTFracture) + { + chunk.damage = behaviorGroup.damageThreshold; + // Fracture +#if REDUCE_DAMAGE_TO_CHILD_CHUNKS + if (it == 0) + { + damage -= chunk.damage - oldChunkDamage; + } +#endif + // this is an alternative deletion path (instead of using the delete flag on the fracture event) + // this can allow us to skip some parts of damageChunk() and fractureChunk(), but it involves duplicating some code + // we are still relying on the delete flag for now + if(destructible->mInDeleteChunkMode && false) + { + removeChunk(chunks[chunk.indexInAsset]); + uint16_t parentIndex = source.parentIndex; + + Chunk* rootChunk = getRootChunk(chunk); + const bool dynamic = rootChunk != NULL ? (rootChunk->state & ChunkDynamic) != 0 : false; + if(!dynamic) + { + Chunk* parent = (parentIndex != DestructibleAssetImpl::InvalidChunkIndex) ? &chunks[parentIndex + destructible->getFirstChunkIndex()] : NULL; + const DestructibleAssetParametersNS::Chunk_Type* parentSource = parent ? (destructible->getDestructibleAsset()->mParams->chunks.buf + parent->indexInAsset) : NULL; + const uint32_t startIndex = parentSource ? parentSource->firstChildIndex + destructible->getFirstChunkIndex() : chunk.indexInAsset /* + actor first index */; + const uint32_t stopIndex = parentSource ? startIndex + parentSource->numChildren : startIndex + 1; + // Walk children of current parent (siblings) + for (uint32_t childIndex = startIndex; childIndex < stopIndex; ++childIndex) + { + Chunk& child = chunks[childIndex]; + if (child.isDestroyed()) + { + continue; + } + bool belowSupportDepth = (child.flags & ChunkBelowSupportDepth) != 0; + if (&child != &chunk && !belowSupportDepth) + { + // this is a sibling, which we can keep because we're at a supported depth or above + if ((child.state & ChunkVisible) == 0) + { + // Make this chunk shape visible, attach to root bone + if (dscene->appendShapes(child, dynamic)) + { + destructible->setChunkVisibility(child.indexInAsset, true); + } + } + } + } + } + + while(parentIndex != DestructibleAssetImpl::InvalidChunkIndex) + { + Chunk * parent = &chunks[parentIndex + destructible->getFirstChunkIndex()]; + if(parent->state & ChunkVisible) + { + removeChunk(*parent); + } + PX_ASSERT(parent->indexInAsset == parentIndex + destructible->getFirstChunkIndex()); + parentIndex = destructible->getDestructibleAsset()->mParams->chunks.buf[parent->indexInAsset].parentIndex; + } + } + else + { + FractureEvent& fractureEvent = output.insert(); + fractureEvent.position = position; + fractureEvent.impulse = PxVec3(0.0f); + fractureEvent.chunkIndexInAsset = chunk.indexInAsset; + fractureEvent.destructibleID = destructible->getID(); + fractureEvent.flags = virtualEventFlag; + fractureEvent.damageFraction = damageFraction; + const bool normalCrumbleCondition = canCrumble && !hasChildren && damageFraction*damage >= behaviorGroup.damageThreshold; + if (it == 0 && (normalCrumbleCondition || forceCrumbleOrRTFracture)) + { + // Crumble + fractureEvent.flags |= FractureEvent::CrumbleChunk; + } + fractureEvent.deletionWeight = 0.0f; + if (destructibleParameters.debrisDepth >= 0 && source.depth >= (uint16_t)destructibleParameters.debrisDepth) + { + ++possibleDeleteChunks; +// const float relativeDamage = behaviorGroup.damageThreshold > 0.0f ? effectiveDamage/behaviorGroup.damageThreshold : 1.0f; + fractureEvent.deletionWeight = 1.0f;// - PxExp(-relativeDamage); // Flat probability for now + totalDeleteChunkRelativeDamage += fractureEvent.deletionWeight; + } + } + } + if (!(destructibleParameters.flags & DestructibleParametersFlag::ACCUMULATE_DAMAGE)) + { + chunk.damage = 0; + } + if (it == 1) + { + chunk.damage = oldChunkDamage; + } + } + + if (it == 1) + { + break; + } + + fractureCount = output.size() - originalEventBufferSize; + if (!hasChildren || fractureCount > 0) + { + break; + } + + if (useLegacyChunkOverlap) + { + // Try treating this as a childless chunk. + overlapDistance -= chunk.localSphereRadius; + } + + // If we have bounding sphere overlap, mark it as a virtual fracture event + virtualEventFlag = FractureEvent::Virtual; + } + } + else + if (useLegacyChunkOverlap) + { + // Legacy system relied on this being done in the loop above (in the other branch of the conditional) + overlapDistance -= chunk.localSphereRadius; + } + + if (fractureCount > 0) + { + maxDepth = PxMax(depth, maxDepth); + } + + if (hasChildren && overlapDistance < padding && depth < (uint32_t)stopDepth) + { + // Recurse + const uint32_t startIndex = source.firstChildIndex + destructible->getFirstChunkIndex(); + const uint32_t stopIndex = startIndex + source.numChildren; + for (uint32_t childIndex = startIndex; childIndex < stopIndex; ++childIndex) + { + fractureCount += damageChunk(chunks[childIndex], position, direction, fromImpact, damage, damageRadius, outputs, + possibleDeleteChunks, totalDeleteChunkRelativeDamage, maxDepth, depth + 1, stopDepth, padding); + } + } + + return fractureCount; +} + + +/* + fractureChunk causes the chunk referenced in fractureEvent to become a dynamic, standalone chunk. + + If the chunk was invisible because it was an ancestor of a visible chunk, then the ancestor will desroyed, + and appropriate descendants (including the chunk in question) will be made visible. + + Any chunks which become visible that are at, or deeper than, the support depth will also become standalone + dynamic chunks. +*/ + +void DestructibleStructure::fractureChunk(const FractureEvent& fractureEvent) +{ + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(fractureEvent.destructibleID); + if (!destructible) + { + return; + } + + destructible->wakeForEvent(); + + // ===SyncParams=== + if(0 != destructible->getSyncParams().getUserActorID()) + { + destructible->evaluateForHitChunkList(fractureEvent); + } + + Chunk& chunk = chunks[fractureEvent.chunkIndexInAsset + destructible->getFirstChunkIndex()]; + + const PxVec3& position = fractureEvent.position; + const PxVec3& impulse = fractureEvent.impulse; + if(fractureEvent.flags & FractureEvent::CrumbleChunk) + { + chunk.flags |= ChunkCrumbled; + } + + const DestructibleAssetParametersNS::Chunk_Type& source = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk.indexInAsset]; + + if ((fractureEvent.flags & FractureEvent::Forced) == 0 && (source.flags & DestructibleAssetImpl::UnfracturableChunk) != 0) + { + return; + } + + if (chunk.isDestroyed()) + { + return; + } + +#if APEX_RUNTIME_FRACTURE + // The runtime fracture flag pre-empts the crumble flag + if (source.flags & DestructibleAssetImpl::RuntimeFracturableChunk) + { + chunk.flags |= ChunkRuntime; + chunk.flags &= ~(uint8_t)ChunkCrumbled; + } +#endif + + bool loneDynamicShape = false; + if ((chunk.state & ChunkVisible) != 0 && chunkIsSolitary(chunk) && (chunk.state & ChunkDynamic) != 0) + { + loneDynamicShape = true; + } + + uint16_t depth = source.depth; + + PxRigidDynamic* actor = getChunkActor(chunk); + PX_ASSERT(actor != NULL); + + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + bool isKinematic = actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC; + + if (loneDynamicShape) + { + if(0 == (fractureEvent.flags & FractureEvent::Manual)) // if it is a manual fractureEvent, we do not consider giving it an impulse nor to crumble it + { + if (isKinematic) + { + PhysXObjectDescIntl* actorObjDesc = (PhysXObjectDescIntl*)dscene->mModule->mSdk->getPhysXObjectInfo(actor); + if (actorObjDesc != NULL) + { + uintptr_t& cindex = (uintptr_t&)actorObjDesc->userData; + if (cindex != 0) + { + // Dormant actor - turn dynamic + const uint32_t dormantActorIndex = (uint32_t)~cindex; + DormantActorEntry& dormantActorEntry = dscene->mDormantActors.direct(dormantActorIndex); + dormantActorEntry.actor = NULL; + dscene->mDormantActors.free(dormantActorIndex); + cindex = (uintptr_t)0; + { + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, false); + dscene->addActor(*actorObjDesc, *actor, dormantActorEntry.unscaledMass, + ((dormantActorEntry.flags & ActorFIFOEntry::IsDebris) != 0)); + actor->wakeUp(); + } + isKinematic = false; + } + } + } + + if (!isKinematic && impulse.magnitudeSquared() > 0.0f && ((chunk.flags & ChunkCrumbled) != 0 || (fractureEvent.flags & FractureEvent::DamageFromImpact) == 0)) + { + addChunkImpluseForceAtPos(chunk, impulse, position); + } + if ((chunk.flags & ChunkCrumbled)) + { + crumbleChunk(fractureEvent, chunk); + } +#if APEX_RUNTIME_FRACTURE + else if ((chunk.flags & ChunkRuntime)) + { + runtimeFractureChunk(fractureEvent, chunk); + } +#endif + return; + } + } + + Chunk* rootChunk = getRootChunk(chunk); + const bool dynamic = rootChunk != NULL ? (rootChunk->state & ChunkDynamic) != 0 : false; + + uint16_t parentIndex = source.parentIndex; + uint32_t chunkIndex = chunk.indexInAsset + destructible->getFirstChunkIndex(); + + //Sync the shadow scene if using physics based stress solver + if(stressSolver&&stressSolver->isPhysxBasedSim) + { + stressSolver->removeChunkFromShadowScene(false,chunkIndex); + } + for (;;) + { + Chunk* parent = (parentIndex != DestructibleAssetImpl::InvalidChunkIndex) ? &chunks[parentIndex + destructible->getFirstChunkIndex()] : NULL; + const DestructibleAssetParametersNS::Chunk_Type* parentSource = parent ? (destructible->getDestructibleAsset()->mParams->chunks.buf + parent->indexInAsset) : NULL; + const uint32_t startIndex = parentSource ? parentSource->firstChildIndex + destructible->getFirstChunkIndex() : chunkIndex; + const uint32_t stopIndex = parentSource ? startIndex + parentSource->numChildren : startIndex + 1; + // Walk children of current parent (siblings) + for (uint32_t childIndex = startIndex; childIndex < stopIndex; ++childIndex) + { + Chunk& child = chunks[childIndex]; + if (child.isDestroyed()) + { + continue; + } + + bool belowSupportDepth = (child.flags & ChunkBelowSupportDepth) != 0; + + if (&child != &chunk && !belowSupportDepth) + { + // this is a sibling, which we can keep because we're at a supported depth or above + if ((child.state & ChunkVisible) == 0) + { + // Make this chunk shape visible, attach to root bone + dscene->appendShapes(child, dynamic); + destructible->setChunkVisibility(child.indexInAsset, true); + } + } + else if (child.flags & ChunkCrumbled) + { + // This chunk needs to be crumbled + if (isKinematic) + { + crumbleChunk(fractureEvent, child, &impulse); + } + else + { + if (impulse.magnitudeSquared() > 0.0f) + { + addChunkImpluseForceAtPos(child, impulse, position); + } + crumbleChunk(fractureEvent, child); + } + if (parent) + { + parent->flags |= ChunkMissingChild; + } + setSupportInvalid(true); + } +#if APEX_RUNTIME_FRACTURE + else if (child.flags & ChunkRuntime) + { + runtimeFractureChunk(fractureEvent, child); + if (parent) + { + parent->flags |= ChunkMissingChild; + } + setSupportInvalid(true); + } +#endif + else + { + // This is either the chunk or a sibling, which we are breaking off + if ((fractureEvent.flags & FractureEvent::Silent) == 0 && dscene->mModule->m_chunkReport != NULL) + { + dscene->createChunkReportDataForFractureEvent(fractureEvent, destructible, child); + } + destructible->setChunkVisibility(child.indexInAsset, false); // In case its mesh changes + + // if the fractureEvent is manually generated, we remove the chunk instead of simulating it + if(0 != (fractureEvent.flags & FractureEvent::DeleteChunk)) + { + removeChunk(child); + } + else + { + PX_ASSERT(0 == (fractureEvent.flags & FractureEvent::DeleteChunk)); + PxRigidDynamic* oldActor = getChunkActor(child); + PxRigidDynamic* newActor = dscene->createRoot(child, getChunkGlobalPose(child), true); + if (newActor != NULL && oldActor == actor) + { + physx::PxRigidDynamic* newRigidDynamic = newActor->is<physx::PxRigidDynamic>(); + PxVec3 childCenterOfMass = newRigidDynamic->getGlobalPose().transform(newRigidDynamic->getCMassLocalPose().p); + { + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + newActor->setLinearVelocity(physx::PxRigidBodyExt::getVelocityAtPos(*actor, childCenterOfMass)); + newActor->setAngularVelocity(actor->getAngularVelocity()); + } + } + } + + PX_ASSERT(child.isDestroyed() == ((child.state & ChunkVisible) == 0)); + if (!child.isDestroyed()) + { + destructible->setChunkVisibility(child.indexInAsset, true); + if (&child == &chunk) + { + if (impulse.magnitudeSquared() > 0.0f) + { + // Bring position nearer to chunk for better effect + PxVec3 newPosition = position; + const PxVec3 c = getChunkWorldCentroid(child); + const PxVec3 disp = newPosition - c; + const float d2 = disp.magnitudeSquared(); + if (d2 > child.localSphereRadius * child.localSphereRadius) + { + newPosition = c + disp * (disp.magnitudeSquared() * PxRecipSqrt(d2)); + } + addChunkImpluseForceAtPos(child, impulse, newPosition); + } + } + addDust(child); + } + if (parent) + { + parent->flags |= ChunkMissingChild; + } + setSupportInvalid(true); + } + } + if (!parent) + { + break; + } + if (parent->state & ChunkVisible) + { + removeChunk(*parent); + } + else if (parent->isDestroyed()) + { + break; + } + parent->clearShapes(); + chunkIndex = parentIndex; + parentIndex = parentSource->parentIndex; + PX_ASSERT(depth > 0); + if (depth > 0) + { + --depth; + } + } + + dscene->capDynamicActorCount(); +} + +void DestructibleStructure::crumbleChunk(const FractureEvent& fractureEvent, Chunk& chunk, const PxVec3* impulse) +{ + if (chunk.isDestroyed()) + { + return; + } + + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + +#if APEX_RUNTIME_FRACTURE + if ((destructible->getDestructibleParameters().flags & DestructibleParametersFlag::CRUMBLE_VIA_RUNTIME_FRACTURE) != 0) + { + runtimeFractureChunk(fractureEvent, chunk); + return; + } +#else + PX_UNUSED(fractureEvent); +#endif + + dscene->getChunkReportData(chunk, ApexChunkFlag::DESTROYED_CRUMBLED); + + PX_ASSERT(chunk.reportID < dscene->mChunkReportHandles.size() || chunk.reportID == DestructibleScene::InvalidReportID); + if (chunk.reportID < dscene->mChunkReportHandles.size()) + { + IntPair& handle = dscene->mChunkReportHandles[chunk.reportID]; + if ( (uint32_t)handle.i0 < dscene->mDamageEventReportData.size() ) + { + ApexDamageEventReportDataImpl& DamageEventReport = dscene->mDamageEventReportData[(uint32_t)handle.i0]; + + DamageEventReport.impactDamageActor = fractureEvent.impactDamageActor; + DamageEventReport.appliedDamageUserData = fractureEvent.appliedDamageUserData; + DamageEventReport.hitPosition = fractureEvent.position; + DamageEventReport.hitDirection = fractureEvent.hitDirection; + } + } + + EmitterActor* emitterToUse = destructible->getCrumbleEmitter() && destructible->isCrumbleEmitterEnabled() ? destructible->getCrumbleEmitter() : NULL; + + const float crumbleParticleSpacing = destructible->getCrumbleParticleSpacing(); + + if (crumbleParticleSpacing > 0.0f && (emitterToUse != NULL || dscene->mModule->m_chunkCrumbleReport != NULL)) + { + physx::Array<PxVec3> volumeFillPos; + /// \todo expose jitter + const float jitter = 0.25f; + for (uint32_t hullIndex = destructible->getDestructibleAsset()->getChunkHullIndexStart(chunk.indexInAsset); hullIndex < destructible->getDestructibleAsset()->getChunkHullIndexStop(chunk.indexInAsset); ++hullIndex) + { + destructible->getDestructibleAsset()->chunkConvexHulls[hullIndex].fill(volumeFillPos, getChunkGlobalPose(chunk), destructible->getScale(), destructible->getCrumbleParticleSpacing(), jitter, 250, true); + } + destructible->spawnParticles(emitterToUse, dscene->mModule->m_chunkCrumbleReport, chunk, volumeFillPos, true, impulse); + } + + if (chunk.state & ChunkVisible) + { + removeChunk(chunk); + } +} + +#if APEX_RUNTIME_FRACTURE +void DestructibleStructure::runtimeFractureChunk(const FractureEvent& fractureEvent, Chunk& chunk) +{ + if (chunk.isDestroyed()) + { + return; + } + + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + PX_UNUSED(destructible); + + if (destructible->getRTActor() != NULL) + { + destructible->getRTActor()->patternFracture(fractureEvent,true); + } + + if (chunk.state & ChunkVisible) + { + removeChunk(chunk); + } +} +#endif + +void DestructibleStructure::addDust(Chunk& chunk) +{ + PX_UNUSED(chunk); +#if 0 // Not implementing dust in 1.2.0 + if (chunk.isDestroyed()) + { + return; + } + + DestructibleActor* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + + EmitterActor* emitterToUse = destructible->getDustEmitter() && destructible->getDustEmitter() ? destructible->getDustEmitter() : NULL; + + const float dustParticleSpacing = destructible->getDustParticleSpacing(); + + if (dustParticleSpacing > 0.0f && (emitterToUse != NULL || dscene->mModule->m_chunkDustReport != NULL)) + { + physx::Array<PxVec3> tracePos; + /// \todo expose jitter + const float jitter = 0.25f; + destructible->getAsset()->traceSurfaceBoundary(tracePos, chunk.indexInAsset, getChunkGlobalPose(chunk), destructible->getScale(), dustParticleSpacing, jitter, 0.5f * dustParticleSpacing, 250); + destructible->spawnParticles(emitterToUse, dscene->mModule->m_chunkDustReport, chunk, tracePos); + } +#endif +} + +void DestructibleStructure::removeChunk(Chunk& chunk) +{ + dscene->scheduleChunkShapesForDelete(chunk); + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + + //Sync the shadow scene if using physics based stress solver + if(stressSolver&&stressSolver->isPhysxBasedSim) + { + uint32_t chunkIndex = chunk.indexInAsset + destructible->getFirstChunkIndex(); + stressSolver->removeChunkFromShadowScene(false,chunkIndex); + } + destructible->setChunkVisibility(chunk.indexInAsset, false); + const DestructibleAssetParametersNS::Chunk_Type& source = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk.indexInAsset]; + if (source.parentIndex != DestructibleAssetImpl::InvalidChunkIndex) + { + Chunk& parent = chunks[source.parentIndex + destructible->getFirstChunkIndex()]; + parent.flags |= ChunkMissingChild; + } + // Remove from static roots list (this no-ops if the chunk was not in the static roots list) + destructible->getStaticRoots().free(chunk.indexInAsset); + // No more static chunks, make sure this actor field is cleared + if (actorForStaticChunks != NULL) + { + SCOPED_PHYSX_LOCK_READ(actorForStaticChunks->getScene()); + if (actorForStaticChunks->getNbShapes() == 0) + { + actorForStaticChunks = NULL; + } + } +} + +struct ChunkIsland +{ + ChunkIsland() : actor(NULL), flags(0), actorIslandDataIndex(0) {} + + physx::Array<uint32_t> indices; + PxRigidDynamic* actor; + uint32_t flags; + uint32_t actorIslandDataIndex; +}; + +struct ActorIslandData +{ + ActorIslandData() : islandCount(0), flags(0) {} + + enum Flag + { + SubmmittedForMassRecalc = 0x1 + }; + + uint32_t islandCount; + uint32_t flags; +}; + +void DestructibleStructure::separateUnsupportedIslands() +{ + // Find instances where an island broke away from an existing + // island, but instead of two new islands there should actually + // have been three (or more) because of discontinuities. Fix it. + + PX_PROFILE_ZONE("DestructibleSeparateUnsupportedIslands", GetInternalApexSDK()->getContextId()); + physx::Array<uint32_t> chunksRemaining = supportDepthChunks; + physx::Array<ChunkIsland> islands; + + // Instead of sorting to find islands that share actors, will merely count. + // Since we expect the number of new islands to be small, we should be able + // to eliminate most of the work this way. + physx::Array<ActorIslandData> islandData(dscene->mActorFIFO.size() + dscene->mDormantActors.usedCount() + 1); // Max size needed + + while (chunksRemaining.size()) + { + uint32_t chunkIndex = chunksRemaining.back(); + chunksRemaining.popBack(); + + Chunk& chunk = chunks[chunkIndex]; + + if ((chunk.state & ChunkTemp0) != 0) + { + continue; + } + PxRigidDynamic* actor = dscene->chunkIntact(chunk); + if (actor == NULL) + { + // we conveniently update and find recently broken links here since this loop is executed here + if(NULL != stressSolver) + { + if(!stressSolver->isPhysxBasedSim) + { + stressSolver->onUpdate(chunkIndex); + } + } + + continue; + } + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + ChunkIsland& island = islands.insert(); + island.indices.pushBack(chunkIndex); + island.actor = actor; + const bool actorStatic = (chunk.state & ChunkDynamic) == 0; + PhysXObjectDesc* actorObjDesc = (PhysXObjectDesc*) dscene->mModule->mSdk->getPhysXObjectInfo(island.actor); + int32_t index = -(int32_t)(intptr_t)actorObjDesc->userData; + if (index > 0 && actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC) + { + index = int32_t(dscene->mDormantActors.getRank((uint32_t)index-1) + dscene->mActorFIFO.size()); // Get to the dormant portion of the array + } + PX_ASSERT(index >= 0 && index < (int32_t)islandData.size()); + + island.actorIslandDataIndex = (uint32_t)index; + + ++islandData[(uint32_t)index].islandCount; + chunk.state |= ChunkTemp0; + for (uint32_t i = 0; i < island.indices.size(); ++i) + { + const uint32_t chunkIndex = island.indices[i]; + Chunk& chunk = chunks[chunkIndex]; + island.flags |= chunk.flags & ChunkExternallySupported; + DestructibleActorImpl* dactor = dscene->mDestructibles.direct(chunk.destructibleID); + const uint32_t visibleAssetIndex = chunk.visibleAncestorIndex >= 0 ? (uint32_t)chunk.visibleAncestorIndex - dactor->getFirstChunkIndex() : chunk.indexInAsset; + DestructibleAssetParametersNS::Chunk_Type& source = dactor->getDestructibleAsset()->mParams->chunks.buf[visibleAssetIndex]; + if (source.flags & (DestructibleAssetImpl::UnfracturableChunk | DestructibleAssetImpl::DescendantUnfractureable)) + { + island.flags |= ChunkExternallySupported; + } + const uint32_t firstOverlapIndex = firstOverlapIndices[chunkIndex]; + const uint32_t stopOverlapIndex = firstOverlapIndices[chunkIndex + 1]; + for (uint32_t j = firstOverlapIndex; j < stopOverlapIndex; ++j) + { + const uint32_t overlapChunkIndex = overlaps[j]; + Chunk& overlapChunk = chunks[overlapChunkIndex]; + if ((overlapChunk.state & ChunkTemp0) == 0) + { + PxRigidDynamic* overlapActor = dscene->chunkIntact(overlapChunk); + if (overlapActor != NULL) + { + if (overlapActor == actor || + ((island.flags & ChunkExternallySupported) != 0 && + actorStatic && (overlapChunk.state & ChunkDynamic) == 0)) + { + island.indices.pushBack(overlapChunkIndex); + overlapChunk.state |= (uint32_t)ChunkTemp0; + } + } + } + } + } + } + + physx::Array<PxRigidDynamic*> dirtyActors; // will need mass properties recalculated + + physx::Array<DestructibleActorImpl*> destructiblesInIsland; + + for (uint32_t islandNum = 0; islandNum < islands.size(); ++islandNum) + { + ChunkIsland& island = islands[islandNum]; + + SCOPED_PHYSX_LOCK_READ(island.actor->getScene()); + if (island.actor->getNbShapes() == 0) + { + // This can happen if this island's chunks have all been destroyed + continue; + } + PhysXObjectDescIntl* actorObjDesc = dscene->mModule->mSdk->getGenericPhysXObjectInfo(island.actor); + ActorIslandData& data = islandData[island.actorIslandDataIndex]; + PX_ASSERT(data.islandCount > 0); + const bool dynamic = !(island.actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC); + if (!(island.flags & ChunkExternallySupported) || dynamic) + { + if (data.islandCount > 1) + { + --data.islandCount; + createDynamicIsland(island.indices); + actorObjDesc = dscene->mModule->mSdk->getGenericPhysXObjectInfo(island.actor); // Need to get this again, since the pointer can change from createDynamicIsland()! + if ((data.flags & ActorIslandData::SubmmittedForMassRecalc) == 0) + { + dirtyActors.pushBack(island.actor); + data.flags |= ActorIslandData::SubmmittedForMassRecalc; + } + if (island.actorIslandDataIndex > 0 && island.actorIslandDataIndex <= (uint32_t)dscene->mActorFIFO.size()) + { + dscene->mActorFIFO[island.actorIslandDataIndex-1].age = 0.0f; // Reset the age of the original actor. It will have a different set of chunks after this + } + } + else + { + if (!dynamic) + { + createDynamicIsland(island.indices); + actorObjDesc = dscene->mModule->mSdk->getGenericPhysXObjectInfo(island.actor); // Need to get this again, since the pointer can change from createDynamicIsland()! + // If we ever are able to simply clear the BF_KINEMATIC flag, remember to recalculate the mass properties here. + } + else + { + // Recalculate list of destructibles on this dynamic PxRigidDynamic island + destructiblesInIsland.reset(); + for (uint32_t i = 0; i < actorObjDesc->mApexActors.size(); ++i) + { + const DestructibleActor* dActor = static_cast<const DestructibleActor*>(actorObjDesc->mApexActors[i]); + ((DestructibleActorProxy*)dActor)->impl.unreferencedByActor(island.actor); + } + actorObjDesc->mApexActors.reset(); + bool isDebris = true; // Until proven otherwise + for (uint32_t i = 0; i < island.indices.size(); ++i) + { + const uint32_t chunkIndex = island.indices[i]; + Chunk& chunk = chunks[chunkIndex]; + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + const DestructibleParameters& parameters = destructible->getDestructibleParameters(); + DestructibleAssetParametersNS::Chunk_Type& assetChunk = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk.indexInAsset]; + if (parameters.debrisDepth >= 0) + { + if (assetChunk.depth < (island.indices.size() == 1 ? parameters.debrisDepth : (parameters.debrisDepth + 1))) // If there is more than one chunk in an island, insist that all chunks must lie strictly _below_ the debris depth to be considered debris + { + isDebris = false; + } + } + else + { + isDebris = false; + } + if ((destructible->getInternalFlags() & DestructibleActorImpl::IslandMarker) == 0) + { + destructiblesInIsland.pushBack(destructible); + PX_ASSERT(actorObjDesc->mApexActors.find(destructible->getAPI()) == actorObjDesc->mApexActors.end()); + actorObjDesc->mApexActors.pushBack(destructible->getAPI()); + destructible->referencedByActor(island.actor); + destructible->getInternalFlags() |= DestructibleActorImpl::IslandMarker; + } + } + PX_ASSERT(island.actorIslandDataIndex > 0); + if (isDebris && island.actorIslandDataIndex > 0 && island.actorIslandDataIndex <= (uint32_t)dscene->mActorFIFO.size()) + { + dscene->mActorFIFO[island.actorIslandDataIndex-1].flags |= ActorFIFOEntry::IsDebris; + } + for (uint32_t i = 0; i < actorObjDesc->mApexActors.size(); ++i) + { + destructiblesInIsland[i]->getInternalFlags() &= ~(uint16_t)DestructibleActorImpl::IslandMarker; + } + } + } + } + + if (actorObjDesc->userData == 0) // initially static chunk + { + // Recalculate list of destructibles on the kinematic PxRigidDynamic island + for (uint32_t i = actorObjDesc->mApexActors.size(); i--;) + { + DestructibleActorProxy* proxy = const_cast<DestructibleActorProxy*>(static_cast<const DestructibleActorProxy*>(actorObjDesc->mApexActors[i])); + if (proxy->impl.getStaticRoots().usedCount() == 0) + { + proxy->impl.unreferencedByActor(island.actor); + actorObjDesc->mApexActors.replaceWithLast(i); + } + } + } + + if (!dynamic) + { + if (actorObjDesc->mApexActors.size() == 0) + { + // if all destructible references have been removed + if (actorForStaticChunks == island.actor) + { + actorForStaticChunks = NULL; + } + } + else + { + dirtyActors.pushBack(island.actor); + } + } + } + + for (uint32_t dirtyActorNum = 0; dirtyActorNum < dirtyActors.size(); ++dirtyActorNum) + { + PxRigidDynamic* actor = dirtyActors[dirtyActorNum]; + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + + const uint32_t nShapes = actor->getNbShapes(); + if (nShapes > 0) + { + float mass = 0.0f; + for (uint32_t i = 0; i < nShapes; ++i) + { + PxShape* shape; + actor->getShapes(&shape, 1, i); + DestructibleStructure::Chunk* chunk = dscene->getChunk(shape); + if (chunk == NULL || !chunk->isFirstShape(shape)) // BRG OPTIMIZE + { + continue; + } + DestructibleActorImpl* dactor = dscene->mDestructibles.direct(chunk->destructibleID); + mass += dactor->getChunkMass(chunk->indexInAsset); + } + if (mass > 0.0f) + { + // Updating mass here, since it won't cause extra work for MOI calculator + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + physx::PxRigidBodyExt::setMassAndUpdateInertia(*actor, dscene->scaleMass(mass), NULL, true); // Ensures that we count shapes that have been flagged as non-simulation shapes + } + } + } + + for (uint32_t supportChunkNum = 0; supportChunkNum < supportDepthChunks.size(); ++supportChunkNum) + { + chunks[supportDepthChunks[supportChunkNum]].state &= ~(uint32_t)ChunkTemp0; + } + + setSupportInvalid(false); +} + +void DestructibleStructure::createDynamicIsland(const physx::Array<uint32_t>& indices) +{ + PX_PROFILE_ZONE("DestructibleCreateDynamicIsland", GetInternalApexSDK()->getContextId()); + + if (indices.size() == 0) + { + return; + } + + PxRigidDynamic* actor = dscene->chunkIntact(chunks[indices[0]]); + PX_ASSERT(actor != NULL); + + SCOPED_PHYSX_LOCK_READ(actor->getScene()); + SCOPED_PHYSX_LOCK_WRITE(actor->getScene()); + + physx::Array<Chunk*> removedChunks; + for (uint32_t i = 0; i < indices.size(); ++i) + { + Chunk& chunk = chunks[indices[i]]; + if (!chunk.isDestroyed()) + { + Chunk* rootChunk = getRootChunk(chunk); + if (rootChunk && (rootChunk->state & ChunkTemp1) == 0) + { + rootChunk->state |= (uint32_t)ChunkTemp1; + removedChunks.pushBack(rootChunk); + if(stressSolver && stressSolver->isPhysxBasedSim) + { + stressSolver->removeChunkFromIsland(indices[i]); + } + PxRigidDynamic* actor = getChunkActor(*rootChunk); + if (!(actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC)) + { + actor->wakeUp(); + } + } + } + else + { + // This won't mark the found chunks with ChunkTemp1, but we should not + // have any duplicates from this search + DestructibleScene::CollectVisibleChunks chunkOp(removedChunks); + dscene->forSubtree(chunk, chunkOp); + } + } + if (removedChunks.size() == 0) + { + return; + } + + // Eliminate chunks that are unfractureable. + for (uint32_t i = 0; i < removedChunks.size(); ++i) + { + Chunk& chunk = *removedChunks[i]; + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + destructible->getStaticRoots().free(chunk.indexInAsset); + DestructibleAssetParametersNS::Chunk_Type& source = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk.indexInAsset]; + if ((source.flags & DestructibleAssetImpl::DescendantUnfractureable) != 0) + { + chunk.state &= ~(uint32_t)ChunkTemp1; + removedChunks[i] = NULL; + for (uint32_t j = 0; j < source.numChildren; ++j) + { + const uint32_t childIndex = destructible->getFirstChunkIndex() + source.firstChildIndex + j; + Chunk& child = chunks[childIndex]; + removedChunks.pushBack(&child); + destructible->setChunkVisibility(child.indexInAsset, false); // In case its mesh changes + dscene->appendShapes(child, true); + destructible->setChunkVisibility(child.indexInAsset, true); + } + removeChunk(chunk); + } + if ((source.flags & DestructibleAssetImpl::UnfracturableChunk) != 0) + { + if (actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC) + { + chunk.state &= ~(uint32_t)ChunkTemp1; + removedChunks[i] = NULL; + } + } + } + + uint32_t convexShapeCount = 0; + uint32_t chunkCount = 0; + for (uint32_t i = 0; i < removedChunks.size(); ++i) + { + Chunk* chunk = removedChunks[i]; + if (chunk == NULL) + { + continue; + } + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk->destructibleID); + removedChunks[chunkCount++] = chunk; + + convexShapeCount += destructible->getDestructibleAsset()->getChunkHullCount(chunk->indexInAsset); + } + for (uint32_t i = chunkCount; i < removedChunks.size(); ++i) + { + removedChunks[i] = NULL; + } + + PxRigidDynamic* newActor = NULL; + + physx::Array<DestructibleActorImpl*> destructiblesInIsland; + + float mass = 0.0f; + + uint32_t* convexShapeCounts = (uint32_t*)PxAlloca(sizeof(uint32_t) * chunkCount); + PxConvexMeshGeometry* convexShapeDescs = (PxConvexMeshGeometry*)PxAlloca(sizeof(PxConvexMeshGeometry) * convexShapeCount); + uint32_t createdShapeCount = 0; + bool isDebris = true; // until proven otherwise + uint32_t minDepth = 0xFFFFFFFF; + bool takesImpactDamage = false; + float minContactReportThreshold = PX_MAX_F32; + PhysX3DescTemplateImpl physX3Template; + + for (uint32_t i = 0; i < chunkCount; ++i) + { + Chunk* chunk = removedChunks[i]; + + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk->destructibleID); + destructible->getPhysX3Template(physX3Template); + if ((destructible->getInternalFlags() & DestructibleActorImpl::IslandMarker) == 0) + { + destructiblesInIsland.pushBack(destructible); + destructible->getInternalFlags() |= DestructibleActorImpl::IslandMarker; + + if (!newActor) + { + newActor = dscene->mPhysXScene->getPhysics().createRigidDynamic(actor->getGlobalPose()); + + PX_ASSERT(newActor); + physX3Template.apply(newActor); + + if (destructible->getDestructibleParameters().dynamicChunksDominanceGroup < 32) + { + newActor->setDominanceGroup(destructible->getDestructibleParameters().dynamicChunksDominanceGroup); + } + + newActor->setActorFlag(PxActorFlag::eSEND_SLEEP_NOTIFIES, true); + const DestructibleActorParamNS::BehaviorGroup_Type& behaviorGroup = destructible->getBehaviorGroup(chunk->indexInAsset); + newActor->setMaxDepenetrationVelocity(behaviorGroup.maxDepenetrationVelocity); + } + } + DestructibleParameters& parameters = destructible->getDestructibleParameters(); + DestructibleAssetParametersNS::Chunk_Type& assetChunk = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk->indexInAsset]; + if (parameters.debrisDepth >= 0) + { + if (assetChunk.depth < (chunkCount == 1 ? parameters.debrisDepth : (parameters.debrisDepth + 1))) // If there is more than one chunk in an island, insist that all chunks must lie strictly _below_ the debris depth to be considered debris + { + isDebris = false; + } + } + else + { + isDebris = false; + } + if (assetChunk.depth < minDepth) + { + minDepth = assetChunk.depth; + } + if (destructible->takesImpactDamageAtDepth(assetChunk.depth)) + { + takesImpactDamage = true; + minContactReportThreshold = PxMin(minContactReportThreshold, + destructible->getContactReportThreshold(*chunk)); + } + + chunk->state &= ~(uint32_t)ChunkTemp1; + mass += destructible->getChunkMass(chunk->indexInAsset); + + const uint32_t oldShapeCount = newActor->getNbShapes(); + for (uint32_t hullIndex = destructible->getDestructibleAsset()->getChunkHullIndexStart(chunk->indexInAsset); hullIndex < destructible->getDestructibleAsset()->getChunkHullIndexStop(chunk->indexInAsset); ++hullIndex) + { + PxConvexMeshGeometry& convexShapeDesc = convexShapeDescs[createdShapeCount]; + PX_PLACEMENT_NEW(&convexShapeDesc, PxConvexMeshGeometry); + + // Need to get PxConvexMesh + // Shape(s): + PxTransform localPose = getChunkLocalPose(*chunk); + + convexShapeDesc.convexMesh = destructible->getConvexMesh(hullIndex); + // Make sure we can get a collision mesh + if (!convexShapeDesc.convexMesh) + { + PX_ALWAYS_ASSERT(); + return; + } + convexShapeDesc.scale.scale = destructible->getScale(); + // Divide out the cooking scale to get the proper scaling + const PxVec3 cookingScale = dscene->getModuleDestructible()->getChunkCollisionHullCookingScale(); + convexShapeDesc.scale.scale.x /= cookingScale.x; + convexShapeDesc.scale.scale.y /= cookingScale.y; + convexShapeDesc.scale.scale.z /= cookingScale.z; + if ((convexShapeDesc.scale.scale - PxVec3(1.0f)).abs().maxElement() < 10*PX_EPS_F32) + { + convexShapeDesc.scale.scale = PxVec3(1.0f); + } + + PxShape* shape; + + shape = newActor->createShape(convexShapeDesc, + physX3Template.materials.begin(), + static_cast<uint16_t>(physX3Template.materials.size()), + static_cast<physx::PxShapeFlags>(physX3Template.shapeFlags)); + shape->setLocalPose(localPose); + physX3Template.apply(shape); + + physx::PxPairFlags pairFlag = (physx::PxPairFlags)physX3Template.contactReportFlags; + if (takesImpactDamage) + { + pairFlag /* |= PxPairFlag::eNOTIFY_CONTACT_FORCES */ + |= PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS + | PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND + | PxPairFlag::eNOTIFY_CONTACT_POINTS; + } + + if (destructible->getBehaviorGroup(chunk->indexInAsset).materialStrength > 0.0f) + { + pairFlag |= PxPairFlag::eMODIFY_CONTACTS; + } + + if (dscene->mApexScene->getApexPhysX3Interface()) + dscene->mApexScene->getApexPhysX3Interface()->setContactReportFlags(shape, pairFlag, destructible->getAPI(), chunk->indexInAsset); + + + ++createdShapeCount; + } + dscene->scheduleChunkShapesForDelete(*chunk); + convexShapeCounts[i] = newActor->getNbShapes() - oldShapeCount; + } + + if (destructiblesInIsland.size() == 0) + { + return; + } + + /* + What if the different destructibles have different properties? Which to choose for the island? For now we'll just choose one. + */ + DestructibleActorImpl* templateDestructible = destructiblesInIsland[0]; + + newActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, false); + if (takesImpactDamage) + { + // Set contact report threshold if the actor can take impact damage + newActor->setContactReportThreshold(minContactReportThreshold); + } + PxRigidBodyExt::setMassAndUpdateInertia(*newActor, dscene->scaleMass(mass)); + + { + dscene->mActorsToAddIndexMap[newActor] = dscene->mActorsToAdd.size(); + dscene->mActorsToAdd.pushBack(newActor); + + float initWakeCounter = dscene->mPhysXScene->getWakeCounterResetValue(); + newActor->setWakeCounter(initWakeCounter); + } + + // Use the templateDestructible to start the actorDesc, then add the other destructibles in the island + PhysXObjectDescIntl* actorObjDesc = dscene->mModule->mSdk->createObjectDesc(templateDestructible->getAPI(), newActor); + actorObjDesc->userData = 0; + templateDestructible->setActorObjDescFlags(actorObjDesc, minDepth); + templateDestructible->referencedByActor(newActor); // needs to be called after setActorObjDescFlags + // While we're at it, clear the marker flags here + templateDestructible->getInternalFlags() &= ~(uint16_t)DestructibleActorImpl::IslandMarker; + for (uint32_t i = 1; i < destructiblesInIsland.size(); ++i) + { + DestructibleActorImpl* destructibleInIsland = destructiblesInIsland[i]; + PX_ASSERT(actorObjDesc->mApexActors.find(destructibleInIsland->getAPI()) == actorObjDesc->mApexActors.end()); + actorObjDesc->mApexActors.pushBack(destructibleInIsland->getAPI()); + destructibleInIsland->referencedByActor(newActor); + destructibleInIsland->getInternalFlags() &= ~(uint16_t)DestructibleActorImpl::IslandMarker; + } + + dscene->addActor(*actorObjDesc, *newActor, mass, isDebris); + + uint32_t newIslandID = newPxActorIslandReference(*removedChunks[0], *newActor); + uint32_t shapeStart = 0; + const uint32_t actorShapeCount = newActor->getNbShapes(); + PX_ALLOCA(shapeArray, physx::PxShape*, actorShapeCount); + PxRigidActor* rigidActor = newActor->is<physx::PxRigidActor>(); + rigidActor->getShapes(shapeArray, actorShapeCount); + for (uint32_t i = 0; i < chunkCount; ++i) + { + Chunk& chunk = *removedChunks[i]; + chunk.islandID = newIslandID; + uint32_t shapeCount = convexShapeCounts[i]; + PxShape* const* newShapes = shapeArray + shapeStart; + shapeStart += shapeCount; + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + PX_ASSERT(this == destructible->getStructure()); + destructible->setChunkVisibility(chunk.indexInAsset, false); + chunk.state |= (uint32_t)ChunkVisible | (uint32_t)ChunkDynamic; + destructible->setChunkVisibility(chunk.indexInAsset, true); + chunk.setShapes(newShapes, shapeCount); + DestructibleScene::VisibleChunkSetDescendents chunkOp(chunk.indexInAsset+destructible->getFirstChunkIndex(), true); + dscene->forSubtree(chunk, chunkOp, true); + for (uint32_t j = 0; j < shapeCount; ++j) + { + PhysXObjectDescIntl* shapeObjDesc = dscene->mModule->mSdk->createObjectDesc(destructible->getAPI(), newShapes[j]); + shapeObjDesc->userData = &chunk; + } + } + + if (newActor && dscene->getModuleDestructible()->m_destructiblePhysXActorReport != NULL) + { + dscene->getModuleDestructible()->m_destructiblePhysXActorReport->onPhysXActorCreate(*newActor); + } + + //===SyncParams=== + evaluateForHitChunkList(indices); +} + + +void DestructibleStructure::calculateExternalSupportChunks() +{ + const uint32_t chunkCount = chunks.size(); + PX_UNUSED(chunkCount); + PX_PROFILE_ZONE("DestructibleStructureCalculateExternalSupportChunks", GetInternalApexSDK()->getContextId()); + + supportDepthChunks.resize(0); + supportDepthChunksNotExternallySupportedCount = 0; + + // iterate all chunks, one destructible after the other + for (uint32_t i = 0; i < destructibles.size(); ++i) + { + DestructibleActorImpl* destructible = destructibles[i]; + if (destructible == NULL) + continue; + + DestructibleAssetImpl* destructibleAsset = destructible->getDestructibleAsset(); + const float paddingFactor = destructibleAsset->mParams->neighborPadding; + const float padding = paddingFactor * (destructible->getOriginalBounds().maximum - destructible->getOriginalBounds().minimum).magnitude(); + const DestructibleAssetParametersNS::Chunk_Type* destructibleAssetChunks = destructibleAsset->mParams->chunks.buf; + + const uint32_t supportDepth = destructible->getSupportDepth(); + const bool useAssetDefinedSupport = destructible->useAssetDefinedSupport(); + const bool useWorldSupport = destructible->useWorldSupport(); + + const uint32_t firstChunkIndex = destructible->getFirstChunkIndex(); + const uint32_t destructibleChunkCount = destructible->getChunkCount(); + for (uint32_t chunkIndex = firstChunkIndex; chunkIndex < firstChunkIndex + destructibleChunkCount; ++chunkIndex) + { + Chunk& chunk = chunks[chunkIndex]; + const DestructibleAssetParametersNS::Chunk_Type& source = destructibleAssetChunks[chunk.indexInAsset]; + + // init chunks flags (this is why all chunks need to be iterated) + chunk.flags &= ~((uint8_t)ChunkBelowSupportDepth | (uint8_t)ChunkExternallySupported | (uint8_t)ChunkWorldSupported); + + if (source.depth > supportDepth) + { + chunk.flags |= ChunkBelowSupportDepth; + } + else if (source.depth == supportDepth) + { + // keep list of all support depth chunks + supportDepthChunks.pushBack(chunkIndex); + + if (!destructible->isInitiallyDynamic()) + { + // Only static destructibles can be externally supported + if (useAssetDefinedSupport) + { + if ((source.flags & DestructibleAssetImpl::SupportChunk) != 0) + { + chunk.flags |= ChunkExternallySupported; + } + } + if (useWorldSupport) // Test even if ChunkExternallySupported flag is already set, since we want to set the ChunkWorldSupported flag correctly + { + PhysX3DescTemplateImpl physX3Template; + destructible->getPhysX3Template(physX3Template); + for (uint32_t hullIndex = destructibleAsset->getChunkHullIndexStart(chunk.indexInAsset); hullIndex < destructibleAsset->getChunkHullIndexStop(chunk.indexInAsset); ++hullIndex) + { + PxTransform globalPose(destructible->getInitialGlobalPose()); + globalPose.p = globalPose.p + globalPose.rotate(destructible->getScale().multiply(destructibleAsset->getChunkPositionOffset(chunk.indexInAsset))); + if (dscene->testWorldOverlap(destructibleAsset->chunkConvexHulls[hullIndex], globalPose, destructible->getScale(), padding, &physX3Template.queryFilterData)) + { + chunk.flags |= ChunkExternallySupported | ChunkWorldSupported; + break; + } + } + } + + if ( ((chunk.flags & ChunkExternallySupported) == 0) && + supportDepthChunks.size() > supportDepthChunksNotExternallySupportedCount + 1) + { + // Will sort the supportDepthChunks so that externally supported ones are all at the end of the array + nvidia::swap(supportDepthChunks.back(), supportDepthChunks[supportDepthChunksNotExternallySupportedCount]); + ++supportDepthChunksNotExternallySupportedCount; + } + } + } + } + } +} + +void DestructibleStructure::invalidateBounds(const PxBounds3* bounds, uint32_t boundsCount) +{ + for (uint32_t chunkNum = supportDepthChunks.size(); chunkNum-- > supportDepthChunksNotExternallySupportedCount;) + { + const uint32_t chunkIndex = supportDepthChunks[chunkNum]; + Chunk& chunk = chunks[chunkIndex]; + if (chunk.state & ChunkDynamic) + { + continue; // Only affect still-static chunks + } + DestructibleActorImpl* destructible = dscene->mDestructibles.direct(chunk.destructibleID); + const float paddingFactor = destructible->getDestructibleAsset()->mParams->neighborPadding; + const float padding = paddingFactor * (destructible->getOriginalBounds().maximum - destructible->getOriginalBounds().minimum).magnitude(); + const DestructibleAssetParametersNS::Chunk_Type& source = destructible->getDestructibleAsset()->mParams->chunks.buf[chunk.indexInAsset]; + if (destructible->useAssetDefinedSupport() && (source.flags & DestructibleAssetImpl::SupportChunk) != 0) + { + continue; // Asset-defined support. This is not affected by external actors. + } + PxBounds3 chunkBounds = destructible->getChunkBounds(chunk.indexInAsset); + chunkBounds.fattenFast(2.0f*padding); + bool affectedByInvalidBounds = false; + for (uint32_t boundsNum = 0; boundsNum < boundsCount; ++boundsNum) + { + if (bounds[boundsNum].intersects(chunkBounds)) + { + affectedByInvalidBounds = true; + break; + } + } + if (!affectedByInvalidBounds) + { + continue; + } + bool isWorldSupported = false; // until proven otherwise + PhysX3DescTemplateImpl physX3Template; + destructible->getPhysX3Template(physX3Template); + for (uint32_t hullIndex = destructible->getDestructibleAsset()->getChunkHullIndexStart(chunk.indexInAsset); hullIndex < destructible->getDestructibleAsset()->getChunkHullIndexStop(chunk.indexInAsset); ++hullIndex) + { + PxTransform globalPose(destructible->getInitialGlobalPose()); + globalPose.p = globalPose.p + globalPose.rotate(destructible->getScale().multiply(destructible->getDestructibleAsset()->getChunkPositionOffset(chunk.indexInAsset))); + if (dscene->testWorldOverlap(destructible->getDestructibleAsset()->chunkConvexHulls[hullIndex], globalPose, destructible->getScale(), padding, &physX3Template.queryFilterData)) + { + isWorldSupported = true; + break; + } + } + if (!isWorldSupported) + { + chunk.flags &= ~(uint8_t)ChunkExternallySupported; + swap(supportDepthChunks[supportDepthChunksNotExternallySupportedCount++], supportDepthChunks[chunkNum++]); + supportInvalid = true; + } + } +} + +void DestructibleStructure::buildSupportGraph() +{ + PX_PROFILE_ZONE("DestructibleStructureBuildSupportGraph", GetInternalApexSDK()->getContextId()); + + // First ensure external support data is up-to-date + calculateExternalSupportChunks(); + + // Now create graph + + if (destructibles.size() > 1) + { + // First record cached overlaps within each destructible + physx::Array<IntPair> cachedOverlapPairs; + for (uint32_t i = 0; i < destructibles.size(); ++i) + { + DestructibleActorImpl* destructible = destructibles[i]; + if (destructible != NULL) + { + DestructibleAssetImpl* asset = destructibles[i]->getDestructibleAsset(); + PX_ASSERT(asset); + CachedOverlapsNS::IntPair_DynamicArray1D_Type* internalOverlaps = asset->getOverlapsAtDepth(destructible->getSupportDepth()); + cachedOverlapPairs.reserve(cachedOverlapPairs.size() + internalOverlaps->arraySizes[0]); + for (int j = 0; j < internalOverlaps->arraySizes[0]; ++j) + { + CachedOverlapsNS::IntPair_Type& internalPair = internalOverlaps->buf[j]; + IntPair& pair = cachedOverlapPairs.insert(); + pair.i0 = internalPair.i0 + (int32_t)destructible->getFirstChunkIndex(); + pair.i1 = internalPair.i1 + (int32_t)destructible->getFirstChunkIndex(); + } + } + } + + physx::Array<IntPair> overlapPairs; + uint32_t overlapCount = overlapPairs.size(); + + // Now find overlaps between destructibles. Start by creating a destructible overlap list + physx::Array<BoundsRep> destructibleBoundsReps; + destructibleBoundsReps.reserve(destructibles.size()); + for (uint32_t i = 0; i < destructibles.size(); ++i) + { + DestructibleActorImpl* destructible = destructibles[i]; + BoundsRep& boundsRep = destructibleBoundsReps.insert(); + if (destructible != NULL) + { + boundsRep.aabb = destructible->getOriginalBounds(); + } + else + { + boundsRep.type = 1; // Will not test 1-0 or 1-1 overlaps + } + const float paddingFactor = destructible->getDestructibleAsset()->mParams->neighborPadding; + const float padding = paddingFactor * (destructible->getOriginalBounds().maximum - destructible->getOriginalBounds().minimum).magnitude(); + PX_ASSERT(!boundsRep.aabb.isEmpty()); + boundsRep.aabb.fattenFast(padding); + } + physx::Array<IntPair> destructiblePairs; + { + PX_PROFILE_ZONE("DestructibleStructureBoundsCalculateOverlaps", GetInternalApexSDK()->getContextId()); + BoundsInteractions interactions(false); + interactions.set(0, 0, true); // Only test 0-0 overlaps + PX_ASSERT(destructibleBoundsReps.size() > 1); + boundsCalculateOverlaps(destructiblePairs, Bounds3XYZ, &destructibleBoundsReps[0], destructibleBoundsReps.size(), sizeof(destructibleBoundsReps[0]), interactions); + } + + // Test for chunk overlaps between overlapping destructibles + for (uint32_t overlapIndex = 0; overlapIndex < destructiblePairs.size(); ++overlapIndex) + { + const IntPair& destructibleOverlap = destructiblePairs[overlapIndex]; + + DestructibleActorImpl* destructible0 = destructibles[(uint32_t)destructibleOverlap.i0]; + const uint32_t startChunkAssetIndex0 = destructible0->getDestructibleAsset()->mParams->firstChunkAtDepth.buf[destructible0->getSupportDepth()]; + const uint32_t stopChunkAssetIndex0 = destructible0->getDestructibleAsset()->mParams->firstChunkAtDepth.buf[destructible0->getSupportDepth() + 1]; + const float paddingFactor0 = destructible0->getDestructibleAsset()->mParams->neighborPadding; + const float padding0 = paddingFactor0 * (destructible0->getOriginalBounds().maximum - destructible0->getOriginalBounds().minimum).magnitude(); + + DestructibleActorImpl* destructible1 = destructibles[(uint32_t)destructibleOverlap.i1]; + const uint32_t startChunkAssetIndex1 = destructible1->getDestructibleAsset()->mParams->firstChunkAtDepth.buf[destructible1->getSupportDepth()]; + const uint32_t stopChunkAssetIndex1 = destructible1->getDestructibleAsset()->mParams->firstChunkAtDepth.buf[destructible1->getSupportDepth() + 1]; + const float paddingFactor1 = destructible1->getDestructibleAsset()->mParams->neighborPadding; + const float padding1 = paddingFactor1 * (destructible1->getOriginalBounds().maximum - destructible1->getOriginalBounds().minimum).magnitude(); + + // Find AABB overlaps + + // chunkBoundsReps contains bounds of all support chunks for both destructibles (first part destructible0, second part destructible1) + physx::Array<BoundsRep> chunkBoundsReps; + chunkBoundsReps.reserve((stopChunkAssetIndex0 - startChunkAssetIndex0) + (stopChunkAssetIndex1 - startChunkAssetIndex1)); + + // Destructible 0 bounds + for (uint32_t chunkAssetIndex = startChunkAssetIndex0; chunkAssetIndex < stopChunkAssetIndex0; ++chunkAssetIndex) + { + BoundsRep& bounds = chunkBoundsReps.insert(); + PxMat44 scaledTM = destructible0->getInitialGlobalPose(); + scaledTM.scale(PxVec4(destructible0->getScale(), 1.f)); + bounds.aabb = destructible0->getDestructibleAsset()->getChunkActorLocalBounds(chunkAssetIndex); + PxBounds3Transform(bounds.aabb, scaledTM); + PX_ASSERT(!bounds.aabb.isEmpty()); + bounds.aabb.fattenFast(padding0); + bounds.type = 0; + } + + // Destructible 1 bounds + for (uint32_t chunkAssetIndex = startChunkAssetIndex1; chunkAssetIndex < stopChunkAssetIndex1; ++chunkAssetIndex) + { + BoundsRep& bounds = chunkBoundsReps.insert(); + PxMat44 scaledTM = destructible1->getInitialGlobalPose(); + scaledTM.scale(PxVec4(destructible1->getScale(), 1.f)); + bounds.aabb = destructible1->getDestructibleAsset()->getChunkActorLocalBounds(chunkAssetIndex); + PxBounds3Transform(bounds.aabb, scaledTM); + PX_ASSERT(!bounds.aabb.isEmpty()); + bounds.aabb.fattenFast(padding1); + bounds.type = 1; + } + + { + PX_PROFILE_ZONE("DestructibleStructureBoundsCalculateOverlaps", GetInternalApexSDK()->getContextId()); + BoundsInteractions interactions(false); + interactions.set(0, 1, true); // Only test 0-1 overlaps + if (chunkBoundsReps.size() > 0) + { + // this adds overlaps into overlapPairs with indices into the chunkBoundsReps array + boundsCalculateOverlaps(overlapPairs, Bounds3XYZ, &chunkBoundsReps[0], chunkBoundsReps.size(), sizeof(chunkBoundsReps[0]), interactions, true); + } + } + + // Now do detailed overlap test + const bool performDetailedOverlapTest = destructible0->performDetailedOverlapTestForExtendedStructures() || destructible1->performDetailedOverlapTestForExtendedStructures(); + { + const float padding = padding0 + padding1; + + // upperOffset transforms from chunkBoundsReps indices to asset chunk indices of the second destructible + const int32_t upperOffset = int32_t(startChunkAssetIndex1 - (stopChunkAssetIndex0 - startChunkAssetIndex0)); + + PX_PROFILE_ZONE("DestructibleStructureDetailedOverlapTest", GetInternalApexSDK()->getContextId()); + const uint32_t oldSize = overlapCount; + for (uint32_t overlapIndex = oldSize; overlapIndex < overlapPairs.size(); ++overlapIndex) + { + IntPair& AABBOverlap = overlapPairs[overlapIndex]; + // The new overlaps will be indexed incorrectly. Fix the indexing. + if (AABBOverlap.i0 > AABBOverlap.i1) + { + // Ensures i0 corresponds to destructible0, i1 to destructible 1 + // because lower chunkBoundsReps indices belong to destructible0 + nvidia::swap(AABBOverlap.i0, AABBOverlap.i1); + } + + // transform chunkBoundsReps indices to asset chunk indices + AABBOverlap.i0 += startChunkAssetIndex0; + AABBOverlap.i1 += upperOffset; + if (!performDetailedOverlapTest || DestructibleAssetImpl::chunksInProximity(*destructible0->getDestructibleAsset(), (uint16_t)AABBOverlap.i0, + PxTransform(destructible0->getInitialGlobalPose()), destructible0->getScale(), *destructible1->getDestructibleAsset(), (uint16_t)AABBOverlap.i1, + PxTransform(destructible1->getInitialGlobalPose()), destructible1->getScale(), padding)) + { + // Record overlap with global indexing + IntPair& overlap = overlapPairs[overlapCount++]; + overlap.i0 = AABBOverlap.i0 + (int32_t)destructible0->getFirstChunkIndex(); + overlap.i1 = AABBOverlap.i1 + (int32_t)destructible1->getFirstChunkIndex(); + } + } + } + overlapPairs.resize(overlapCount); + } + + // We now have all chunk overlaps in the structure. + // Make 'overlapPairs' symmetric - i.e. if (A,B) is in the array, then so is (B,A). + overlapPairs.resize(2 * overlapCount); + for (uint32_t i = 0; i < overlapCount; ++i) + { + IntPair& overlap = overlapPairs[i]; + IntPair& recipOverlap = overlapPairs[i + overlapCount]; + recipOverlap.i0 = overlap.i1; + recipOverlap.i1 = overlap.i0; + } + overlapCount *= 2; + + // Now sort overlapPairs by index0 and index1 (symmetric, so it doesn't matter which we sort by first) + qsort(overlapPairs.begin(), overlapCount, sizeof(IntPair), IntPair::compare); + + + // merge new overlaps with cached ones + physx::Array<IntPair> allOverlapPairs(overlapPairs.size() + cachedOverlapPairs.size()); + ApexMerge(overlapPairs.begin(), overlapPairs.size(), cachedOverlapPairs.begin(), cachedOverlapPairs.size(), allOverlapPairs.begin(), allOverlapPairs.size(), IntPair::compare); + overlapCount = allOverlapPairs.size(); + + // Create the structure's chunk overlap list + createIndexStartLookup(firstOverlapIndices, 0, chunks.size(), &allOverlapPairs.begin()->i0, overlapCount, sizeof(IntPair)); + overlaps.resize(overlapCount); + for (uint32_t overlapIndex = 0; overlapIndex < overlapCount; ++overlapIndex) + { + overlaps[overlapIndex] = (uint32_t)allOverlapPairs[overlapIndex].i1; + } + } + else if (destructibles.size() == 1 && destructibles[0] != NULL) + { + // fast path for case of structures with only 1 destructible + + DestructibleAssetImpl* asset = destructibles[0]->getDestructibleAsset(); + CachedOverlapsNS::IntPair_DynamicArray1D_Type* internalOverlaps = asset->getOverlapsAtDepth(destructibles[0]->getSupportDepth()); + + uint32_t numOverlaps = (uint32_t)internalOverlaps->arraySizes[0]; + + // Create the structure's chunk overlap list + createIndexStartLookup(firstOverlapIndices, 0, chunks.size(), &internalOverlaps->buf[0].i0, numOverlaps, sizeof(IntPair)); + + overlaps.resize(numOverlaps); + for (uint32_t overlapIndex = 0; overlapIndex < numOverlaps; ++overlapIndex) + { + overlaps[overlapIndex] = (uint32_t)internalOverlaps->buf[overlapIndex].i1; + } + } + + // embed this call within DestructibleStructure, rather than exposing the StressSolver to other classes + postBuildSupportGraph(); +} + +void DestructibleStructure::postBuildSupportGraph() +{ + if(NULL != stressSolver) + { + PX_DELETE(stressSolver); + stressSolver = NULL; + dscene->setStressSolverTick(this, false); + } + + { + // instantiate a stress solver if the user wants to use it + for(physx::Array<DestructibleActorImpl*>::ConstIterator kIter = destructibles.begin(); kIter != destructibles.end(); ++kIter) + { + const DestructibleActorImpl & currentDestructibleActor = *(*kIter); + PX_ASSERT(NULL != ¤tDestructibleActor); + if(currentDestructibleActor.useStressSolver()) + { + stressSolver = PX_NEW(DestructibleStructureStressSolver)(*this,currentDestructibleActor.getDestructibleParameters().supportStrength); + if (!stressSolver->isPhysxBasedSim || stressSolver->isCustomEnablesSimulating) + { + dscene->setStressSolverTick(this, true); + } + break; + } + } + } +} + +void DestructibleStructure::evaluateForHitChunkList(const physx::Array<uint32_t> & chunkIndices) const +{ + PX_ASSERT(NULL != &chunkIndices); + FractureEvent fractureEvent; + ::memset(static_cast<void *>(&fractureEvent), 0x00, 1 * sizeof(FractureEvent)); + for(physx::Array<uint32_t>::ConstIterator iter = chunkIndices.begin(); iter != chunkIndices.end(); ++iter) + { + DestructibleActorImpl & destructibleActor = *(dscene->mDestructibles.direct(chunks[*iter].destructibleID)); + PX_ASSERT(NULL != &destructibleActor); + if(0 != destructibleActor.getSyncParams().getUserActorID()) + { + fractureEvent.chunkIndexInAsset = *iter - destructibleActor.getFirstChunkIndex(); + PX_ASSERT(fractureEvent.chunkIndexInAsset < destructibleActor.getChunkCount()); + destructibleActor.evaluateForHitChunkList(fractureEvent); + } + } +} + +void DestructibleStructure::addChunkImpluseForceAtPos(Chunk& chunk, const PxVec3& impulse, const PxVec3& position, bool wakeup) +{ + physx::Array<PxShape*>& shapes = getChunkShapes(chunk); + PX_ASSERT(!shapes.empty()); + if (!shapes.empty()) + { + // All shapes should have the same actor + PxRigidActor* actor = shapes[0]->getActor(); + if (actor->getScene()) + { + PxRigidDynamic* rigidDynamic = actor->is<physx::PxRigidDynamic>(); + if (rigidDynamic && !(rigidDynamic->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC)) + { + PxRigidBodyExt::addForceAtPos(*actor->is<physx::PxRigidBody>(), impulse, position, PxForceMode::eIMPULSE, wakeup); + } + } + else // the actor hasn't been added to the scene yet, so store the forces to apply later. + { + ActorForceAtPosition forceToAdd(impulse, position, PxForceMode::eIMPULSE, wakeup, true); + dscene->addForceToAddActorsMap(actor, forceToAdd); + } + } +} + +// http://en.wikipedia.org/wiki/Jenkins_hash_function +// Fast and convenient hash for arbitrary multi-byte keys +uint32_t jenkinsHash(const void *data, size_t sizeInBytes) +{ + uint32_t hash, i; + const char* key = reinterpret_cast<const char*>(data); + for (hash = i = 0; i < sizeInBytes; ++i) + { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash; +} + +uint32_t DestructibleStructure::newPxActorIslandReference(Chunk& chunk, PxRigidDynamic& nxActor) +{ + uint32_t islandID = jenkinsHash(&chunk, sizeof(Chunk)); + + // Prevent hash collisions + while (NULL != islandToActor.find(islandID)) + { + ++islandID; + } + + PX_ASSERT(islandID != InvalidID); + + islandToActor[islandID] = &nxActor; + actorToIsland[&nxActor] = islandID; + + dscene->setStructureUpdate(this, true); // islandToActor needs to be cleared in DestructibleStructure::tick + + return islandID; +} + +void DestructibleStructure::removePxActorIslandReferences(PxRigidDynamic& nxActor) const +{ + islandToActor.erase(actorToIsland[&nxActor]); + actorToIsland.erase(&nxActor); +} + +PxRigidDynamic* DestructibleStructure::getChunkActor(Chunk& chunk) +{ + physx::Array<PxShape*>& shapes = getChunkShapes(chunk); + PxRigidDynamic* actor; + SCOPED_PHYSX_LOCK_READ(dscene->mApexScene); + actor = !shapes.empty() ? shapes[0]->getActor()->is<PxRigidDynamic>() : NULL; + return actor; +} + +const PxRigidDynamic* DestructibleStructure::getChunkActor(const Chunk& chunk) const +{ + const physx::Array<PxShape*>& shapes = getChunkShapes(chunk); + PxRigidDynamic* actor; + SCOPED_PHYSX_LOCK_READ(dscene->mApexScene); + actor = !shapes.empty() ? shapes[0]->getActor()->is<PxRigidDynamic>() : NULL; + return actor; +} + +PxTransform DestructibleStructure::getChunkLocalPose(const Chunk& chunk) const +{ + const physx::Array<PxShape*>* shapes; + PxVec3 offset; + if (chunk.visibleAncestorIndex == (int32_t)InvalidChunkIndex) + { + shapes = &chunk.shapes; + offset = PxVec3(0.0f); + } + else + { + shapes = &chunks[(uint32_t)chunk.visibleAncestorIndex].shapes; + offset = chunk.localOffset - chunks[(uint32_t)chunk.visibleAncestorIndex].localOffset; + } + + PxTransform pose(PxIdentity); + if (!shapes->empty() && NULL != (*shapes)[0]) + { + SCOPED_PHYSX_LOCK_READ(dscene->getModulePhysXScene()); + // All shapes should have the same global pose + pose = (*shapes)[0]->getLocalPose(); + } + pose.p += offset; + return pose; +} + +PxTransform DestructibleStructure::getChunkActorPose(const Chunk& chunk) const +{ + const physx::Array<PxShape*>& shapes = getChunkShapes(chunk); + PxTransform pose(PxIdentity); + if (!shapes.empty() && NULL != shapes[0]) + { + // All shapes should have the same actor + SCOPED_PHYSX_LOCK_READ(dscene->getModulePhysXScene()); + pose = shapes[0]->getActor()->getGlobalPose(); + } + return pose; +} + +void DestructibleStructure::setSupportInvalid(bool supportIsInvalid) +{ + supportInvalid = supportIsInvalid; + dscene->setStructureUpdate(this, supportIsInvalid); +} + +} +} // end namespace nvidia + diff --git a/APEX_1.4/module/destructible/src/DestructibleStructureStressSolver.cpp b/APEX_1.4/module/destructible/src/DestructibleStructureStressSolver.cpp new file mode 100644 index 00000000..b45db174 --- /dev/null +++ b/APEX_1.4/module/destructible/src/DestructibleStructureStressSolver.cpp @@ -0,0 +1,1445 @@ +/* + * 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. + */ + + +#include "DestructibleStructureStressSolver.h" +#include "DestructibleStructure.h" +#include "DestructibleActorImpl.h" +#include "PxProfiler.h" + +namespace +{ + const uint32_t InvalidLinkedChunkIndex = 0xFFFFFFFF; + const uint32_t MaxWarmingFrame = 200; + const uint32_t MaxLeaveInAdvaceWarmingWindow = 100; + const uint32_t MaxActiveCycle = 1000; + const float ShadowSceneDeltaTime = 0.001; +}; // namespace nameless + +namespace nvidia +{ +namespace destructible +{ +using namespace physx; + +// a helper data structure used to hold a [actor pointer] [chunk pointer] pair +struct ActorChunkPair +{ +public: + ActorChunkPair(const DestructibleActorImpl * actorAlias, const DestructibleStructure::Chunk * chunkAlias); + ~ActorChunkPair(); + + const DestructibleActorImpl * actorAlias; + const DestructibleStructure::Chunk * chunkAlias; +private: + ActorChunkPair(); +}; // struct ActorChunkPair + +ActorChunkPair::ActorChunkPair(const DestructibleActorImpl * actorAlias_, const DestructibleStructure::Chunk * chunkAlias_) + :actorAlias(actorAlias_) + ,chunkAlias(chunkAlias_) +{ + PX_ASSERT(NULL != actorAlias); + PX_ASSERT(NULL != chunkAlias); +} + +ActorChunkPair::~ActorChunkPair() +{ + chunkAlias = NULL; + actorAlias = NULL; +} + +StructureScratchBuffer::StructureScratchBuffer(uint8_t * const bufferStart_, uint32_t bufferCount_) + :bufferStart(bufferStart_) + ,bufferCount(bufferCount_) +{ + PX_ASSERT(NULL != bufferStart && 0 != bufferCount); + ::memset(static_cast<void*>(bufferStart), StructureScratchBuffer::ByteEmpty, bufferCount * sizeof(bufferStart[0])); +} + +StructureScratchBuffer::~StructureScratchBuffer() +{ +} + +bool StructureScratchBuffer::isOccupied(uint32_t index) const +{ + PX_ASSERT(index < bufferCount); + PX_ASSERT(StructureScratchBuffer::ByteEmpty == bufferStart[index] || StructureScratchBuffer::ByteExist == bufferStart[index]); + return StructureScratchBuffer::ByteExist == bufferStart[index]; +} + +void StructureScratchBuffer::setOccupied(uint32_t index) +{ + PX_ASSERT(index < bufferCount); + PX_ASSERT(StructureScratchBuffer::ByteEmpty == bufferStart[index]); + bufferStart[index] = StructureScratchBuffer::ByteExist; +} + +PeninsulaData::PeninsulaData() + :rootLinkedChunkIndex(InvalidLinkedChunkIndex) + ,peninsulaState(0x00) + ,chunkCount(0) + ,aggregateMass(0.0f) + ,geometricCenter(0.0f) +{ +} + +PeninsulaData::PeninsulaData(uint8_t peninsulaState_, uint32_t chunkCount_) + :rootLinkedChunkIndex(InvalidLinkedChunkIndex) + ,peninsulaState(peninsulaState_) + ,chunkCount(chunkCount_) + ,aggregateMass(0.0f) + ,geometricCenter(0.0f) +{ +} + +PeninsulaData::PeninsulaData(uint8_t peninsulaState_, uint32_t chunkCount_, float aggregateMass_, PxVec3 geometricCenter_) + :rootLinkedChunkIndex(InvalidLinkedChunkIndex) + ,peninsulaState(peninsulaState_) + ,chunkCount(chunkCount_) + ,aggregateMass(aggregateMass_) + ,geometricCenter(geometricCenter_) +{ +} + +PeninsulaData::~PeninsulaData() +{ +} + +bool PeninsulaData::isValid() const +{ + PX_ASSERT(peninsulaState < PeninsulaData::PeninsulaInvalidMaxFlag); + return (!hasFlag(PeninsulaData::PeninsulaEncounteredExternalSupport)); +} + +void PeninsulaData::resetData() +{ + chunkCount = 0; + aggregateMass = 0.0f; + geometricCenter = PxVec3(0.0f); +} + +void PeninsulaData::setFlag(PeninsulaData::PeninsulaFlag peninsulaFlag) +{ + PX_ASSERT(peninsulaFlag < PeninsulaData::PeninsulaInvalidMaxFlag); + PX_ASSERT(!hasFlag(peninsulaFlag)); + peninsulaState |= peninsulaFlag; + PX_ASSERT(peninsulaState < PeninsulaData::PeninsulaInvalidMaxFlag); +} + +void PeninsulaData::setLinkedChunkData(const ActorChunkPair & actorChunkPair, Int2Type<StressEvaluationType::EvaluateByCount>) +{ + PX_ASSERT(NULL != &actorChunkPair); + PX_ASSERT(peninsulaState < PeninsulaData::PeninsulaInvalidMaxFlag); + PX_ASSERT(0 == chunkCount); + PX_ASSERT(0.0f == aggregateMass); + PX_ASSERT(geometricCenter.isZero()); + chunkCount = 1; + PX_UNUSED(actorChunkPair); +} + +void PeninsulaData::setLinkedChunkData(const ActorChunkPair & actorChunkPair, Int2Type<StressEvaluationType::EvaluateByMoment>) +{ + PX_ASSERT(NULL != &actorChunkPair); + PX_ASSERT(peninsulaState < PeninsulaData::PeninsulaInvalidMaxFlag); + PX_ASSERT(0 == chunkCount); + PX_ASSERT(0.0f == aggregateMass); + PX_ASSERT(geometricCenter.isZero()); + chunkCount = 1; + aggregateMass = actorChunkPair.actorAlias->getChunkMass(actorChunkPair.chunkAlias->indexInAsset); + geometricCenter = actorChunkPair.actorAlias->getStructure()->getChunkWorldCentroid(*(actorChunkPair.chunkAlias)); +} + +void PeninsulaData::setRootLinkedChunkIndex(uint32_t linkedChunkIndex) +{ + PX_ASSERT(InvalidLinkedChunkIndex == rootLinkedChunkIndex); + rootLinkedChunkIndex = linkedChunkIndex; +} + +void PeninsulaData::assimilate(const PeninsulaData & that, Int2Type<StressEvaluationType::EvaluateByCount>) +{ + this->peninsulaState |= that.peninsulaState; + this->chunkCount += that.chunkCount; +} + +void PeninsulaData::assimilate(const PeninsulaData & that, Int2Type<StressEvaluationType::EvaluateByMoment>) +{ + this->peninsulaState |= that.peninsulaState; + this->chunkCount += that.chunkCount; + this->geometricCenter = ((this->geometricCenter * this->aggregateMass) + (that.geometricCenter * that.aggregateMass)) / (this->aggregateMass + that.aggregateMass); + this->aggregateMass += that.aggregateMass; +} + +bool PeninsulaData::hasFlag(PeninsulaData::PeninsulaFlag peninsulaFlag) const +{ + PX_ASSERT(peninsulaFlag < PeninsulaData::PeninsulaInvalidMaxFlag); + PX_ASSERT(peninsulaState < PeninsulaData::PeninsulaInvalidMaxFlag); + return (0 != (peninsulaState & peninsulaFlag)); +} + +uint32_t PeninsulaData::getDataChunkCount() const +{ + return chunkCount; +} + +float PeninsulaData::getDataAggregateMass() const +{ + return aggregateMass; +} + +const PxVec3 & PeninsulaData::getDataGeometricCenter() const +{ + return geometricCenter; +} + +uint32_t PeninsulaData::getRootLinkedChunkIndex() const +{ + PX_ASSERT(InvalidLinkedChunkIndex != rootLinkedChunkIndex); + return rootLinkedChunkIndex; +} + +SnapEvent * SnapEvent::instantiate(FractureEventProxy * fractureEventProxyBufferStart, uint32_t fractureEventProxyBufferCount, float tickSecondsToSnap) +{ + SnapEvent * snapEvent = NULL; + PX_ASSERT(NULL != fractureEventProxyBufferStart); + PX_ASSERT(0 != fractureEventProxyBufferCount); + PX_ASSERT(tickSecondsToSnap >= 0.0f); + snapEvent = PX_NEW(SnapEvent)(fractureEventProxyBufferStart, fractureEventProxyBufferCount, tickSecondsToSnap); + return snapEvent; +} + +void SnapEvent::onDestroy() +{ + PX_ASSERT(NULL != fractureEventProxyBufferStart); + PX_DELETE([]fractureEventProxyBufferStart); // derived from UserAllocated, don't have to use PX_FREE(x) + fractureEventProxyBufferStart = NULL; + PX_DELETE(this); +} + +bool SnapEvent::isRipeAfterUpdatingTime(float deltaTime) +{ + bool isRipeAfterUpdatingTime = false; + PX_ASSERT(deltaTime >= 0.0f); + if(tickSecondsRemainingToSnap >= 0.0f) + { + PX_ASSERT(deltaTime > FLT_EPSILON); + tickSecondsRemainingToSnap -= deltaTime; + if(tickSecondsRemainingToSnap < 0.0f) + { + isRipeAfterUpdatingTime = true; + } + } + return isRipeAfterUpdatingTime; +} + +bool SnapEvent::isExpired() const +{ + return (tickSecondsRemainingToSnap < 0.0f); +} + +uint32_t SnapEvent::getFractureEventProxyCount() const +{ + return fractureEventProxyBufferCount; +} + +const FractureEventProxy & SnapEvent::getFractureEventProxy(uint32_t index) const +{ + PX_ASSERT(index < fractureEventProxyBufferCount); + PX_ASSERT(NULL != fractureEventProxyBufferStart); + return fractureEventProxyBufferStart[index]; +} + +SnapEvent::SnapEvent(FractureEventProxy * fractureEventProxyBufferStart_, uint32_t fractureEventProxyBufferCount_, float tickSecondsToSnap_) + :fractureEventProxyBufferStart(fractureEventProxyBufferStart_) + ,fractureEventProxyBufferCount(fractureEventProxyBufferCount_) + ,tickSecondsRemainingToSnap(tickSecondsToSnap_) +{ + PX_ASSERT(NULL != fractureEventProxyBufferStart); + PX_ASSERT(0 != fractureEventProxyBufferCount); + PX_ASSERT(tickSecondsRemainingToSnap >= 0.0f); +} + +SnapEvent::~SnapEvent() +{ + PX_ASSERT(NULL == fractureEventProxyBufferStart); +} +DestructibleStructureStressSolver::DestructibleStructureStressSolver(const DestructibleStructure & bindedStructureAlias_ , float strength_) + :bindedStructureAlias(bindedStructureAlias_) + ,structureLinkCount(0) + ,structureLinkCondition(NULL) + ,scratchBuffer(NULL) + ,scratchBufferLocked(false) + ,userTimeDelay(PX_MAX_F32) + ,userMassThreshold(PX_MAX_F32) +{ + PX_ASSERT(NULL != &bindedStructureAlias); + + // initialize internal members + structureLinkCount = bindedStructureAlias.chunks.size(); + structureLinkCondition = PX_NEW(uint8_t)[structureLinkCount]; + ::memset(static_cast<void*>(structureLinkCondition), 0x00, structureLinkCount * sizeof(uint8_t)); + for(uint32_t index = 0; index < bindedStructureAlias.supportDepthChunks.size(); ++index) + { + structureLinkCondition[bindedStructureAlias.supportDepthChunks[index]] = DestructibleStructureStressSolver::LinkedChunkExist; + } + scratchBuffer = PX_NEW(uint8_t)[structureLinkCount]; + ::memset(static_cast<void*>(scratchBuffer), 0x00, structureLinkCount * sizeof(uint8_t)); + PX_ASSERT(structureLinkCount > 0 && NULL != structureLinkCondition && NULL != scratchBuffer); + + // get user's parameters + for(physx::Array<DestructibleActorImpl*>::ConstIterator kIter = bindedStructureAlias.destructibles.begin(); kIter != bindedStructureAlias.destructibles.end(); ++kIter) + { + const DestructibleActorImpl & currentDestructibleActor = *(*kIter); + PX_ASSERT(NULL != ¤tDestructibleActor); + const float currentUserTimeDelay = currentDestructibleActor.getStressSolverTimeDelay(); + PX_ASSERT(currentUserTimeDelay >= 0.0f); + const float currentUserMassThreshold = currentDestructibleActor.getStressSolverMassThreshold(); + PX_ASSERT(currentUserMassThreshold >= 0.0f); + if(currentUserTimeDelay < userTimeDelay) + { + userTimeDelay = currentUserTimeDelay; + } + if(currentUserMassThreshold < userMassThreshold) + { + userMassThreshold = currentUserMassThreshold; + } + } + PX_ASSERT(userTimeDelay < PX_MAX_F32); + PX_ASSERT(userMassThreshold < PX_MAX_F32); + //Define the real joint for the chunks within the Actors + isPhysxBasedSim = false; + isSimulating = false; + if(strength_ > 0) + { + createShadowScene(MaxWarmingFrame,MaxActiveCycle,strength_); + } +} + +DestructibleStructureStressSolver::~DestructibleStructureStressSolver() +{ + if(isPhysxBasedSim) + { + removePhysStressSolver(); + } + while(!snapEventContainer.empty()) + { + snapEventContainer.popBack()->onDestroy(); + } + if(NULL != scratchBuffer) + { + PX_ASSERT(!scratchBufferLocked); + PX_FREE(scratchBuffer); // use PX_FREE(x) instead of PX_DELETE([]x) + scratchBuffer = NULL; + } + if(NULL != structureLinkCondition) + { + PX_FREE(structureLinkCondition); // use PX_FREE(x) instead of PX_DELETE([]x) + structureLinkCondition = NULL; + } +} + +void DestructibleStructureStressSolver::onTick(float deltaTime) +{ + PX_ASSERT(deltaTime >= 0.0f); + if(!snapEventContainer.empty()) + { + uint32_t expiredSnapEventCount = 0; + + // update and fracture ripe linked chunk(s) + for(physx::Array<SnapEvent*>::ConstIterator kIter = snapEventContainer.begin(); kIter != snapEventContainer.end(); ++kIter) + { + SnapEvent & currentSnapEvent = *(*kIter); + PX_ASSERT(NULL != ¤tSnapEvent); + const bool snapEventJustRipe = currentSnapEvent.isRipeAfterUpdatingTime(deltaTime); + if(snapEventJustRipe) + { + for(uint32_t index = 0; index < currentSnapEvent.getFractureEventProxyCount(); ++index) + { + // skip fracturing linked chunks that were fractured in the meantime + const FractureEventProxy & currentFractureEventProxy = currentSnapEvent.getFractureEventProxy(index); + PX_ASSERT(NULL != ¤tFractureEventProxy); + const uint32_t currentLinkedChunkIndex = currentFractureEventProxy.rootLinkedChunkIndex; + PX_ASSERT(assertLinkedChunkIndexOk(currentLinkedChunkIndex)); + if(!isLinkedChunkBroken(currentLinkedChunkIndex)) + { + setLinkedChunkBroken(currentLinkedChunkIndex); + const FractureEvent & currentFractureEvent = interpret(currentFractureEventProxy); + PX_ASSERT(NULL != ¤tFractureEvent); + getBindedStructureMutable().fractureChunk(currentFractureEvent); + } + } + continue; + } + else + { + if(currentSnapEvent.isExpired()) + { + ++expiredSnapEventCount; + continue; + } + } + } + + // clear the container if it no longer contain any pending snap events + PX_ASSERT(expiredSnapEventCount <= snapEventContainer.size()); + if(snapEventContainer.size() == expiredSnapEventCount) + { + while(!snapEventContainer.empty()) + { + snapEventContainer.popBack()->onDestroy(); + } + } + } +} + +void DestructibleStructureStressSolver::physcsBasedStressSolverTick() +{ + PX_PROFILE_ZONE("DestructiblePhysBasedStressSolver", GetInternalApexSDK()->getContextId()); + + if(currentWarmingFrame < initialWarmFrames) + { + currentWarmingFrame++; + } + else + { + initializingMaxForce = false; + } + if(continuousNoUpdationCount > MaxLeaveInAdvaceWarmingWindow) + { + initializingMaxForce = false; + } + uint32_t breakChunk = 0xFFFFFFFF; + + if(initializingMaxForce || !isSleep) + { + breakChunk = predictBreakChunk(ShadowSceneDeltaTime,supportStrength); + } + if(currentActiveSimulationFrame < activeCycle) + { + if(isActiveWakedUp) + { + isSleep = false; + } + ++currentActiveSimulationFrame; + } + else + { + isSleep = true; + currentActiveSimulationFrame = 0; + } + isActiveWakedUp = false; + if(!initializingMaxForce) + { + for(uint32_t i = 0;i < this->initialWarmingKillList.size();i++) + { + removeChunkFromShadowScene(true,initialWarmingKillList[i]); + } + initialWarmingKillList.clear(); + for(uint32_t i = 0;i < islandKillList.size();i++) + { + isActiveWakedUp = true; + if(!initializingMaxForce) + { + removeChunkFromShadowScene(false,islandKillList[i]); + } + } + islandKillList.clear(); + } + + + if(breakChunk == 0xFFFFFFFF) + { + return; + } + else + { + breakChunks(breakChunk); + } +} + +void DestructibleStructureStressSolver::removeChunkFromIsland(uint32_t index) +{ + islandKillList.pushBack(index); +} + +void DestructibleStructureStressSolver::breakChunks(uint32_t breakChunk) +{ + removeChunkFromShadowScene(false, breakChunk); + DestructibleStructure::Chunk &chunk = getBindedStructureMutable().chunks[breakChunk]; + if(!chunk.isDestroyed()) + { + FractureEvent e2; + e2.position= getBindedStructureMutable().getChunkWorldCentroid(chunk); + e2.chunkIndexInAsset = chunk.indexInAsset; + e2.impulse= PxVec3(0.0f); + e2.destructibleID = chunk.destructibleID; + e2.flags= chunk.flags; + e2.hitDirection = PxVec3(0.0f); + getBindedStructureMutable().fractureChunk(e2); + } +} + +void DestructibleStructureStressSolver::calculateMaxForce(uint32_t& index, float supportStrength_) +{ + PX_PROFILE_ZONE("DestructiblePhysBasedStressSolverCalculateForce", GetInternalApexSDK()->getContextId()); + float maximumForce = 0; + uint32_t maximumIndex = 0xFFFFFFFF; + PxVec3 linearForce(0),angularForce(0); + uint32_t updateCount = 0; + for(uint32_t i = 0;i < linkedJoint.size();i++) + { + if(!linkedJoint[i].isDestroyed) + { + linkedJoint[i].joint->getConstraint()->getForce(linearForce,angularForce); + forces[linkedJoint[i].actor1Index] += angularForce.magnitude(); + } + } + for(uint32_t i = 0;i<forces.size();i++) + { + if(!shadowActors[i].isDestroyed) + { + shadowActors[i].currentForce = forces[i]; + if(initializingMaxForce) + { + if(forces[i] > shadowActors[i].maxInitialForce) + { + updateCount++; + } + shadowActors[i].maxInitialForce = PxMax( shadowActors[i].maxInitialForce,forces[i]); + } + if(forces[i] > maximumForce) + { + maximumForce = forces[i]; + maximumIndex = i; + } + } + } + for(uint32_t i = 0; i<forces.size();i++) + { + forces[i] = 0; + } + + if(updateCount <= (supportChunkSize/((MaxLeaveInAdvaceWarmingWindow*2)))) + { + if(isNoChunkWarmingUpdate) + { + continuousNoUpdationCount++; + } + isNoChunkWarmingUpdate = true; + } + else + { + isNoChunkWarmingUpdate = false; + continuousNoUpdationCount = 0; + } + if(initializingMaxForce) + { + index = 0xFFFFFFFF; + return; + } + if(maximumIndex < shadowActors.size() && shadowActors[maximumIndex].currentForce >= shadowActors[maximumIndex].maxInitialForce* (1+supportStrength_)) + { + index = bindedStructureAlias.supportDepthChunks[maximumIndex]; + return; + } + else + { + index = 0xFFFFFFFF; + return; + } + return; +} + +void DestructibleStructureStressSolver::removeChunkFromShadowScene(bool localIndex, uint32_t index) +{ + PX_PROFILE_ZONE("DestructiblePhysBasedStressSolverRemoveChunk", GetInternalApexSDK()->getContextId()); + if(!localIndex) + { + index = globalHashedtoSupportChunks[index]; + } + if(index == 0xFFFFFFFF) + { + return; + } + if(initializingMaxForce) + { + initialWarmingKillList.pushBack(index); + return; + } + if(!shadowActors[index].isDestroyed) + { + shadowScene->removeActor(*shadowActors[index].actor); + isActiveWakedUp = true; + shadowActors[index].isDestroyed = true; + } +} + +uint32_t DestructibleStructureStressSolver::predictBreakChunk(float deltaTime, float supportStrength_) +{ + // Simulate shadowScene for prediction + uint32_t maximumIndex = 0xFFFFFFFF; + //if(shadowScene->checkResults()) + { + if(isSimulating) + { + shadowScene->fetchResults(true); + } + } + + shadowScene->simulate(deltaTime); + isSimulating = true; + + calculateMaxForce(maximumIndex,supportStrength_); + return maximumIndex; +} + +void DestructibleStructureStressSolver::resetActiveCycle(uint32_t actCycle) +{ + activeCycle = actCycle; +} + +void DestructibleStructureStressSolver::resetInitialWarmFrames(uint32_t iniWarmFrames) +{ + initialWarmFrames = iniWarmFrames; +} + +void DestructibleStructureStressSolver::resetSupportStrength(float supStrength) +{ + supportStrength = supStrength; +} + +void DestructibleStructureStressSolver::createShadowScene(uint32_t initialWarmFrames_,uint32_t actCycle, float supStrength) +{ + + PX_PROFILE_ZONE("DestructiblePhysBasedStressSolverInitial", GetInternalApexSDK()->getContextId()); + //Initialize Parameters + initializingMaxForce = true; + isSimulating = false; + initialWarmFrames = initialWarmFrames_; + currentWarmingFrame = 0; + supportChunkSize = bindedStructureAlias.supportDepthChunks.size(); + isSleep = true; + isActiveWakedUp = false; + currentActiveSimulationFrame = 0; + continuousNoUpdationCount = 0; + activeCycle = actCycle; + isPhysxBasedSim = true; + activeCycle = actCycle; + supportStrength = supStrength; + isCustomEnablesSimulating = true; + isNoChunkWarmingUpdate = false; + + //Initialize the shadow scene + + bindedStructureAlias.dscene->getApexScene()->getPhysXScene()->lockRead(); + + newSceneSDK = &bindedStructureAlias.dscene->getApexScene()->getPhysXScene()->getPhysics(); + PxSceneDesc sceneDesc(newSceneSDK->getTolerancesScale()); + sceneDesc.gravity = bindedStructureAlias.dscene->getApexScene()->getGravity(); + sceneDesc.cpuDispatcher = PxDefaultCpuDispatcherCreate(4); + sceneDesc.filterCallback = NULL; + sceneDesc.filterShader = bindedStructureAlias.dscene->getApexScene()->getPhysXScene()->getFilterShader(); + shadowScene = newSceneSDK->createScene(sceneDesc); + shadowScene->setSimulationEventCallback(NULL); + + bindedStructureAlias.dscene->getApexScene()->getPhysXScene()->unlockRead(); + + + //Initialize arrays + globalHashedtoSupportChunks.resize(bindedStructureAlias.chunks.size()); + shadowActors.resize(supportChunkSize); + for(uint32_t i = 0;i < supportChunkSize; ++i) + { + globalHashedtoSupportChunks[i] = 0xFFFFFFFF; + } + for(uint32_t i = 0 ;i < supportChunkSize; ++i) + { + globalHashedtoSupportChunks[bindedStructureAlias.supportDepthChunks[i]] = i; + } + PxBounds3 bound; + bound.setEmpty(); + for(uint32_t i = 0; i < supportChunkSize; ++i) + { + if(!bindedStructureAlias.chunks[bindedStructureAlias.supportDepthChunks[i]].isDestroyed()) + { + bound.include(bindedStructureAlias.getChunkWorldCentroid(bindedStructureAlias.chunks[bindedStructureAlias.supportDepthChunks[i]])); + } + } + PxVec3 translate = bound.getCenter(); + for(uint32_t i = 0; i< supportChunkSize; ++i) + { + forces.pushBack(0); + } + //Initialize shadow actors + for(uint32_t i = 0;i < supportChunkSize;++i) + { + const nvidia::destructible::DestructibleStructure::Chunk* chunk = &bindedStructureAlias.chunks[bindedStructureAlias.supportDepthChunks[i]]; + if(!chunk->isDestroyed()/*&&!(chunk->flags&ChunkRemoved)*/) // BRG - reclaimed ChunkRemoved bit. This should not have been used here anyhow - it had function-limited scope + { + shadowActors[i].actor = newSceneSDK->createRigidDynamic(PxTransform(bindedStructureAlias.getChunkWorldCentroid(bindedStructureAlias.chunks[bindedStructureAlias.supportDepthChunks[i]])-translate)); + DestructibleActorImpl* dactor = bindedStructureAlias.dscene->mDestructibles.direct(chunk->destructibleID); + shadowActors[i].actor->setMass(dactor->getChunkMass(chunk->indexInAsset)); + shadowScene->addActor(*shadowActors[i].actor); + shadowActors[i].actor->wakeUp(); + shadowActors[i].isDestroyed = false; + shadowActors[i].currentForce = 0.0; + shadowActors[i].maxInitialForce = 0.0; + //Add the static joint objects to the externally supported chunks + if(chunk->flags& ChunkExternallySupported) + { + PxFixedJointCreate(*newSceneSDK,shadowActors[i].actor,PxTransform(PxVec3(0.0f, 0.0, 0.0f), PxQuat(PxIdentity)),NULL,shadowActors[i].actor->getGlobalPose()); + } + } + else + { + shadowActors[i].isDestroyed=true; + } + } + //Create the joints using a local hash array.. .after that we clear it. + Array<Array<bool> > linkedHash; + linkedHash.resize(supportChunkSize); + for(uint32_t i = 0;i < supportChunkSize;++i) + { + linkedHash[i].resize(supportChunkSize); + for(uint32_t j = 0;j < supportChunkSize; ++j) + { + linkedHash[i][j]=false; + } + } + //Link all the chunks which are overlapping. + for(uint32_t i = 0; i < supportChunkSize;++i) + { + const uint32_t firstOverlapIndex = bindedStructureAlias.firstOverlapIndices[bindedStructureAlias.supportDepthChunks[i]]; + const uint32_t stopOverlapIndex = bindedStructureAlias.firstOverlapIndices[bindedStructureAlias.supportDepthChunks[i]+1]; + for(uint32_t index = firstOverlapIndex; index < stopOverlapIndex; ++index) + { + const uint32_t currentLinkedChunkIndex = bindedStructureAlias.overlaps[index]; + linkedHash[globalHashedtoSupportChunks[currentLinkedChunkIndex]][i]=true; + linkedHash[i][globalHashedtoSupportChunks[currentLinkedChunkIndex]]=true; + } + } + //We use hash since we don't know if there is redundant overlapping info, for example A-B and B-A.So we should gurantee that only one joint is linked between two rigid bodies. + //The overhead to initial hash is not so big since it is in the initializing stage, not affect the frame rate when simulating. + for(uint32_t i = 0; i < supportChunkSize; ++i ) + { + for(uint32_t j = 0; j < i; ++j) + { + if(linkedHash[i][j]) + { + //Create the joints for actor1 and actor2 + if(!shadowActors[i].isDestroyed&&!shadowActors[j].isDestroyed) + { + PxFixedJoint* createdJoint = PxFixedJointCreate(*newSceneSDK,shadowActors[i].actor,shadowActors[j].actor->getGlobalPose(),shadowActors[j].actor,shadowActors[i].actor->getGlobalPose()); + if(createdJoint) + { + LinkedJoint joint; + joint.actor1Index = i; + joint.actor2Index = j; + joint.isDestroyed = false; + joint.joint = createdJoint; + linkedJoint.pushBack(joint); + } + } + } + } + } + for(uint32_t i = 0;i < linkedHash.size(); ++i) + { + linkedHash[i].clear(); + } + linkedHash.clear(); +} + +void DestructibleStructureStressSolver::enablePhyStressSolver(float strength) +{ + PX_ASSERT(strength > 0); + isCustomEnablesSimulating = true; + if(!isPhysxBasedSim) + { + createShadowScene(MaxWarmingFrame,MaxActiveCycle,strength); + } + bindedStructureAlias.dscene->setStructureUpdate(&getBindedStructureMutable(), true); // Get a tick to update this +} + +void DestructibleStructureStressSolver::removePhysStressSolver() +{ + if(isPhysxBasedSim) + { + for(uint32_t i=0;i<shadowActors.size();i++) + { + if(!shadowActors[i].isDestroyed) + { + shadowScene->removeActor(*shadowActors[i].actor); + } + } + shadowActors.clear(); + for(uint32_t i=0;i<linkedJoint.size();i++) + { + if(!linkedJoint[i].isDestroyed) + { + if(linkedJoint[i].joint) + { + linkedJoint[i].joint->release(); + linkedJoint[i].joint=NULL; + } + } + } + linkedJoint.clear(); + + if (isSimulating) + { + shadowScene->fetchResults(true); + isSimulating = false; + } + + if(shadowScene) + { + shadowScene->release(); + } + + globalHashedtoSupportChunks.clear(); + initialWarmingKillList.clear(); + islandKillList.clear(); + forces.clear(); + } +} + +void DestructibleStructureStressSolver::disablePhyStressSolver() +{ + isCustomEnablesSimulating = false; +} + +void DestructibleStructureStressSolver::onUpdate(uint32_t linkedChunkIndex) +{ + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + if(!isLinkedChunkBroken(linkedChunkIndex)) + { + setLinkedChunkBroken(linkedChunkIndex); + recentlyBrokenLinkedChunkIndices.pushBack(linkedChunkIndex); + } +} + +void DestructibleStructureStressSolver::onResolve() +{ + physx::Array<uint32_t> linkedChunkIndicesForEvaluation; + processLinkedChunkIndicesForEvaluation(linkedChunkIndicesForEvaluation); + if(!linkedChunkIndicesForEvaluation.empty()) + { + evaluateForPotentialIslands(linkedChunkIndicesForEvaluation); + } +} + +void DestructibleStructureStressSolver::processLinkedChunkIndicesForEvaluation(physx::Array<uint32_t> & linkedChunkIndicesForEvaluation) +{ + PX_ASSERT(NULL != &linkedChunkIndicesForEvaluation); + PX_ASSERT(linkedChunkIndicesForEvaluation.empty()); + + StructureScratchBuffer evaluationRecord = acquireScratchBuffer(); + + // avoid getting snap events' links because they either pending fracture or are already broken (the snap event container only clear out when all snap events have been executed) + for(physx::Array<SnapEvent*>::ConstIterator kIter = snapEventContainer.begin(); kIter != snapEventContainer.end(); ++kIter) + { + SnapEvent & currentSnapEvent = *(*kIter); + PX_ASSERT(NULL != ¤tSnapEvent); + for(uint32_t index = 0; index < currentSnapEvent.getFractureEventProxyCount(); ++index) + { + const uint32_t currentLinkedChunkIndex = currentSnapEvent.getFractureEventProxy(index).rootLinkedChunkIndex; + PX_ASSERT(assertLinkedChunkIndexOk(currentLinkedChunkIndex)); + if(!evaluationRecord.isOccupied(currentLinkedChunkIndex)) + { + evaluationRecord.setOccupied(currentLinkedChunkIndex); + } + } + } + + // push unique adjacent unbroken links of recently broken links + while(!recentlyBrokenLinkedChunkIndices.empty()) + { + const uint32_t currentLinkedChunkIndex = recentlyBrokenLinkedChunkIndices.popBack(); + PX_ASSERT(assertLinkedChunkIndexOk(currentLinkedChunkIndex)); + physx::Array<uint32_t> unbrokenAdjacentLinkedChunkIndices; + getUnbrokenAdjacentLinkedChunkIndices(currentLinkedChunkIndex, unbrokenAdjacentLinkedChunkIndices); + for(physx::Array<uint32_t>::ConstIterator kIter = unbrokenAdjacentLinkedChunkIndices.begin(); kIter != unbrokenAdjacentLinkedChunkIndices.end(); ++kIter) + { + const uint32_t currentUnbrokenAdjacentLinkedChunkIndex = *kIter; + PX_ASSERT(assertLinkedChunkIndexOk(currentUnbrokenAdjacentLinkedChunkIndex)); + if(!evaluationRecord.isOccupied(currentUnbrokenAdjacentLinkedChunkIndex)) + { + evaluationRecord.setOccupied(currentUnbrokenAdjacentLinkedChunkIndex); + linkedChunkIndicesForEvaluation.pushBack(currentUnbrokenAdjacentLinkedChunkIndex); + } + } + } + + // push unique previously-identified strained links + if(!strainedLinkedChunkIndices.empty()) + { + bool containerRequireRefresh = false; + + // we also take this chance to mark links that may already be broken off + for(physx::Array<uint32_t>::Iterator iter = strainedLinkedChunkIndices.begin(); iter != strainedLinkedChunkIndices.end(); ++iter) + { + const uint32_t currentLinkedChunkIndex = *iter; + PX_ASSERT(assertLinkedChunkIndexOk(currentLinkedChunkIndex)); + PX_ASSERT(InvalidLinkedChunkIndex != *iter); + if(isLinkedChunkBroken(currentLinkedChunkIndex)) + { + *iter = InvalidLinkedChunkIndex; + containerRequireRefresh = true; + } + else + { + PX_ASSERT(isLinkedChunkStrained(currentLinkedChunkIndex)); + if(!evaluationRecord.isOccupied(currentLinkedChunkIndex)) + { + evaluationRecord.setOccupied(currentLinkedChunkIndex); + linkedChunkIndicesForEvaluation.pushBack(currentLinkedChunkIndex); + } + } + } + + // update the container to hold only unbroken links + if(containerRequireRefresh) + { + physx::Array<uint32_t> updatedContainer; + for(physx::Array<uint32_t>::ConstIterator kIter = strainedLinkedChunkIndices.begin(); kIter != strainedLinkedChunkIndices.end(); ++kIter) + { + if(InvalidLinkedChunkIndex != *kIter) + { + updatedContainer.pushBack(*kIter); + } + } + strainedLinkedChunkIndices = updatedContainer; + } + } + + relinquishScratchBuffer(); + PX_ASSERT(assertLinkedChunkIndicesForEvaluationOk(linkedChunkIndicesForEvaluation)); + PX_ASSERT(recentlyBrokenLinkedChunkIndices.empty()); +} + +void DestructibleStructureStressSolver::evaluateForPotentialIslands(const physx::Array<uint32_t> & linkedChunkIndicesForEvaluation) +{ + PX_COMPILE_TIME_ASSERT(2 == DestructibleStructureStressSolver::PathTraversalCount); + PX_ASSERT(NULL != &linkedChunkIndicesForEvaluation); + PX_ASSERT(!linkedChunkIndicesForEvaluation.empty()); + for(physx::Array<uint32_t>::ConstIterator kIter = linkedChunkIndicesForEvaluation.begin(); kIter != linkedChunkIndicesForEvaluation.end(); ++kIter) + { + const uint32_t currentLinkedChunkIndex = *kIter; + PX_ASSERT(assertLinkedChunkIndexOk(currentLinkedChunkIndex)); + physx::Array<uint32_t> unbrokenAdjacentLinkedChunkIndices; + if(passLinkCountTest(currentLinkedChunkIndex, unbrokenAdjacentLinkedChunkIndices)) + { + PX_ASSERT(!unbrokenAdjacentLinkedChunkIndices.empty()); + uint32_t linkedChunkIndicesForTraversal[2] = {InvalidLinkedChunkIndex, InvalidLinkedChunkIndex}; + if(passLinkAdjacencyTest(unbrokenAdjacentLinkedChunkIndices, linkedChunkIndicesForTraversal)) + { + PX_ASSERT(InvalidLinkedChunkIndex != linkedChunkIndicesForTraversal[0] && InvalidLinkedChunkIndex != linkedChunkIndicesForTraversal[1]); + evaluateForPotentialPeninsulas(currentLinkedChunkIndex, linkedChunkIndicesForTraversal); + } + } + } +} + +bool DestructibleStructureStressSolver::passLinkCountTest(uint32_t linkedChunkIndex, physx::Array<uint32_t> & unbrokenAdjacentLinkedChunkIndices) const +{ + PX_COMPILE_TIME_ASSERT(2 == DestructibleStructureStressSolver::LowerLimitActivationCount && 3 == DestructibleStructureStressSolver::UpperLimitActivationCount); + bool passLinkCountTest = false; + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + PX_ASSERT(NULL != &unbrokenAdjacentLinkedChunkIndices); + PX_ASSERT(unbrokenAdjacentLinkedChunkIndices.empty()); + + // check that the candidate linked chunk has 2 or 3 remaining unbroken links, and that initially it had more + const uint32_t firstOverlapIndex = bindedStructureAlias.firstOverlapIndices[linkedChunkIndex]; + const uint32_t stopOverlapIndex = bindedStructureAlias.firstOverlapIndices[linkedChunkIndex + 1]; + const uint32_t initialLinkCount = stopOverlapIndex - firstOverlapIndex; + if(initialLinkCount > 2) + { + uint32_t unbrokenLinkCount = 0; + for(uint32_t index = firstOverlapIndex; index < stopOverlapIndex; ++index) + { + const uint32_t currentLinkedChunkIndex = bindedStructureAlias.overlaps[index]; + if(!isLinkedChunkBroken(currentLinkedChunkIndex)) + { + ++unbrokenLinkCount; + if(unbrokenLinkCount > 3) + { + break; + } + } + } + switch(unbrokenLinkCount) + { + case 0: + // ignore + break; + case 1: + // ignore + break; + case 2: + { + PX_ASSERT(initialLinkCount > 2); + getUnbrokenAdjacentLinkedChunkIndices(linkedChunkIndex, unbrokenAdjacentLinkedChunkIndices); + passLinkCountTest = true; + } + break; + case 3: + { + if(initialLinkCount > 3) + { + getUnbrokenAdjacentLinkedChunkIndices(linkedChunkIndex, unbrokenAdjacentLinkedChunkIndices); + passLinkCountTest = true; + } + } + break; + case 4: + // ignore + break; + default: + PX_ASSERT(!"!"); + } + } + PX_ASSERT(passLinkCountTest ? (2 == unbrokenAdjacentLinkedChunkIndices.size() || 3 == unbrokenAdjacentLinkedChunkIndices.size()) : unbrokenAdjacentLinkedChunkIndices.empty()); + return passLinkCountTest; +} + +bool DestructibleStructureStressSolver::passLinkAdjacencyTest(const physx::Array<uint32_t> & unbrokenAdjacentLinkedChunkIndices, uint32_t (&linkedChunkIndicesForTraversal)[2]) const +{ + PX_COMPILE_TIME_ASSERT(2 == DestructibleStructureStressSolver::LowerLimitActivationCount && 3 == DestructibleStructureStressSolver::UpperLimitActivationCount); + PX_COMPILE_TIME_ASSERT(2 == DestructibleStructureStressSolver::PathTraversalCount); + bool passLinkAdjacencyTest = false; + PX_ASSERT(NULL != &unbrokenAdjacentLinkedChunkIndices); + PX_ASSERT(2 == unbrokenAdjacentLinkedChunkIndices.size() || 3 == unbrokenAdjacentLinkedChunkIndices.size()); + PX_ASSERT(NULL != linkedChunkIndicesForTraversal); + linkedChunkIndicesForTraversal[0] = InvalidLinkedChunkIndex; + linkedChunkIndicesForTraversal[1] = InvalidLinkedChunkIndex; + + // check that the candidate linked chunk has 2 traversal paths which are not immediately adjacent to each other, and that only 1 traversal path can optionally include 1 different starting point + const uint32_t unbrokenLinkCount = unbrokenAdjacentLinkedChunkIndices.size(); + switch(unbrokenLinkCount) + { + case 2: + { + // the 2 linked chunks must not be adjacent to each other + if(!areUnbrokenLinkedChunksAdjacent(unbrokenAdjacentLinkedChunkIndices[0], unbrokenAdjacentLinkedChunkIndices[1])) + { + linkedChunkIndicesForTraversal[0] = unbrokenAdjacentLinkedChunkIndices[0]; + linkedChunkIndicesForTraversal[1] = unbrokenAdjacentLinkedChunkIndices[1]; + passLinkAdjacencyTest = true; + } + } + break; + case 3: + { + // if 2 linked chunks are adjacent, the 3rd linked chunk cannot be adjacent to either one + if(areUnbrokenLinkedChunksAdjacent(unbrokenAdjacentLinkedChunkIndices[0], unbrokenAdjacentLinkedChunkIndices[1])) + { + if(!areUnbrokenLinkedChunksAdjacent(unbrokenAdjacentLinkedChunkIndices[0], unbrokenAdjacentLinkedChunkIndices[2]) && + !areUnbrokenLinkedChunksAdjacent(unbrokenAdjacentLinkedChunkIndices[1], unbrokenAdjacentLinkedChunkIndices[2]) ) + { + linkedChunkIndicesForTraversal[0] = unbrokenAdjacentLinkedChunkIndices[0]; + linkedChunkIndicesForTraversal[1] = unbrokenAdjacentLinkedChunkIndices[2]; + passLinkAdjacencyTest = true; + } + } + // if 2 linked chunks are not adjacent, the 3rd linked chunk must be adjacent to only one other linked chunk + else + { + if( areUnbrokenLinkedChunksAdjacent(unbrokenAdjacentLinkedChunkIndices[0], unbrokenAdjacentLinkedChunkIndices[2]) ? + !areUnbrokenLinkedChunksAdjacent(unbrokenAdjacentLinkedChunkIndices[1], unbrokenAdjacentLinkedChunkIndices[2]) : + areUnbrokenLinkedChunksAdjacent(unbrokenAdjacentLinkedChunkIndices[1], unbrokenAdjacentLinkedChunkIndices[2]) ) + { + linkedChunkIndicesForTraversal[0] = unbrokenAdjacentLinkedChunkIndices[0]; + linkedChunkIndicesForTraversal[1] = unbrokenAdjacentLinkedChunkIndices[1]; + passLinkAdjacencyTest = true; + } + } + } + break; + default: + PX_ASSERT(!"!"); + } + PX_ASSERT(passLinkAdjacencyTest ? (InvalidLinkedChunkIndex != linkedChunkIndicesForTraversal[0] && InvalidLinkedChunkIndex != linkedChunkIndicesForTraversal[1]) : (InvalidLinkedChunkIndex == linkedChunkIndicesForTraversal[0] && InvalidLinkedChunkIndex == linkedChunkIndicesForTraversal[1])); + return passLinkAdjacencyTest; +} + +void DestructibleStructureStressSolver::evaluateForPotentialPeninsulas(uint32_t rootLinkedChunkIndex, const uint32_t (&linkedChunkIndicesForTraversal)[2]) +{ + PX_COMPILE_TIME_ASSERT(2 == DestructibleStructureStressSolver::PathTraversalCount); + PX_ASSERT(assertLinkedChunkIndexOk(rootLinkedChunkIndex)); + PX_ASSERT(NULL != linkedChunkIndicesForTraversal); + + // collect both peninsulas' data + PeninsulaData peninsulaData[2]; + for(uint32_t index = 0; index < 2; ++index) + { + StructureScratchBuffer traverseRecord = acquireScratchBuffer(); + traverseRecord.setOccupied(rootLinkedChunkIndex); + peninsulaData[index].resetData(); + peninsulaData[index] = traverseLink(linkedChunkIndicesForTraversal[index], traverseRecord); + peninsulaData[index].setRootLinkedChunkIndex(rootLinkedChunkIndex); + relinquishScratchBuffer(); + } + + evaluatePeninsulas(peninsulaData); +} + +PeninsulaData DestructibleStructureStressSolver::traverseLink(uint32_t linkedChunkIndex, StructureScratchBuffer & traverseRecord) const +{ + PeninsulaData peninsulaData; + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + + // this will not count as a valid peninsula if it contains any chunk that is being externally supported + traverseRecord.setOccupied(linkedChunkIndex); + if(0 != (ChunkExternallySupported & bindedStructureAlias.chunks[linkedChunkIndex].flags)) + { + peninsulaData.setFlag(PeninsulaData::PeninsulaEncounteredExternalSupport); + } + if(isLinkedChunkStrained(linkedChunkIndex)) + { + peninsulaData.setFlag(PeninsulaData::PeninsulaEncounteredAnotherWeakLink); + } + + // gather data for remaining unbroken links + if(peninsulaData.isValid()) + { + peninsulaData.setLinkedChunkData(getActorChunkPair(linkedChunkIndex), Int2Type<StressEvaluationEnum>()); + const uint32_t firstOverlapIndex = bindedStructureAlias.firstOverlapIndices[linkedChunkIndex]; + const uint32_t stopOverlapIndex = bindedStructureAlias.firstOverlapIndices[linkedChunkIndex + 1]; + for(uint32_t index = firstOverlapIndex; index < stopOverlapIndex; ++index) + { + const uint32_t currentLinkedChunkIndex = bindedStructureAlias.overlaps[index]; + if(!isLinkedChunkBroken(currentLinkedChunkIndex)) + { + if(!traverseRecord.isOccupied(currentLinkedChunkIndex)) + { + peninsulaData.assimilate(traverseLink(currentLinkedChunkIndex, traverseRecord), Int2Type<StressEvaluationEnum>()); + if(!peninsulaData.isValid()) + { + peninsulaData.resetData(); + break; + } + } + } + } + } + + return peninsulaData; +} + +void DestructibleStructureStressSolver::evaluatePeninsulas(const PeninsulaData (&peninsulasForEvaluation)[2]) +{ + PX_COMPILE_TIME_ASSERT(2 == DestructibleStructureStressSolver::PathTraversalCount); + PX_ASSERT(NULL != peninsulasForEvaluation); + + // determine type of operation + const bool trySnapOffWithinFreeIsland = !peninsulasForEvaluation[0].hasFlag(PeninsulaData::PeninsulaEncounteredExternalSupport) && !peninsulasForEvaluation[1].hasFlag(PeninsulaData::PeninsulaEncounteredExternalSupport); + const bool trySnapOffFromSupportedPeninsula = peninsulasForEvaluation[0].hasFlag(PeninsulaData::PeninsulaEncounteredExternalSupport) ^ peninsulasForEvaluation[1].hasFlag(PeninsulaData::PeninsulaEncounteredExternalSupport); + const bool trackLinkForFutureEvaluation = peninsulasForEvaluation[0].hasFlag(PeninsulaData::PeninsulaEncounteredExternalSupport) && peninsulasForEvaluation[1].hasFlag(PeninsulaData::PeninsulaEncounteredExternalSupport); + PX_ASSERT(trySnapOffWithinFreeIsland ? !trySnapOffFromSupportedPeninsula && !trackLinkForFutureEvaluation : trySnapOffFromSupportedPeninsula ? !trackLinkForFutureEvaluation : trackLinkForFutureEvaluation); + + // try snapping off based on data of the peninsula with more mass + if(trySnapOffWithinFreeIsland) + { + const PeninsulaData & subjectPeninsulaData = peninsulasForEvaluation[0].getDataAggregateMass() > peninsulasForEvaluation[1].getDataAggregateMass() ? peninsulasForEvaluation[0] : peninsulasForEvaluation[1]; + SnapEvent * snapEvent = NULL; + snapEvent = interpret(subjectPeninsulaData, Int2Type<StressEvaluationEnum>()); + if(NULL != snapEvent) + { + snapEventContainer.pushBack(snapEvent); + snapEvent = NULL; + } + } + // try snapping off based on data of the peninsula that is not being externally supported + else if(trySnapOffFromSupportedPeninsula) + { + const PeninsulaData & subjectPeninsulaData = peninsulasForEvaluation[0].hasFlag(PeninsulaData::PeninsulaEncounteredExternalSupport) ? peninsulasForEvaluation[1] : peninsulasForEvaluation[0]; + SnapEvent * snapEvent = NULL; + snapEvent = interpret(subjectPeninsulaData, Int2Type<StressEvaluationEnum>()); + if(NULL != snapEvent) + { + snapEventContainer.pushBack(snapEvent); + snapEvent = NULL; + } + } + // track this link for re-evaluation because it is susceptible to snapping off + else if(trackLinkForFutureEvaluation) + { + PX_ASSERT(peninsulasForEvaluation[0].getRootLinkedChunkIndex() == peninsulasForEvaluation[1].getRootLinkedChunkIndex()); + const uint32_t linkedChunkIndex = peninsulasForEvaluation[0].getRootLinkedChunkIndex(); + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + if(!isLinkedChunkStrained(linkedChunkIndex)) + { + setLinkedChunkStrained(linkedChunkIndex); + strainedLinkedChunkIndices.pushBack(linkedChunkIndex); + } + } +} + +SnapEvent * DestructibleStructureStressSolver::interpret(const PeninsulaData & peninsulaData, Int2Type<StressEvaluationType::EvaluateByCount>) const +{ + SnapEvent * snapEvent= NULL; + PX_ASSERT(NULL != &peninsulaData); + const bool stressConditionPassed = (peninsulaData.getDataChunkCount() > 20); + if(stressConditionPassed) + { + const bool breakAdjacentLinkedChunks = true; + + // set up data for proxy fracture events + physx::Array<uint32_t> unbrokenAdjacentLinkedChunkIndices; + const uint32_t linkedChunkIndex = peninsulaData.getRootLinkedChunkIndex(); + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + if(breakAdjacentLinkedChunks) + { + getUnbrokenAdjacentLinkedChunkIndices(linkedChunkIndex, unbrokenAdjacentLinkedChunkIndices); + } + FractureEventProxy * fractureEventProxyBufferStart = NULL; + const uint32_t fractureEventProxyBufferCount = 1 + unbrokenAdjacentLinkedChunkIndices.size(); + fractureEventProxyBufferStart = PX_NEW(FractureEventProxy)[fractureEventProxyBufferCount]; + ::memset(static_cast<void*>(fractureEventProxyBufferStart), 0x00, fractureEventProxyBufferCount * sizeof(FractureEventProxy)); + + // set up data for primary weak link + ActorChunkPair actorChunkPair = getActorChunkPair(linkedChunkIndex); + FractureEventProxy & fractureEventProxy = fractureEventProxyBufferStart[0]; + fractureEventProxy.rootLinkedChunkIndex = linkedChunkIndex; + fractureEventProxy.chunkIndexInAsset = actorChunkPair.chunkAlias->indexInAsset; + fractureEventProxy.destructibleId = actorChunkPair.actorAlias->getID(); + fractureEventProxy.fractureEventProxyFlags = 0; + fractureEventProxy.fractureEventProxyFlags |= FractureEvent::Snap; + fractureEventProxy.rootLinkedChunkPosition = PxVec3(0.0f); + fractureEventProxy.impulse = PxVec3(0.0f); + + // set up data for secondary weak links + if(breakAdjacentLinkedChunks) + { + for(uint32_t index = 0; index < unbrokenAdjacentLinkedChunkIndices.size(); ++index) + { + ActorChunkPair currentActorChunkPair = getActorChunkPair(unbrokenAdjacentLinkedChunkIndices[index]); + FractureEventProxy & currentFractureEventProxy = fractureEventProxyBufferStart[1 + index]; + currentFractureEventProxy.rootLinkedChunkIndex = unbrokenAdjacentLinkedChunkIndices[index]; + currentFractureEventProxy.chunkIndexInAsset = currentActorChunkPair.chunkAlias->indexInAsset; + currentFractureEventProxy.destructibleId = currentActorChunkPair.actorAlias->getID(); + currentFractureEventProxy.fractureEventProxyFlags = 0; + currentFractureEventProxy.fractureEventProxyFlags |= FractureEvent::Snap; + currentFractureEventProxy.rootLinkedChunkPosition = PxVec3(0.0f); + currentFractureEventProxy.impulse = PxVec3(0.0f); + } + } + + // store them in a snap event + const float tickSecondsToSnap = peninsulaData.getDataChunkCount() > 40 ? 2.5f : 5.0f; + PX_ASSERT(NULL != fractureEventProxyBufferStart && 0 != fractureEventProxyBufferCount); + snapEvent = SnapEvent::instantiate(fractureEventProxyBufferStart, fractureEventProxyBufferCount, tickSecondsToSnap); + PX_ASSERT(NULL != snapEvent); + fractureEventProxyBufferStart = NULL; + } + return snapEvent; +} + +SnapEvent * DestructibleStructureStressSolver::interpret(const PeninsulaData & peninsulaData, Int2Type<StressEvaluationType::EvaluateByMoment>) const +{ + SnapEvent * snapEvent= NULL; + PX_ASSERT(NULL != &peninsulaData); + const bool stressConditionPassed = peninsulaData.getDataAggregateMass() > userMassThreshold; + if(stressConditionPassed) + { + // set up data for proxy fracture events + const uint32_t linkedChunkIndex = peninsulaData.getRootLinkedChunkIndex(); + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + FractureEventProxy * fractureEventProxyBufferStart = NULL; + const uint32_t fractureEventProxyBufferCount = 1; + fractureEventProxyBufferStart = PX_NEW(FractureEventProxy)[fractureEventProxyBufferCount]; + ::memset(static_cast<void*>(fractureEventProxyBufferStart), 0x00, fractureEventProxyBufferCount * sizeof(FractureEventProxy)); + + // set up data for primary weak link + ActorChunkPair actorChunkPair = getActorChunkPair(linkedChunkIndex); + FractureEventProxy & fractureEventProxy = fractureEventProxyBufferStart[0]; + fractureEventProxy.rootLinkedChunkIndex = linkedChunkIndex; + fractureEventProxy.chunkIndexInAsset = actorChunkPair.chunkAlias->indexInAsset; + fractureEventProxy.destructibleId = actorChunkPair.actorAlias->getID(); + fractureEventProxy.fractureEventProxyFlags = 0; + fractureEventProxy.fractureEventProxyFlags |= FractureEvent::Snap; + fractureEventProxy.rootLinkedChunkPosition = actorChunkPair.actorAlias->getStructure()->getChunkWorldCentroid(*(actorChunkPair.chunkAlias)); + fractureEventProxy.impulse = -1 * (peninsulaData.getDataGeometricCenter() - fractureEventProxy.rootLinkedChunkPosition).getNormalized(); + + // store them in a snap event + const float tickSecondsToSnap = userTimeDelay; + PX_ASSERT(NULL != fractureEventProxyBufferStart && 0 != fractureEventProxyBufferCount); + snapEvent = SnapEvent::instantiate(fractureEventProxyBufferStart, fractureEventProxyBufferCount, tickSecondsToSnap); + PX_ASSERT(NULL != snapEvent); + fractureEventProxyBufferStart = NULL; + } + return snapEvent; +} + +const FractureEvent & DestructibleStructureStressSolver::interpret(const FractureEventProxy & fractureEventProxy) const +{ + static FractureEvent staticFractureEvent; + PX_ASSERT(NULL != &fractureEventProxy); + ::memset(static_cast<void*>(&staticFractureEvent), 0x00, 1 * sizeof(FractureEvent)); + staticFractureEvent.position = fractureEventProxy.rootLinkedChunkPosition; + staticFractureEvent.chunkIndexInAsset = fractureEventProxy.chunkIndexInAsset; + staticFractureEvent.impulse = fractureEventProxy.impulse; + staticFractureEvent.destructibleID = fractureEventProxy.destructibleId; + staticFractureEvent.flags = fractureEventProxy.fractureEventProxyFlags; + staticFractureEvent.hitDirection = PxVec3(0.0f); + return staticFractureEvent; +} + +bool DestructibleStructureStressSolver::isLinkedChunkBroken(uint32_t linkedChunkIndex) const +{ + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + PX_ASSERT(NULL != structureLinkCondition); + PX_ASSERT(structureLinkCondition[linkedChunkIndex] < DestructibleStructureStressSolver::LinkedChunkInvalidMaxFlag); + PX_ASSERT(0 != (DestructibleStructureStressSolver::LinkedChunkExist & structureLinkCondition[linkedChunkIndex])); + return (0 != (DestructibleStructureStressSolver::LinkedChunkBroken & structureLinkCondition[linkedChunkIndex])); +} + +void DestructibleStructureStressSolver::setLinkedChunkBroken(uint32_t linkedChunkIndex) +{ + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + PX_ASSERT(NULL != structureLinkCondition); + PX_ASSERT(0 != (DestructibleStructureStressSolver::LinkedChunkExist & structureLinkCondition[linkedChunkIndex])); + PX_ASSERT(0 == (DestructibleStructureStressSolver::LinkedChunkBroken & structureLinkCondition[linkedChunkIndex]) && "usage error!"); + structureLinkCondition[linkedChunkIndex] |= DestructibleStructureStressSolver::LinkedChunkBroken; + PX_ASSERT(structureLinkCondition[linkedChunkIndex] < DestructibleStructureStressSolver::LinkedChunkInvalidMaxFlag); +} + +bool DestructibleStructureStressSolver::isLinkedChunkStrained(uint32_t linkedChunkIndex) const +{ + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + PX_ASSERT(NULL != structureLinkCondition); + PX_ASSERT(structureLinkCondition[linkedChunkIndex] < DestructibleStructureStressSolver::LinkedChunkInvalidMaxFlag); + PX_ASSERT(0 != (DestructibleStructureStressSolver::LinkedChunkExist & structureLinkCondition[linkedChunkIndex])); + PX_ASSERT(!isLinkedChunkBroken(linkedChunkIndex) && "usage error!"); + return (0 != (DestructibleStructureStressSolver::LinkedChunkStrained & structureLinkCondition[linkedChunkIndex])); +} + +void DestructibleStructureStressSolver::setLinkedChunkStrained(uint32_t linkedChunkIndex) +{ + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + PX_ASSERT(NULL != structureLinkCondition); + PX_ASSERT(0 != (DestructibleStructureStressSolver::LinkedChunkExist & structureLinkCondition[linkedChunkIndex])); + PX_ASSERT(0 == (DestructibleStructureStressSolver::LinkedChunkStrained & structureLinkCondition[linkedChunkIndex]) && "usage error!"); + PX_ASSERT(!isLinkedChunkBroken(linkedChunkIndex) && "usage error!"); + structureLinkCondition[linkedChunkIndex] |= DestructibleStructureStressSolver::LinkedChunkStrained; + PX_ASSERT(structureLinkCondition[linkedChunkIndex] < DestructibleStructureStressSolver::LinkedChunkInvalidMaxFlag); +} + +void DestructibleStructureStressSolver::getUnbrokenAdjacentLinkedChunkIndices(uint32_t linkedChunkIndex, physx::Array<uint32_t> & unbrokenAdjacentLinkedChunkIndices) const +{ + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndex)); + PX_ASSERT(NULL != &unbrokenAdjacentLinkedChunkIndices); + PX_ASSERT(unbrokenAdjacentLinkedChunkIndices.empty()); + const uint32_t firstOverlapIndex = bindedStructureAlias.firstOverlapIndices[linkedChunkIndex]; + const uint32_t stopOverlapIndex = bindedStructureAlias.firstOverlapIndices[linkedChunkIndex + 1]; + for(uint32_t index = firstOverlapIndex; index < stopOverlapIndex; ++index) + { + const uint32_t currentLinkedChunkIndex = bindedStructureAlias.overlaps[index]; + if(!isLinkedChunkBroken(currentLinkedChunkIndex)) + { + unbrokenAdjacentLinkedChunkIndices.pushBack(currentLinkedChunkIndex); + } + } +} + +bool DestructibleStructureStressSolver::areUnbrokenLinkedChunksAdjacent(uint32_t linkedChunkIndexReference, uint32_t linkedChunkIndexSubject) const +{ + bool areUnbrokenLinkedChunksAdjacent = false; + PX_ASSERT(assertLinkedChunkIndexOk(linkedChunkIndexReference) && assertLinkedChunkIndexOk(linkedChunkIndexSubject)); + PX_ASSERT(!isLinkedChunkBroken(linkedChunkIndexReference) && !isLinkedChunkBroken(linkedChunkIndexSubject)); + const uint32_t firstOverlapIndex = bindedStructureAlias.firstOverlapIndices[linkedChunkIndexReference]; + const uint32_t stopOverlapIndex = bindedStructureAlias.firstOverlapIndices[linkedChunkIndexReference + 1]; + for(uint32_t index = firstOverlapIndex; index < stopOverlapIndex; ++index) + { + const uint32_t currentLinkedChunkIndex = bindedStructureAlias.overlaps[index]; + if(currentLinkedChunkIndex == linkedChunkIndexSubject) + { + PX_ASSERT(!isLinkedChunkBroken(currentLinkedChunkIndex)); + areUnbrokenLinkedChunksAdjacent = true; + break; + } + } + return areUnbrokenLinkedChunksAdjacent; +} + +ActorChunkPair DestructibleStructureStressSolver::getActorChunkPair(uint32_t chunkIndexInStructure) const +{ + const DestructibleActorImpl * actor = NULL; + const DestructibleStructure::Chunk * chunk = NULL; + PX_ASSERT(chunkIndexInStructure < bindedStructureAlias.chunks.size()); + for(physx::Array<DestructibleActorImpl*>::ConstIterator kIter = bindedStructureAlias.destructibles.begin(); kIter != bindedStructureAlias.destructibles.end(); ++kIter) + { + const DestructibleActorImpl * currentDestructibleActor = *kIter; + PX_ASSERT(NULL != currentDestructibleActor); + if(chunkIndexInStructure >= currentDestructibleActor->getFirstChunkIndex() && chunkIndexInStructure < (currentDestructibleActor->getFirstChunkIndex() + currentDestructibleActor->getDestructibleAsset()->getChunkCount())) + { + actor = currentDestructibleActor; + chunk = &(bindedStructureAlias.chunks[chunkIndexInStructure]); + PX_ASSERT((actor->getFirstChunkIndex() + chunk->indexInAsset) == chunkIndexInStructure); + break; + } + } + PX_ASSERT(NULL != actor && NULL != chunk); + return ActorChunkPair(actor, chunk); +} + +StructureScratchBuffer DestructibleStructureStressSolver::acquireScratchBuffer() const +{ + // bitwise const qualifier only - so as to allow const methods to use this method too + PX_ASSERT(!scratchBufferLocked); + scratchBufferLocked = true; + return StructureScratchBuffer(scratchBuffer, structureLinkCount); +} + +void DestructibleStructureStressSolver::relinquishScratchBuffer() const +{ + // bitwise const qualifier only - so as to allow const methods to use this method too + PX_ASSERT(scratchBufferLocked); + scratchBufferLocked = false; +} + +DestructibleStructure & DestructibleStructureStressSolver::getBindedStructureMutable() +{ + return const_cast<DestructibleStructure&>(bindedStructureAlias); +} + +bool DestructibleStructureStressSolver::assertLinkedChunkIndexOk(uint32_t linkedChunkIndex) const +{ + PX_ASSERT(bindedStructureAlias.chunks.size() == structureLinkCount ? linkedChunkIndex < structureLinkCount : false); + PX_UNUSED(linkedChunkIndex); + return true; +} + +bool DestructibleStructureStressSolver::assertLinkedChunkIndicesForEvaluationOk(const physx::Array<uint32_t> & linkedChunkIndicesForEvaluation) const +{ + for(physx::Array<uint32_t>::ConstIterator kIter = linkedChunkIndicesForEvaluation.begin(); kIter != linkedChunkIndicesForEvaluation.end(); ++kIter) + { + const uint32_t currentLinkedChunkIndex = *kIter; + PX_ASSERT(assertLinkedChunkIndexOk(currentLinkedChunkIndex)); + PX_ASSERT(!isLinkedChunkBroken(currentLinkedChunkIndex)); + PX_UNUSED(currentLinkedChunkIndex); + } + for(physx::Array<uint32_t>::ConstIterator kIter = linkedChunkIndicesForEvaluation.begin(); kIter != linkedChunkIndicesForEvaluation.end(); ++kIter) + { + const uint32_t referenceLinkedChunkIndex = *kIter; + for(physx::Array<uint32_t>::ConstIterator kJter = kIter + 1; kJter != linkedChunkIndicesForEvaluation.end(); ++kJter) + { + const uint32_t subjectLinkedChunkIndex = *kJter; + PX_ASSERT(referenceLinkedChunkIndex != subjectLinkedChunkIndex); + PX_UNUSED(referenceLinkedChunkIndex); + PX_UNUSED(subjectLinkedChunkIndex); + } + } + return true; +} + +} // namespace destructible +} // namespace nvidia
\ No newline at end of file diff --git a/APEX_1.4/module/destructible/src/ModuleDestructibleImpl.cpp b/APEX_1.4/module/destructible/src/ModuleDestructibleImpl.cpp new file mode 100644 index 00000000..32476372 --- /dev/null +++ b/APEX_1.4/module/destructible/src/ModuleDestructibleImpl.cpp @@ -0,0 +1,1079 @@ +/* + * 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. + */ + + +#include "ApexDefs.h" +#include "ModuleDestructibleImpl.h" +#include "ModuleDestructibleRegistration.h" +#include "DestructibleAssetProxy.h" +#include "DestructibleActorProxy.h" +#include "DestructibleActorJointProxy.h" +#include "DestructibleScene.h" +#include "ApexSharedUtils.h" +#include "PsMemoryBuffer.h" + +#include "PxPhysics.h" +#include "PxScene.h" + +#include "ApexStream.h" +#include "ModulePerfScope.h" +using namespace destructible; + +#include "ApexSDKIntl.h" +#include "ApexUsingNamespace.h" +#include "WriteCheck.h" + +namespace nvidia +{ +namespace apex +{ + +#if defined(_USRDLL) || PX_OSX + +/* Modules don't have to link against the framework, they keep their own */ +ApexSDKIntl* gApexSdk = 0; +ApexSDK* GetApexSDK() +{ + return gApexSdk; +} +ApexSDKIntl* GetInternalApexSDK() +{ + return gApexSdk; +} + +APEX_API Module* CALL_CONV createModule( + ApexSDKIntl* inSdk, + ModuleIntl** niRef, + uint32_t APEXsdkVersion, + uint32_t PhysXsdkVersion, + ApexCreateError* errorCode) +{ + if (APEXsdkVersion != APEX_SDK_VERSION) + { + if (errorCode) + { + *errorCode = APEX_CE_WRONG_VERSION; + } + return NULL; + } + + if (PhysXsdkVersion != PX_PHYSICS_VERSION) + { + if (errorCode) + { + *errorCode = APEX_CE_WRONG_VERSION; + } + return NULL; + } + + gApexSdk = inSdk; + destructible::ModuleDestructibleImpl* impl = PX_NEW(destructible::ModuleDestructibleImpl)(inSdk); + *niRef = (ModuleIntl*) impl; + return (Module*) impl; +} +#else +/* Statically linking entry function */ +void instantiateModuleDestructible() +{ + ApexSDKIntl* sdk = GetInternalApexSDK(); + destructible::ModuleDestructibleImpl* impl = PX_NEW(destructible::ModuleDestructibleImpl)(sdk); + sdk->registerExternalModule((Module*) impl, (ModuleIntl*) impl); +} +#endif +} + +namespace destructible +{ + +AuthObjTypeID DestructibleAssetImpl::mAssetTypeID; // Static class member +#ifdef WITHOUT_APEX_AUTHORING + +class DestructibleAssetDummyAuthoring : public AssetAuthoring, public UserAllocated +{ +public: + DestructibleAssetDummyAuthoring(ModuleDestructibleImpl* module, ResourceList& list, NvParameterized::Interface* params, const char* name) + { + PX_UNUSED(module); + PX_UNUSED(list); + PX_UNUSED(params); + PX_UNUSED(name); + } + + DestructibleAssetDummyAuthoring(ModuleDestructibleImpl* module, ResourceList& list, const char* name) + { + PX_UNUSED(module); + PX_UNUSED(list); + PX_UNUSED(name); + } + + DestructibleAssetDummyAuthoring(ModuleDestructibleImpl* module, ResourceList& list) + { + PX_UNUSED(module); + PX_UNUSED(list); + } + + virtual ~DestructibleAssetDummyAuthoring() {} + + virtual void setToolString(const char* /*toolName*/, const char* /*toolVersion*/, uint32_t /*toolChangelist*/) + { + + } + + virtual void release() + { + destroy(); + } + + // internal + void destroy() + { + delete this; + } + + +#if 0 + /** + * \brief Save asset configuration to a stream + */ + virtual PxFileBuf& serialize(PxFileBuf& stream) const + { + PX_ASSERT(0); + return stream; + } + + /** + * \brief Load asset configuration from a stream + */ + virtual PxFileBuf& deserialize(PxFileBuf& stream) + { + PX_ASSERT(0); + return stream; + } +#endif + + const char* getName(void) const + { + return NULL; + } + + /** + * \brief Returns the name of this APEX authorable object type + */ + virtual const char* getObjTypeName() const + { + return DESTRUCTIBLE_AUTHORING_TYPE_NAME; + } + + /** + * \brief Prepares a fully authored Asset Authoring object for a specified platform + */ + virtual bool prepareForPlatform(nvidia::apex::PlatformTag) + { + PX_ASSERT(0); + return false; + } + + /** + * \brief Save asset's NvParameterized interface, may return NULL + */ + virtual NvParameterized::Interface* getNvParameterized() const + { + PX_ASSERT(0); + return NULL; + } + + virtual NvParameterized::Interface* releaseAndReturnNvParameterizedInterface(void) + { + PX_ALWAYS_ASSERT(); + return NULL; + } +}; + +typedef ApexAuthorableObject<ModuleDestructibleImpl, DestructibleAssetProxy, DestructibleAssetDummyAuthoring> DestructionAO; + + +#else +typedef ApexAuthorableObject<ModuleDestructibleImpl, DestructibleAssetProxy, DestructibleAssetAuthoringProxy> DestructionAO; +#endif + + +ModuleDestructibleImpl::ModuleDestructibleImpl(ApexSDKIntl* inSdk) : + m_isInitialized(false), + m_maxChunkDepthOffset(0), + m_maxChunkSeparationLOD(0.5f), + m_maxFracturesProcessedPerFrame(UINT32_MAX), + m_maxActorsCreateablePerFrame(UINT32_MAX), + m_dynamicActorFIFOMax(0), + m_chunkFIFOMax(0), + m_sortByBenefit(false), + m_chunkReport(NULL), + m_impactDamageReport(NULL), + m_chunkReportBitMask(0xffffffff), + m_destructiblePhysXActorReport(NULL), + m_chunkReportMaxFractureEventDepth(0xffffffff), + m_chunkStateEventCallbackSchedule(DestructibleCallbackSchedule::Disabled), + m_chunkCrumbleReport(NULL), + m_chunkDustReport(NULL), + m_massScale(1.0f), + m_scaledMassExponent(0.5f), + mApexDestructiblePreviewParams(NULL), + mUseLegacyChunkBoundsTesting(false), + mUseLegacyDamageRadiusSpread(false), + mChunkCollisionHullCookingScale(1.0f), + mFractureTools(NULL) +{ + mName = "Destructible"; + mSdk = inSdk; + mApiProxy = this; + mModuleParams = NULL; + + NvParameterized::Traits* traits = mSdk->getParameterizedTraits(); + if (traits) + { + ModuleDestructibleRegistration::invokeRegistration(traits); + mApexDestructiblePreviewParams = traits->createNvParameterized(DestructiblePreviewParam::staticClassName()); + } + + /* Register this module's authorable object types and create their namespaces */ + const char* pName = DestructibleAssetParameters::staticClassName(); + DestructionAO* eAO = PX_NEW(DestructionAO)(this, mAuthorableObjects, pName); + DestructibleAssetImpl::mAssetTypeID = eAO->getResID(); + + mCachedData = PX_NEW(DestructibleModuleCachedData)(getModuleID()); + +#ifndef WITHOUT_APEX_AUTHORING + mFractureTools = PX_NEW(FractureTools)(); +#endif +} + +AuthObjTypeID ModuleDestructibleImpl::getModuleID() const +{ + READ_ZONE(); + return DestructibleAssetImpl::mAssetTypeID; +} + +ModuleDestructibleImpl::~ModuleDestructibleImpl() +{ + m_destructibleSceneList.clear(); + + PX_DELETE(mCachedData); + mCachedData = NULL; +} + +NvParameterized::Interface* ModuleDestructibleImpl::getDefaultModuleDesc() +{ + READ_ZONE(); + NvParameterized::Traits* traits = mSdk->getParameterizedTraits(); + + if (!mModuleParams) + { + mModuleParams = DYNAMIC_CAST(DestructibleModuleParameters*) + (traits->createNvParameterized("DestructibleModuleParameters")); + PX_ASSERT(mModuleParams); + } + else + { + mModuleParams->initDefaults(); + } + + return mModuleParams; +} + +void ModuleDestructibleImpl::init(NvParameterized::Interface& desc) +{ + WRITE_ZONE(); + if (nvidia::strcmp(desc.className(), DestructibleModuleParameters::staticClassName()) == 0) + { + DestructibleModuleParameters* params = DYNAMIC_CAST(DestructibleModuleParameters*)(&desc); + setValidBoundsPadding(params->validBoundsPadding); + setMaxDynamicChunkIslandCount(params->maxDynamicChunkIslandCount); + setSortByBenefit(params->sortFIFOByBenefit); + setMaxChunkSeparationLOD(params->maxChunkSeparationLOD); + setMaxActorCreatesPerFrame(params->maxActorCreatesPerFrame); + setMaxChunkDepthOffset(params->maxChunkDepthOffset); + + if (params->massScale > 0.0f) + { + m_massScale = params->massScale; + } + + if (params->scaledMassExponent > 0.0f && params->scaledMassExponent <= 1.0f) + { + m_scaledMassExponent = params->scaledMassExponent; + } + + m_isInitialized = true; + for (uint32_t i = 0; i < m_destructibleSceneList.getSize(); ++i) + { + // when module is created after the scene + (DYNAMIC_CAST(DestructibleScene*)(m_destructibleSceneList.getResource(i)))->initModuleSettings(); + } + } + else + { + APEX_INVALID_PARAMETER("The NvParameterized::Interface object is the wrong type"); + } +} + +ModuleSceneIntl* ModuleDestructibleImpl::createInternalModuleScene(SceneIntl& scene, RenderDebugInterface* debugRender) +{ + return PX_NEW(DestructibleScene)(*this, scene, debugRender, m_destructibleSceneList); +} + +void ModuleDestructibleImpl::releaseModuleSceneIntl(ModuleSceneIntl& scene) +{ + DestructibleScene* ds = DYNAMIC_CAST(DestructibleScene*)(&scene); + ds->destroy(); +} + +uint32_t ModuleDestructibleImpl::forceLoadAssets() +{ + uint32_t loadedAssetCount = 0; + + for (uint32_t i = 0; i < mAuthorableObjects.getSize(); i++) + { + AuthorableObjectIntl* ao = static_cast<AuthorableObjectIntl*>(mAuthorableObjects.getResource(i)); + loadedAssetCount += ao->forceLoadAssets(); + } + return loadedAssetCount; +} + +DestructibleScene* ModuleDestructibleImpl::getDestructibleScene(const Scene& apexScene) const +{ + for (uint32_t i = 0 ; i < m_destructibleSceneList.getSize() ; i++) + { + DestructibleScene* ds = DYNAMIC_CAST(DestructibleScene*)(m_destructibleSceneList.getResource(i)); + if (ds->mApexScene == &apexScene) + { + return ds; + } + } + + PX_ASSERT(!"Unable to locate an appropriate DestructibleScene"); + return NULL; +} + +RenderableIterator* ModuleDestructibleImpl::createRenderableIterator(const Scene& apexScene) +{ + WRITE_ZONE(); + DestructibleScene* ds = getDestructibleScene(apexScene); + if (ds) + { + return ds->createRenderableIterator(); + } + + return NULL; +} + +DestructibleActorJoint* ModuleDestructibleImpl::createDestructibleActorJoint(const DestructibleActorJointDesc& destructibleActorJointDesc, Scene& scene) +{ + WRITE_ZONE(); + if (!destructibleActorJointDesc.isValid()) + { + return NULL; + } + DestructibleScene* ds = getDestructibleScene(scene); + if (ds) + { + return ds->createDestructibleActorJoint(destructibleActorJointDesc); + } + else + { + return NULL; + } +} + +bool ModuleDestructibleImpl::isDestructibleActorJointActive(const DestructibleActorJoint* candidateJoint, Scene& apexScene) const +{ + READ_ZONE(); + PX_ASSERT(candidateJoint != NULL); + PX_ASSERT(&apexScene != NULL); + DestructibleScene* destructibleScene = NULL; + destructibleScene = getDestructibleScene(apexScene); + PX_ASSERT(destructibleScene != NULL); + bool found = false; + if (destructibleScene != NULL) + { + for (uint32_t index = 0; index < destructibleScene->mDestructibleActorJointList.getSize(); ++index) + { + DestructibleActorJoint* activeJoint = NULL; + activeJoint = static_cast<DestructibleActorJoint*>(static_cast<DestructibleActorJointProxy*>((destructibleScene->mDestructibleActorJointList.getResource(index)))); + PX_ASSERT(activeJoint != NULL); + if (activeJoint == candidateJoint) + { + found = true; + break; + } + } + } + return found; +} + +void ModuleDestructibleImpl::setMaxDynamicChunkIslandCount(uint32_t maxCount) +{ + WRITE_ZONE(); + m_dynamicActorFIFOMax = maxCount; +} + +void ModuleDestructibleImpl::setMaxChunkCount(uint32_t maxCount) +{ + WRITE_ZONE(); + m_chunkFIFOMax = maxCount; +} + +void ModuleDestructibleImpl::setSortByBenefit(bool sortByBenefit) +{ + WRITE_ZONE(); + m_sortByBenefit = sortByBenefit; +} + +void ModuleDestructibleImpl::setMaxChunkDepthOffset(uint32_t offset) +{ + WRITE_ZONE(); + m_maxChunkDepthOffset = offset; +} + +void ModuleDestructibleImpl::setMaxChunkSeparationLOD(float separationLOD) +{ + WRITE_ZONE(); + m_maxChunkSeparationLOD = PxClamp(separationLOD, 0.0f, 1.0f); +} + +void ModuleDestructibleImpl::setValidBoundsPadding(float pad) +{ + WRITE_ZONE(); + m_validBoundsPadding = pad; +} + +void ModuleDestructibleImpl::setChunkReport(UserChunkReport* chunkReport) +{ + WRITE_ZONE(); + m_chunkReport = chunkReport; +} + +void ModuleDestructibleImpl::setImpactDamageReportCallback(UserImpactDamageReport* impactDamageReport) +{ + WRITE_ZONE(); + m_impactDamageReport = impactDamageReport; +} + +void ModuleDestructibleImpl::setChunkReportBitMask(uint32_t chunkReportBitMask) +{ + WRITE_ZONE(); + m_chunkReportBitMask = chunkReportBitMask; +} + +void ModuleDestructibleImpl::setDestructiblePhysXActorReport(UserDestructiblePhysXActorReport* destructiblePhysXActorReport) +{ + WRITE_ZONE(); + m_destructiblePhysXActorReport = destructiblePhysXActorReport; +} + +void ModuleDestructibleImpl::setChunkReportMaxFractureEventDepth(uint32_t chunkReportMaxFractureEventDepth) +{ + WRITE_ZONE(); + m_chunkReportMaxFractureEventDepth = chunkReportMaxFractureEventDepth; +} + +void ModuleDestructibleImpl::scheduleChunkStateEventCallback(DestructibleCallbackSchedule::Enum chunkStateEventCallbackSchedule) +{ + WRITE_ZONE(); + if (chunkStateEventCallbackSchedule >= (DestructibleCallbackSchedule::Enum)0 && chunkStateEventCallbackSchedule < DestructibleCallbackSchedule::Count) + { + m_chunkStateEventCallbackSchedule = chunkStateEventCallbackSchedule; + } +} + +void ModuleDestructibleImpl::setChunkCrumbleReport(UserChunkParticleReport* chunkCrumbleReport) +{ + WRITE_ZONE(); + m_chunkCrumbleReport = chunkCrumbleReport; +} + +void ModuleDestructibleImpl::setChunkDustReport(UserChunkParticleReport* chunkDustReport) +{ + WRITE_ZONE(); + m_chunkDustReport = chunkDustReport; +} + +void ModuleDestructibleImpl::setWorldSupportPhysXScene(Scene& apexScene, PxScene* physxScene) +{ + WRITE_ZONE(); + DestructibleScene* ds = getDestructibleScene(apexScene); + if (ds) + { + ds->setWorldSupportPhysXScene(physxScene); + } +} + +bool ModuleDestructibleImpl::owns(const PxRigidActor* actor) const +{ + READ_ZONE(); + const PhysXObjectDescIntl* desc = static_cast<const PhysXObjectDescIntl*>(mSdk->getPhysXObjectInfo(actor)); + if (desc != NULL) + { + const uint32_t actorCount = desc->mApexActors.size(); + for (uint32_t i = 0; i < actorCount; ++i) + { + const Actor* actor = desc->mApexActors[i]; + if (actor != NULL && actor->getOwner()->getObjTypeID() == DestructibleAssetImpl::mAssetTypeID) + { + return true; + } + } + } + + return false; +} + +#if APEX_RUNTIME_FRACTURE +bool ModuleDestructibleImpl::isRuntimeFractureShape(const PxShape& shape) const +{ + READ_ZONE(); + for (uint32_t i = 0 ; i < m_destructibleSceneList.getSize() ; i++) + { + DestructibleScene* ds = DYNAMIC_CAST(DestructibleScene*)(m_destructibleSceneList.getResource(i)); + nvidia::fracture::SimScene* simScene = ds->getDestructibleRTScene(false); + if (simScene && simScene->owns(shape)) + { + return true; + } + } + return false; +} +#endif + +DestructibleActor* ModuleDestructibleImpl::getDestructibleAndChunk(const PxShape* shape, int32_t* chunkIndex) const +{ + READ_ZONE(); + const PhysXObjectDescIntl* desc = static_cast<const PhysXObjectDescIntl*>(mSdk->getPhysXObjectInfo(shape)); + if (desc != NULL) + { + const uint32_t actorCount = desc->mApexActors.size(); + PX_ASSERT(actorCount == 1); // Shapes should only be associated with one chunk + if (actorCount > 0) + { + const DestructibleActorProxy* actorProxy = (DestructibleActorProxy*)desc->mApexActors[0]; + if (actorProxy->getOwner()->getObjTypeID() == DestructibleAssetImpl::mAssetTypeID) + { + const DestructibleScene* ds = actorProxy->impl.getDestructibleScene(); + DestructibleStructure::Chunk* chunk = (DestructibleStructure::Chunk*)desc->userData; + if (chunk == NULL || chunk->destructibleID == DestructibleStructure::InvalidID || chunk->destructibleID > ds->mDestructibles.capacity()) + { + return NULL; + } + + DestructibleActorImpl* destructible = ds->mDestructibles.direct(chunk->destructibleID); + if (destructible == NULL) + { + return NULL; + } + + if (chunkIndex) + { + *chunkIndex = (int32_t)chunk->indexInAsset; + } + return destructible->getAPI(); + } + } + } + + return NULL; +} + +void ModuleDestructibleImpl::applyRadiusDamage(Scene& scene, float damage, float momentum, const PxVec3& position, float radius, bool falloff) +{ + WRITE_ZONE(); + DestructibleScene* ds = getDestructibleScene(scene); + if (ds) + { + ds->applyRadiusDamage(damage, momentum, position, radius, falloff); + } +} + +void ModuleDestructibleImpl::setMaxActorCreatesPerFrame(uint32_t maxActorsPerFrame) +{ + WRITE_ZONE(); + m_maxActorsCreateablePerFrame = maxActorsPerFrame; +} + +void ModuleDestructibleImpl::setMaxFracturesProcessedPerFrame(uint32_t maxFracturesProcessedPerFrame) +{ + WRITE_ZONE(); + m_maxFracturesProcessedPerFrame = maxFracturesProcessedPerFrame; +} + +#if 0 // dead code +void ModuleDestructible::releaseBufferedConvexMeshes() +{ + for (uint32_t i = 0; i < convexMeshKillList.size(); i++) + { + convexMeshKillList[i]->release(); + } + convexMeshKillList.clear(); +} +#endif + +void ModuleDestructibleImpl::destroy() +{ +#ifndef WITHOUT_APEX_AUTHORING + if (mFractureTools != NULL) + { + PX_DELETE(mFractureTools); + mFractureTools = NULL; + } +#endif + + NvParameterized::Traits* traits = mSdk->getParameterizedTraits(); + + if (mModuleParams != NULL) + { + mModuleParams->destroy(); + mModuleParams = NULL; + } + + if (mApexDestructiblePreviewParams != NULL) + { + mApexDestructiblePreviewParams->destroy(); + mApexDestructiblePreviewParams = NULL; + } + + // base class + ModuleBase::destroy(); + +#if 0 //dead code + releaseBufferedConvexMeshes(); +#endif + + if (traits) + { + ModuleDestructibleRegistration::invokeUnregistration(traits); + } + + delete this; +} + +/*** ModuleDestructibleImpl::SyncParams ***/ +bool ModuleDestructibleImpl::setSyncParams(UserDamageEventHandler * userDamageEventHandler, UserFractureEventHandler * userFractureEventHandler, UserChunkMotionHandler * userChunkMotionHandler) +{ + WRITE_ZONE(); + bool validEntry = false; + validEntry = ((NULL != userChunkMotionHandler) ? (NULL != userDamageEventHandler || NULL != userFractureEventHandler) : true); + if(validEntry) + { + mSyncParams.userDamageEventHandler = userDamageEventHandler; + mSyncParams.userFractureEventHandler = userFractureEventHandler; + mSyncParams.userChunkMotionHandler = userChunkMotionHandler; + } + return validEntry; +} + +typedef ModuleDestructibleImpl::SyncParams SyncParams; + +SyncParams::SyncParams() +:userDamageEventHandler(NULL) +,userFractureEventHandler(NULL) +,userChunkMotionHandler(NULL) +{ +} + +SyncParams::~SyncParams() +{ + userChunkMotionHandler = NULL; + userFractureEventHandler = NULL; + userDamageEventHandler = NULL; +} + +UserDamageEventHandler * SyncParams::getUserDamageEventHandler() const +{ + return userDamageEventHandler; +} + +UserFractureEventHandler * SyncParams::getUserFractureEventHandler() const +{ + return userFractureEventHandler; +} + +UserChunkMotionHandler * SyncParams::getUserChunkMotionHandler() const +{ + return userChunkMotionHandler; +} + +template<typename T> uint32_t SyncParams::getSize() const +{ + return sizeof(T); +} + +template uint32_t SyncParams::getSize<DamageEventHeader> () const; +template uint32_t SyncParams::getSize<DamageEventUnit> () const; +template uint32_t SyncParams::getSize<FractureEventHeader> () const; +template uint32_t SyncParams::getSize<FractureEventUnit> () const; +template uint32_t SyncParams::getSize<ChunkTransformHeader> () const; +template uint32_t SyncParams::getSize<ChunkTransformUnit> () const; + +const SyncParams & ModuleDestructibleImpl::getSyncParams() const +{ + return mSyncParams; +} + +void ModuleDestructibleImpl::setUseLegacyChunkBoundsTesting(bool useLegacyChunkBoundsTesting) +{ + WRITE_ZONE(); + mUseLegacyChunkBoundsTesting = useLegacyChunkBoundsTesting; +} + +void ModuleDestructibleImpl::setUseLegacyDamageRadiusSpread(bool useLegacyDamageRadiusSpread) +{ + WRITE_ZONE(); + mUseLegacyDamageRadiusSpread = useLegacyDamageRadiusSpread; +} + +bool ModuleDestructibleImpl::setMassScaling(float massScale, float scaledMassExponent, Scene& apexScene) +{ + WRITE_ZONE(); + DestructibleScene* dscene = getDestructibleScene(apexScene); + + if (dscene != NULL) + { + return dscene->setMassScaling(massScale, scaledMassExponent); + } + + return false; +} + +void ModuleDestructibleImpl::invalidateBounds(const PxBounds3* bounds, uint32_t boundsCount, Scene& apexScene) +{ + WRITE_ZONE(); + DestructibleScene* dscene = getDestructibleScene(apexScene); + + if (dscene != NULL) + { + dscene->invalidateBounds(bounds, boundsCount); + } +} + +void ModuleDestructibleImpl::setDamageApplicationRaycastFlags(nvidia::DestructibleActorRaycastFlags::Enum flags, Scene& apexScene) +{ + WRITE_ZONE(); + DestructibleScene* dscene = getDestructibleScene(apexScene); + + if (dscene != NULL) + { + dscene->setDamageApplicationRaycastFlags(flags); + } +} + +bool ModuleDestructibleImpl::setRenderLockMode(RenderLockMode::Enum renderLockMode, Scene& apexScene) +{ + WRITE_ZONE(); + DestructibleScene* dscene = getDestructibleScene(apexScene); + + if (dscene != NULL) + { + return dscene->setRenderLockMode(renderLockMode); + } + + return false; +} + +RenderLockMode::Enum ModuleDestructibleImpl::getRenderLockMode(const Scene& apexScene) const +{ + READ_ZONE(); + DestructibleScene* dscene = getDestructibleScene(apexScene); + + if (dscene != NULL) + { + return dscene->getRenderLockMode(); + } + + return RenderLockMode::NO_RENDER_LOCK; +} + +bool ModuleDestructibleImpl::lockModuleSceneRenderLock(Scene& apexScene) +{ + DestructibleScene* dscene = getDestructibleScene(apexScene); + + if (dscene != NULL) + { + return dscene->lockModuleSceneRenderLock(); + } + + return false; +} + +bool ModuleDestructibleImpl::unlockModuleSceneRenderLock(Scene& apexScene) +{ + DestructibleScene* dscene = getDestructibleScene(apexScene); + + if (dscene != NULL) + { + return dscene->unlockModuleSceneRenderLock(); + } + + return false; +} + +bool ModuleDestructibleImpl::setChunkCollisionHullCookingScale(const PxVec3& scale) +{ + WRITE_ZONE(); + if (scale.x <= 0.0f || scale.y <= 0.0f || scale.z <= 0.0f) + { + return false; + } + + mChunkCollisionHullCookingScale = scale; + + return true; +} + + +/******************************* +* DestructibleModuleCachedData * +*******************************/ + +DestructibleModuleCachedData::DestructibleModuleCachedData(AuthObjTypeID moduleID) : + mModuleID(moduleID) +{ +} + +DestructibleModuleCachedData::~DestructibleModuleCachedData() +{ + clear(); +} + +NvParameterized::Interface* DestructibleModuleCachedData::getCachedDataForAssetAtScale(Asset& asset, const PxVec3& scale) +{ + DestructibleAssetImpl& dasset = DYNAMIC_CAST(DestructibleAssetProxy*)(&asset)->impl; + + DestructibleAssetCollision* collisionSet = findAssetCollisionSet(asset.getName()); + if (collisionSet == NULL) + { + collisionSet = PX_NEW(DestructibleAssetCollision); + collisionSet->setDestructibleAssetToCook(&dasset); + mAssetCollisionSets.pushBack(collisionSet); + } + + return collisionSet->getCollisionAtScale(scale); +} + +PxFileBuf& DestructibleModuleCachedData::serialize(PxFileBuf& stream) const +{ + stream << (uint32_t)Version::Current; + + stream << (uint32_t)mModuleID; + + stream << mAssetCollisionSets.size(); + for (uint32_t i = 0; i < mAssetCollisionSets.size(); ++i) + { + mAssetCollisionSets[i]->serialize(stream); + } + + return stream; +} + +PxFileBuf& DestructibleModuleCachedData::deserialize(PxFileBuf& stream) +{ + clear(false); // false => don't delete cached data for referenced sets + + /*const uint32_t version =*/ + stream.readDword(); // Original version + + mModuleID = stream.readDword(); + + const uint32_t dataSetCount = stream.readDword(); + for (uint32_t i = 0; i < dataSetCount; ++i) + { + DestructibleAssetCollision* collisionSet = PX_NEW(DestructibleAssetCollision); + collisionSet->deserialize(stream, NULL); + // See if we already have a set for the asset + DestructibleAssetCollision* destinationSet = NULL; + for (uint32_t j = 0; j < mAssetCollisionSets.size(); ++j) + { + if (!nvidia::stricmp(mAssetCollisionSets[j]->getAssetName(), collisionSet->getAssetName())) + { + destinationSet = mAssetCollisionSets[j]; + break; + } + } + if (destinationSet == NULL) + { + // We don't have a set for this asset. Simply add it. + destinationSet = mAssetCollisionSets.pushBack(collisionSet); + } + else + { + // We already have a set for this asset. Merge. + destinationSet->merge(*collisionSet); + PX_DELETE(collisionSet); + } + destinationSet->cookAll(); // This should only cook what isn't already cooked + } + + return stream; +} + +PxFileBuf& DestructibleModuleCachedData::serializeSingleAsset(Asset& asset, PxFileBuf& stream) +{ + DestructibleAssetCollision* collisionSet = findAssetCollisionSet(asset.getName()); + if( collisionSet ) + { + collisionSet->serialize(stream); + } + + return stream; +} + +PxFileBuf& DestructibleModuleCachedData::deserializeSingleAsset(Asset& asset, PxFileBuf& stream) +{ + DestructibleAssetCollision* collisionSet = findAssetCollisionSet(asset.getName()); + if (collisionSet == NULL) + { + collisionSet = PX_NEW(DestructibleAssetCollision); + mAssetCollisionSets.pushBack(collisionSet); + } + collisionSet->deserialize(stream, asset.getName()); + + return stream; +} + +void DestructibleModuleCachedData::clear(bool force) +{ + if (force) + { + // force == true, so delete everything + for (uint32_t i = mAssetCollisionSets.size(); i--;) + { + DestructibleAssetCollision* collisionSet = mAssetCollisionSets[i]; + if (collisionSet != NULL) + { + // Spit out warnings to the error stream for any referenced sets + collisionSet->reportReferencedSets(); + collisionSet->clearUnreferencedSets(); + } + PX_DELETE(mAssetCollisionSets[i]); + } + mAssetCollisionSets.reset(); + + return; + } + + // If !force, then we have more work to do: + + for (uint32_t i = mAssetCollisionSets.size(); i--;) + { + DestructibleAssetCollision* collisionSet = mAssetCollisionSets[i]; + if (collisionSet != NULL) + { + collisionSet->clearUnreferencedSets(); + } + } +} + +void DestructibleModuleCachedData::clearAssetCollisionSet(const DestructibleAssetImpl& asset) +{ + for (uint32_t i = mAssetCollisionSets.size(); i--;) + { + if (!mAssetCollisionSets[i] || !mAssetCollisionSets[i]->getAssetName() || !nvidia::stricmp(mAssetCollisionSets[i]->getAssetName(), asset.getName())) + { + PX_DELETE(mAssetCollisionSets[i]); + mAssetCollisionSets.replaceWithLast(i); + } + } +} + +physx::Array<PxConvexMesh*>* DestructibleModuleCachedData::getConvexMeshesForActor(const DestructibleActorImpl& destructible) +{ + const DestructibleAssetImpl* asset = destructible.getDestructibleAsset(); + if (asset == NULL) + { + return NULL; + } + + DestructibleAssetCollision* collisionSet = getAssetCollisionSet(*asset); + if (collisionSet == NULL) + { + return NULL; + } + + physx::Array<PxConvexMesh*>* convexMeshes = collisionSet->getConvexMeshesAtScale(destructible.getScale()); + + const int scaleIndex = collisionSet->getScaleIndex(destructible.getScale(), kDefaultDestructibleAssetCollisionScaleTolerance); + collisionSet->incReferenceCount(scaleIndex); + + return convexMeshes; +} + +void DestructibleModuleCachedData::releaseReferencesToConvexMeshesForActor(const DestructibleActorImpl& destructible) +{ + const DestructibleAssetImpl* asset = destructible.getDestructibleAsset(); + if (asset == NULL) + { + return; + } + + DestructibleAssetCollision* collisionSet = getAssetCollisionSet(*asset); + if (collisionSet == NULL) + { + return; + } + + const int scaleIndex = collisionSet->getScaleIndex(destructible.getScale(), kDefaultDestructibleAssetCollisionScaleTolerance); + collisionSet->decReferenceCount(scaleIndex); +} + +physx::Array<PxConvexMesh*>* DestructibleModuleCachedData::getConvexMeshesForScale(const DestructibleAssetImpl& asset, const PxVec3& scale, bool incRef) +{ + DestructibleAssetCollision* collisionSet = getAssetCollisionSet(asset); + if (collisionSet == NULL) + { + return NULL; + } + + physx::Array<PxConvexMesh*>* convexMeshes = collisionSet->getConvexMeshesAtScale(scale); + + // The DestructibleActor::cacheModuleData() method needs to avoid incrementing the ref count + if (incRef) + { + const int scaleIndex = collisionSet->getScaleIndex(scale, kDefaultDestructibleAssetCollisionScaleTolerance); + collisionSet->incReferenceCount(scaleIndex); + } + + return convexMeshes; +} + +DestructibleAssetCollision* DestructibleModuleCachedData::getAssetCollisionSet(const DestructibleAssetImpl& asset) +{ + DestructibleAssetCollision* collisionSet = findAssetCollisionSet(asset.getName()); + + if (collisionSet == NULL) + { + collisionSet = PX_NEW(DestructibleAssetCollision); + mAssetCollisionSets.pushBack(collisionSet); + } + collisionSet->setDestructibleAssetToCook(const_cast<DestructibleAssetImpl*>(&asset)); + + return collisionSet; +} + +DestructibleAssetCollision* DestructibleModuleCachedData::findAssetCollisionSet(const char* name) +{ + for (uint32_t i = 0; i < mAssetCollisionSets.size(); ++i) + { + if (mAssetCollisionSets[i] && mAssetCollisionSets[i]->getAssetName() && !nvidia::stricmp(mAssetCollisionSets[i]->getAssetName(), name)) + { + return mAssetCollisionSets[i]; + } + } + + return NULL; +} + +} +} // end namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/CachedOverlaps.cpp b/APEX_1.4/module/destructible/src/autogen/CachedOverlaps.cpp new file mode 100644 index 00000000..3ce2e737 --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/CachedOverlaps.cpp @@ -0,0 +1,429 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "CachedOverlaps.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace CachedOverlapsNS; + +const char* const CachedOverlapsFactory::vptr = + NvParameterized::getVptr<CachedOverlaps, CachedOverlaps::ClassAlignment>(); + +const uint32_t NumParamDefs = 6; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, 3, 4, 5, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 2 }, + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->isCached), NULL, 0 }, // isCached + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->overlaps), CHILDREN(2), 1 }, // overlaps + { TYPE_STRUCT, false, 1 * sizeof(IntPair_Type), CHILDREN(3), 2 }, // overlaps[] + { TYPE_I32, false, (size_t)(&((IntPair_Type*)0)->i0), NULL, 0 }, // overlaps[].i0 + { TYPE_I32, false, (size_t)(&((IntPair_Type*)0)->i1), NULL, 0 }, // overlaps[].i1 +}; + + +bool CachedOverlaps::mBuiltFlag = false; +NvParameterized::MutexType CachedOverlaps::mBuiltFlagMutex; + +CachedOverlaps::CachedOverlaps(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &CachedOverlapsFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +CachedOverlaps::~CachedOverlaps() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void CachedOverlaps::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~CachedOverlaps(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* CachedOverlaps::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* CachedOverlaps::getParameterDefinitionTree(void) const +{ + CachedOverlaps* tmpParam = const_cast<CachedOverlaps*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType CachedOverlaps::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType CachedOverlaps::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void CachedOverlaps::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<CachedOverlaps::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ + +void CachedOverlaps::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void CachedOverlaps::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="isCached" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("isCached", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not chunk overlaps are cached at a particular hierarchy depth. In this\n case, overlap really means adjacency.", true); + HintTable[1].init("shortDescription", "Whether or not chunk overlaps are cached at a particular hierarchy depth", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="overlaps" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("overlaps", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The overlaps at a particular hierarchy depth. This is the set of adjacencies,\n stored as pairs of chunk indices, for chunks at a the given hierarchy depth.", true); + HintTable[1].init("shortDescription", "The overlaps at a particular hierarchy depth", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="overlaps[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("overlaps", TYPE_STRUCT, "IntPair", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The overlaps at a particular hierarchy depth. This is the set of adjacencies,\n stored as pairs of chunk indices, for chunks at a the given hierarchy depth.", true); + HintTable[1].init("shortDescription", "The overlaps at a particular hierarchy depth", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="overlaps[].i0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("i0", TYPE_I32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "First element", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="overlaps[].i1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("i1", TYPE_I32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Second element", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[2]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(2); + + ParamDefTable[0].setChildren(Children, 2); + } + + // SetChildren for: nodeIndex=2, longName="overlaps" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(3); + + ParamDefTable[2].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=3, longName="overlaps[]" + { + static Definition* Children[2]; + Children[0] = PDEF_PTR(4); + Children[1] = PDEF_PTR(5); + + ParamDefTable[3].setChildren(Children, 2); + } + + mBuiltFlag = true; + +} +void CachedOverlaps::initStrings(void) +{ +} + +void CachedOverlaps::initDynamicArrays(void) +{ + overlaps.buf = NULL; + overlaps.isAllocated = true; + overlaps.elementSize = sizeof(IntPair_Type); + overlaps.arraySizes[0] = 0; +} + +void CachedOverlaps::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + isCached = bool(false); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void CachedOverlaps::initReferences(void) +{ +} + +void CachedOverlaps::freeDynamicArrays(void) +{ + if (overlaps.isAllocated && overlaps.buf) + { + mParameterizedTraits->free(overlaps.buf); + } +} + +void CachedOverlaps::freeStrings(void) +{ +} + +void CachedOverlaps::freeReferences(void) +{ +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/DestructibleActorChunks.cpp b/APEX_1.4/module/destructible/src/autogen/DestructibleActorChunks.cpp new file mode 100644 index 00000000..ca557972 --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/DestructibleActorChunks.cpp @@ -0,0 +1,642 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "DestructibleActorChunks.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace DestructibleActorChunksNS; + +const char* const DestructibleActorChunksFactory::vptr = + NvParameterized::getVptr<DestructibleActorChunks, DestructibleActorChunks::ClassAlignment>(); + +const uint32_t NumParamDefs = 14; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 1 }, + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->data), CHILDREN(1), 1 }, // data + { TYPE_STRUCT, false, 1 * sizeof(Chunk_Type), CHILDREN(2), 11 }, // data[] + { TYPE_U8, false, (size_t)(&((Chunk_Type*)0)->state), NULL, 0 }, // data[].state + { TYPE_U8, false, (size_t)(&((Chunk_Type*)0)->flags), NULL, 0 }, // data[].flags + { TYPE_U32, false, (size_t)(&((Chunk_Type*)0)->islandID), NULL, 0 }, // data[].islandID + { TYPE_F32, false, (size_t)(&((Chunk_Type*)0)->damage), NULL, 0 }, // data[].damage + { TYPE_VEC4, false, (size_t)(&((Chunk_Type*)0)->localSphere), NULL, 0 }, // data[].localSphere + { TYPE_VEC3, false, (size_t)(&((Chunk_Type*)0)->localOffset), NULL, 0 }, // data[].localOffset + { TYPE_I32, false, (size_t)(&((Chunk_Type*)0)->visibleAncestorIndex), NULL, 0 }, // data[].visibleAncestorIndex + { TYPE_U32, false, (size_t)(&((Chunk_Type*)0)->shapesCount), NULL, 0 }, // data[].shapesCount + { TYPE_TRANSFORM, false, (size_t)(&((Chunk_Type*)0)->globalPose), NULL, 0 }, // data[].globalPose + { TYPE_VEC3, false, (size_t)(&((Chunk_Type*)0)->linearVelocity), NULL, 0 }, // data[].linearVelocity + { TYPE_VEC3, false, (size_t)(&((Chunk_Type*)0)->angularVelocity), NULL, 0 }, // data[].angularVelocity +}; + + +bool DestructibleActorChunks::mBuiltFlag = false; +NvParameterized::MutexType DestructibleActorChunks::mBuiltFlagMutex; + +DestructibleActorChunks::DestructibleActorChunks(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &DestructibleActorChunksFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +DestructibleActorChunks::~DestructibleActorChunks() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void DestructibleActorChunks::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~DestructibleActorChunks(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* DestructibleActorChunks::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* DestructibleActorChunks::getParameterDefinitionTree(void) const +{ + DestructibleActorChunks* tmpParam = const_cast<DestructibleActorChunks*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType DestructibleActorChunks::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType DestructibleActorChunks::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void DestructibleActorChunks::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<DestructibleActorChunks::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ + +void DestructibleActorChunks::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void DestructibleActorChunks::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="data" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("data", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The actor's chunk data.", true); + HintTable[2].init("shortDescription", "The actor's chunk data", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="data[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("data", TYPE_STRUCT, "Chunk", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The actor's chunk data.", true); + HintTable[2].init("shortDescription", "The actor's chunk data", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="data[].state" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("state", TYPE_U8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Bit flags indicating the state of the chunk.", true); + HintTable[1].init("shortDescription", "Bit flags indicating the state of the chunk", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="data[].flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("flags", TYPE_U8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Overall chunk flags.", true); + HintTable[1].init("shortDescription", "Overall chunk flags", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="data[].islandID" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("islandID", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Island ID (if any) to which the chunk is attached.", true); + HintTable[1].init("shortDescription", "Island ID (if any) to which the chunk is attached", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=6, longName="data[].damage" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6]; + ParamDef->init("damage", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How damaged the chunk is.", true); + HintTable[1].init("shortDescription", "How damaged the chunk is", true); + ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=7, longName="data[].localSphere" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7]; + ParamDef->init("localSphere", TYPE_VEC4, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A local bounding sphere for the chunk.", true); + HintTable[1].init("shortDescription", "A local bounding sphere for the chunk", true); + ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=8, longName="data[].localOffset" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8]; + ParamDef->init("localOffset", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A local bounding sphere for the chunk.", true); + HintTable[1].init("shortDescription", "A local bounding sphere for the chunk", true); + ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=9, longName="data[].visibleAncestorIndex" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9]; + ParamDef->init("visibleAncestorIndex", TYPE_I32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Index (in structure) of this chunks' visible ancestor, if any. If none exists, it's InvalidChunkIndex.", true); + HintTable[1].init("shortDescription", "Index (in structure) of this chunks' visible ancestor, if any", true); + ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=10, longName="data[].shapesCount" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10]; + ParamDef->init("shapesCount", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of shapes for this chunk.", true); + HintTable[1].init("shortDescription", "Number of shapes for this chunk", true); + ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=11, longName="data[].globalPose" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11]; + ParamDef->init("globalPose", TYPE_TRANSFORM, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk global transform.", true); + HintTable[1].init("shortDescription", "Chunk global transform", true); + ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=12, longName="data[].linearVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12]; + ParamDef->init("linearVelocity", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk linear velocity.", true); + HintTable[1].init("shortDescription", "Chunk linear velocity", true); + ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=13, longName="data[].angularVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13]; + ParamDef->init("angularVelocity", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk angular velocity.", true); + HintTable[1].init("shortDescription", "Chunk angular velocity", true); + ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(1); + + ParamDefTable[0].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=1, longName="data" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(2); + + ParamDefTable[1].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=2, longName="data[]" + { + static Definition* Children[11]; + Children[0] = PDEF_PTR(3); + Children[1] = PDEF_PTR(4); + Children[2] = PDEF_PTR(5); + Children[3] = PDEF_PTR(6); + Children[4] = PDEF_PTR(7); + Children[5] = PDEF_PTR(8); + Children[6] = PDEF_PTR(9); + Children[7] = PDEF_PTR(10); + Children[8] = PDEF_PTR(11); + Children[9] = PDEF_PTR(12); + Children[10] = PDEF_PTR(13); + + ParamDefTable[2].setChildren(Children, 11); + } + + mBuiltFlag = true; + +} +void DestructibleActorChunks::initStrings(void) +{ +} + +void DestructibleActorChunks::initDynamicArrays(void) +{ + data.buf = NULL; + data.isAllocated = true; + data.elementSize = sizeof(Chunk_Type); + data.arraySizes[0] = 0; +} + +void DestructibleActorChunks::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void DestructibleActorChunks::initReferences(void) +{ +} + +void DestructibleActorChunks::freeDynamicArrays(void) +{ + if (data.isAllocated && data.buf) + { + mParameterizedTraits->free(data.buf); + } +} + +void DestructibleActorChunks::freeStrings(void) +{ +} + +void DestructibleActorChunks::freeReferences(void) +{ +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/DestructibleActorParam.cpp b/APEX_1.4/module/destructible/src/autogen/DestructibleActorParam.cpp new file mode 100644 index 00000000..2036ba2b --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/DestructibleActorParam.cpp @@ -0,0 +1,8244 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "DestructibleActorParam.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace DestructibleActorParamNS; + +const char* const DestructibleActorParamFactory::vptr = + NvParameterized::getVptr<DestructibleActorParam, DestructibleActorParam::ClassAlignment>(); + +const uint32_t NumParamDefs = 294; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 23, 24, 85, + 96, 130, 159, 176, 199, 225, 239, 243, 267, 292, 293, 19, 21, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 47, 48, 49, 50, 56, 81, 82, 83, 84, 40, 41, + 42, 43, 44, 45, 46, 51, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 69, 74, 64, 65, + 66, 67, 68, 70, 71, 72, 73, 75, 76, 77, 78, 79, 80, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 97, 118, 119, 125, 126, 127, 128, 129, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 120, 121, 122, 123, 124, + 131, 139, 140, 141, 142, 155, 156, 157, 158, 132, 133, 134, 135, 136, 137, 138, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 160, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 161, 162, 163, 164, 177, 184, 189, 194, 195, 196, 197, + 198, 178, 179, 180, 181, 182, 183, 185, 186, 187, 188, 190, 191, 192, 193, 200, 204, + 205, 206, 207, 223, 224, 201, 202, 203, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 226, 227, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 228, 229, 240, 241, 242, 244, 245, 246, 247, 251, 255, 256, 257, 258, 259, 260, 266, + 248, 249, 250, 252, 253, 254, 261, 262, 263, 264, 265, 268, 269, 270, 271, 272, 276, + 280, 281, 282, 283, 284, 285, 291, 273, 274, 275, 277, 278, 279, 286, 287, 288, 289, + 290, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 34 }, + { TYPE_STRING, false, (size_t)(&((ParametersStruct*)0)->crumbleEmitterName), NULL, 0 }, // crumbleEmitterName + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->crumbleParticleSpacing), NULL, 0 }, // crumbleParticleSpacing + { TYPE_STRING, false, (size_t)(&((ParametersStruct*)0)->dustEmitterName), NULL, 0 }, // dustEmitterName + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->dustParticleSpacing), NULL, 0 }, // dustParticleSpacing + { TYPE_TRANSFORM, false, (size_t)(&((ParametersStruct*)0)->globalPose), NULL, 0 }, // globalPose + { TYPE_VEC3, false, (size_t)(&((ParametersStruct*)0)->scale), NULL, 0 }, // scale + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->dynamic), NULL, 0 }, // dynamic + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->supportDepth), NULL, 0 }, // supportDepth + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->formExtendedStructures), NULL, 0 }, // formExtendedStructures + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->performDetailedOverlapTestForExtendedStructures), NULL, 0 }, // performDetailedOverlapTestForExtendedStructures + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->keepPreviousFrameBoneBuffer), NULL, 0 }, // keepPreviousFrameBoneBuffer + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->doNotCreateRenderable), NULL, 0 }, // doNotCreateRenderable + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->useAssetDefinedSupport), NULL, 0 }, // useAssetDefinedSupport + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->useWorldSupport), NULL, 0 }, // useWorldSupport + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->renderStaticChunksSeparately), NULL, 0 }, // renderStaticChunksSeparately + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->keepVisibleBonesPacked), NULL, 0 }, // keepVisibleBonesPacked + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->createChunkEvents), NULL, 0 }, // createChunkEvents + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->overrideSkinnedMaterialNames), CHILDREN(34), 1 }, // overrideSkinnedMaterialNames + { TYPE_STRING, false, 1 * sizeof(NvParameterized::DummyStringStruct), NULL, 0 }, // overrideSkinnedMaterialNames[] + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->overrideStaticMaterialNames), CHILDREN(35), 1 }, // overrideStaticMaterialNames + { TYPE_STRING, false, 1 * sizeof(NvParameterized::DummyStringStruct), NULL, 0 }, // overrideStaticMaterialNames[] + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->sleepVelocityFrameDecayConstant), NULL, 0 }, // sleepVelocityFrameDecayConstant + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->useHardSleeping), NULL, 0 }, // useHardSleeping + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->destructibleParameters), CHILDREN(36), 24 }, // destructibleParameters + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->damageCap), NULL, 0 }, // destructibleParameters.damageCap + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->forceToDamage), NULL, 0 }, // destructibleParameters.forceToDamage + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->impactVelocityThreshold), NULL, 0 }, // destructibleParameters.impactVelocityThreshold + { TYPE_U32, false, (size_t)(&((DestructibleParameters_Type*)0)->minimumFractureDepth), NULL, 0 }, // destructibleParameters.minimumFractureDepth + { TYPE_I32, false, (size_t)(&((DestructibleParameters_Type*)0)->impactDamageDefaultDepth), NULL, 0 }, // destructibleParameters.impactDamageDefaultDepth + { TYPE_I32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisDepth), NULL, 0 }, // destructibleParameters.debrisDepth + { TYPE_U32, false, (size_t)(&((DestructibleParameters_Type*)0)->essentialDepth), NULL, 0 }, // destructibleParameters.essentialDepth + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisLifetimeMin), NULL, 0 }, // destructibleParameters.debrisLifetimeMin + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisLifetimeMax), NULL, 0 }, // destructibleParameters.debrisLifetimeMax + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisMaxSeparationMin), NULL, 0 }, // destructibleParameters.debrisMaxSeparationMin + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisMaxSeparationMax), NULL, 0 }, // destructibleParameters.debrisMaxSeparationMax + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisDestructionProbability), NULL, 0 }, // destructibleParameters.debrisDestructionProbability + { TYPE_BOUNDS3, false, (size_t)(&((DestructibleParameters_Type*)0)->validBounds), NULL, 0 }, // destructibleParameters.validBounds + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->maxChunkSpeed), NULL, 0 }, // destructibleParameters.maxChunkSpeed + { TYPE_STRUCT, false, (size_t)(&((DestructibleParameters_Type*)0)->flags), CHILDREN(60), 7 }, // destructibleParameters.flags + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->ACCUMULATE_DAMAGE), NULL, 0 }, // destructibleParameters.flags.ACCUMULATE_DAMAGE + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->DEBRIS_TIMEOUT), NULL, 0 }, // destructibleParameters.flags.DEBRIS_TIMEOUT + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->DEBRIS_MAX_SEPARATION), NULL, 0 }, // destructibleParameters.flags.DEBRIS_MAX_SEPARATION + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->CRUMBLE_SMALLEST_CHUNKS), NULL, 0 }, // destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->ACCURATE_RAYCASTS), NULL, 0 }, // destructibleParameters.flags.ACCURATE_RAYCASTS + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->USE_VALID_BOUNDS), NULL, 0 }, // destructibleParameters.flags.USE_VALID_BOUNDS + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->CRUMBLE_VIA_RUNTIME_FRACTURE), NULL, 0 }, // destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->fractureImpulseScale), NULL, 0 }, // destructibleParameters.fractureImpulseScale + { TYPE_U16, false, (size_t)(&((DestructibleParameters_Type*)0)->damageDepthLimit), NULL, 0 }, // destructibleParameters.damageDepthLimit + { TYPE_U16, false, (size_t)(&((DestructibleParameters_Type*)0)->dynamicChunkDominanceGroup), NULL, 0 }, // destructibleParameters.dynamicChunkDominanceGroup + { TYPE_STRUCT, false, (size_t)(&((DestructibleParameters_Type*)0)->dynamicChunksGroupsMask), CHILDREN(67), 5 }, // destructibleParameters.dynamicChunksGroupsMask + { TYPE_BOOL, false, (size_t)(&((GroupsMask_Type*)0)->useGroupsMask), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.useGroupsMask + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits0), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits0 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits1), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits1 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits2), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits2 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits3), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits3 + { TYPE_STRUCT, false, (size_t)(&((DestructibleParameters_Type*)0)->runtimeFracture), CHILDREN(72), 9 }, // destructibleParameters.runtimeFracture + { TYPE_ENUM, false, (size_t)(&((RuntimeFracture_Type*)0)->RuntimeFractureType), NULL, 0 }, // destructibleParameters.runtimeFracture.RuntimeFractureType + { TYPE_BOOL, false, (size_t)(&((RuntimeFracture_Type*)0)->sheetFracture), NULL, 0 }, // destructibleParameters.runtimeFracture.sheetFracture + { TYPE_U32, false, (size_t)(&((RuntimeFracture_Type*)0)->depthLimit), NULL, 0 }, // destructibleParameters.runtimeFracture.depthLimit + { TYPE_BOOL, false, (size_t)(&((RuntimeFracture_Type*)0)->destroyIfAtDepthLimit), NULL, 0 }, // destructibleParameters.runtimeFracture.destroyIfAtDepthLimit + { TYPE_F32, false, (size_t)(&((RuntimeFracture_Type*)0)->minConvexSize), NULL, 0 }, // destructibleParameters.runtimeFracture.minConvexSize + { TYPE_F32, false, (size_t)(&((RuntimeFracture_Type*)0)->impulseScale), NULL, 0 }, // destructibleParameters.runtimeFracture.impulseScale + { TYPE_STRUCT, false, (size_t)(&((RuntimeFracture_Type*)0)->glass), CHILDREN(81), 5 }, // destructibleParameters.runtimeFracture.glass + { TYPE_U32, false, (size_t)(&((FractureGlass_Type*)0)->numSectors), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.numSectors + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->sectorRand), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.sectorRand + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->firstSegmentSize), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.firstSegmentSize + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->segmentScale), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.segmentScale + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->segmentRand), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.segmentRand + { TYPE_STRUCT, false, (size_t)(&((RuntimeFracture_Type*)0)->voronoi), CHILDREN(86), 4 }, // destructibleParameters.runtimeFracture.voronoi + { TYPE_VEC3, false, (size_t)(&((FractureVoronoi_Type*)0)->dimensions), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.dimensions + { TYPE_U32, false, (size_t)(&((FractureVoronoi_Type*)0)->numCells), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.numCells + { TYPE_F32, false, (size_t)(&((FractureVoronoi_Type*)0)->biasExp), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.biasExp + { TYPE_F32, false, (size_t)(&((FractureVoronoi_Type*)0)->maxDist), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.maxDist + { TYPE_STRUCT, false, (size_t)(&((RuntimeFracture_Type*)0)->attachment), CHILDREN(90), 6 }, // destructibleParameters.runtimeFracture.attachment + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->posX), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.posX + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->negX), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.negX + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->posY), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.posY + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->negY), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.negY + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->posZ), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.posZ + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->negZ), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.negZ + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->supportStrength), NULL, 0 }, // destructibleParameters.supportStrength + { TYPE_I8, false, (size_t)(&((DestructibleParameters_Type*)0)->legacyChunkBoundsTestSetting), NULL, 0 }, // destructibleParameters.legacyChunkBoundsTestSetting + { TYPE_I8, false, (size_t)(&((DestructibleParameters_Type*)0)->legacyDamageRadiusSpreadSetting), NULL, 0 }, // destructibleParameters.legacyDamageRadiusSpreadSetting + { TYPE_BOOL, false, (size_t)(&((DestructibleParameters_Type*)0)->alwaysDrawScatterMesh), NULL, 0 }, // destructibleParameters.alwaysDrawScatterMesh + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->depthParameters), CHILDREN(96), 1 }, // depthParameters + { TYPE_STRUCT, false, 1 * sizeof(DestructibleDepthParameters_Type), CHILDREN(97), 9 }, // depthParameters[] + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->OVERRIDE_IMPACT_DAMAGE), NULL, 0 }, // depthParameters[].OVERRIDE_IMPACT_DAMAGE + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->OVERRIDE_IMPACT_DAMAGE_VALUE), NULL, 0 }, // depthParameters[].OVERRIDE_IMPACT_DAMAGE_VALUE + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->IGNORE_POSE_UPDATES), NULL, 0 }, // depthParameters[].IGNORE_POSE_UPDATES + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->IGNORE_RAYCAST_CALLBACKS), NULL, 0 }, // depthParameters[].IGNORE_RAYCAST_CALLBACKS + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->IGNORE_CONTACT_CALLBACKS), NULL, 0 }, // depthParameters[].IGNORE_CONTACT_CALLBACKS + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->USER_FLAG_0), NULL, 0 }, // depthParameters[].USER_FLAG_0 + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->USER_FLAG_1), NULL, 0 }, // depthParameters[].USER_FLAG_1 + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->USER_FLAG_2), NULL, 0 }, // depthParameters[].USER_FLAG_2 + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->USER_FLAG_3), NULL, 0 }, // depthParameters[].USER_FLAG_3 + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->shapeDescTemplate), CHILDREN(106), 8 }, // shapeDescTemplate + { TYPE_STRUCT, false, (size_t)(&((ShapeDescTemplate_Type*)0)->flags), CHILDREN(114), 20 }, // shapeDescTemplate.flags + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_TRIGGER_ON_ENTER), NULL, 0 }, // shapeDescTemplate.flags.NX_TRIGGER_ON_ENTER + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_TRIGGER_ON_LEAVE), NULL, 0 }, // shapeDescTemplate.flags.NX_TRIGGER_ON_LEAVE + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_TRIGGER_ON_STAY), NULL, 0 }, // shapeDescTemplate.flags.NX_TRIGGER_ON_STAY + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_VISUALIZATION), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_VISUALIZATION + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_DISABLE_COLLISION), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_DISABLE_COLLISION + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_FEATURE_INDICES), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_FEATURE_INDICES + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_DISABLE_RAYCASTING), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_DISABLE_RAYCASTING + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_POINT_CONTACT_FORCE), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_POINT_CONTACT_FORCE + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_FLUID_DRAIN), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_FLUID_DRAIN + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_FLUID_DISABLE_COLLISION), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_FLUID_DISABLE_COLLISION + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_FLUID_TWOWAY), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_FLUID_TWOWAY + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_DISABLE_RESPONSE), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_DISABLE_RESPONSE + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_DYNAMIC_DYNAMIC_CCD), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_DYNAMIC_DYNAMIC_CCD + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_DISABLE_SCENE_QUERIES), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_DISABLE_SCENE_QUERIES + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_CLOTH_DRAIN), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_CLOTH_DRAIN + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_CLOTH_DISABLE_COLLISION), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_CLOTH_DISABLE_COLLISION + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_CLOTH_TWOWAY), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_CLOTH_TWOWAY + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_SOFTBODY_DRAIN), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_SOFTBODY_DRAIN + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_SOFTBODY_DISABLE_COLLISION), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_SOFTBODY_DISABLE_COLLISION + { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_SOFTBODY_TWOWAY), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_SOFTBODY_TWOWAY + { TYPE_U16, false, (size_t)(&((ShapeDescTemplate_Type*)0)->collisionGroup), NULL, 0 }, // shapeDescTemplate.collisionGroup + { TYPE_STRUCT, false, (size_t)(&((ShapeDescTemplate_Type*)0)->groupsMask), CHILDREN(134), 5 }, // shapeDescTemplate.groupsMask + { TYPE_BOOL, false, (size_t)(&((GroupsMask_Type*)0)->useGroupsMask), NULL, 0 }, // shapeDescTemplate.groupsMask.useGroupsMask + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits0), NULL, 0 }, // shapeDescTemplate.groupsMask.bits0 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits1), NULL, 0 }, // shapeDescTemplate.groupsMask.bits1 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits2), NULL, 0 }, // shapeDescTemplate.groupsMask.bits2 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits3), NULL, 0 }, // shapeDescTemplate.groupsMask.bits3 + { TYPE_U16, false, (size_t)(&((ShapeDescTemplate_Type*)0)->materialIndex), NULL, 0 }, // shapeDescTemplate.materialIndex + { TYPE_F32, false, (size_t)(&((ShapeDescTemplate_Type*)0)->density), NULL, 0 }, // shapeDescTemplate.density + { TYPE_F32, false, (size_t)(&((ShapeDescTemplate_Type*)0)->skinWidth), NULL, 0 }, // shapeDescTemplate.skinWidth + { TYPE_U64, false, (size_t)(&((ShapeDescTemplate_Type*)0)->userData), NULL, 0 }, // shapeDescTemplate.userData + { TYPE_U64, false, (size_t)(&((ShapeDescTemplate_Type*)0)->name), NULL, 0 }, // shapeDescTemplate.name + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->actorDescTemplate), CHILDREN(139), 9 }, // actorDescTemplate + { TYPE_STRUCT, false, (size_t)(&((ActorDescTemplate_Type*)0)->flags), CHILDREN(148), 7 }, // actorDescTemplate.flags + { TYPE_BOOL, false, (size_t)(&((ActorDescFlags_Type*)0)->NX_AF_DISABLE_COLLISION), NULL, 0 }, // actorDescTemplate.flags.NX_AF_DISABLE_COLLISION + { TYPE_BOOL, false, (size_t)(&((ActorDescFlags_Type*)0)->NX_AF_DISABLE_RESPONSE), NULL, 0 }, // actorDescTemplate.flags.NX_AF_DISABLE_RESPONSE + { TYPE_BOOL, false, (size_t)(&((ActorDescFlags_Type*)0)->NX_AF_LOCK_COM), NULL, 0 }, // actorDescTemplate.flags.NX_AF_LOCK_COM + { TYPE_BOOL, false, (size_t)(&((ActorDescFlags_Type*)0)->NX_AF_FLUID_DISABLE_COLLISION), NULL, 0 }, // actorDescTemplate.flags.NX_AF_FLUID_DISABLE_COLLISION + { TYPE_BOOL, false, (size_t)(&((ActorDescFlags_Type*)0)->NX_AF_CONTACT_MODIFICATION), NULL, 0 }, // actorDescTemplate.flags.NX_AF_CONTACT_MODIFICATION + { TYPE_BOOL, false, (size_t)(&((ActorDescFlags_Type*)0)->NX_AF_FORCE_CONE_FRICTION), NULL, 0 }, // actorDescTemplate.flags.NX_AF_FORCE_CONE_FRICTION + { TYPE_BOOL, false, (size_t)(&((ActorDescFlags_Type*)0)->NX_AF_USER_ACTOR_PAIR_FILTERING), NULL, 0 }, // actorDescTemplate.flags.NX_AF_USER_ACTOR_PAIR_FILTERING + { TYPE_F32, false, (size_t)(&((ActorDescTemplate_Type*)0)->density), NULL, 0 }, // actorDescTemplate.density + { TYPE_U16, false, (size_t)(&((ActorDescTemplate_Type*)0)->actorCollisionGroup), NULL, 0 }, // actorDescTemplate.actorCollisionGroup + { TYPE_U16, false, (size_t)(&((ActorDescTemplate_Type*)0)->dominanceGroup), NULL, 0 }, // actorDescTemplate.dominanceGroup + { TYPE_STRUCT, false, (size_t)(&((ActorDescTemplate_Type*)0)->contactReportFlags), CHILDREN(155), 12 }, // actorDescTemplate.contactReportFlags + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_IGNORE_PAIR), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_IGNORE_PAIR + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_ON_START_TOUCH), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_START_TOUCH + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_ON_END_TOUCH), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_END_TOUCH + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_ON_TOUCH), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_TOUCH + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_ON_IMPACT), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_IMPACT + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_ON_ROLL), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_ROLL + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_ON_SLIDE), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_SLIDE + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_FORCES), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_FORCES + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_ON_END_TOUCH_FORCE_THRESHOLD), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_END_TOUCH_FORCE_THRESHOLD + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_ON_TOUCH_FORCE_THRESHOLD), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_TOUCH_FORCE_THRESHOLD + { TYPE_BOOL, false, (size_t)(&((ContactPairFlag_Type*)0)->NX_NOTIFY_CONTACT_MODIFICATION), NULL, 0 }, // actorDescTemplate.contactReportFlags.NX_NOTIFY_CONTACT_MODIFICATION + { TYPE_U16, false, (size_t)(&((ActorDescTemplate_Type*)0)->forceFieldMaterial), NULL, 0 }, // actorDescTemplate.forceFieldMaterial + { TYPE_U64, false, (size_t)(&((ActorDescTemplate_Type*)0)->userData), NULL, 0 }, // actorDescTemplate.userData + { TYPE_U64, false, (size_t)(&((ActorDescTemplate_Type*)0)->name), NULL, 0 }, // actorDescTemplate.name + { TYPE_U64, false, (size_t)(&((ActorDescTemplate_Type*)0)->compartment), NULL, 0 }, // actorDescTemplate.compartment + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->bodyDescTemplate), CHILDREN(167), 12 }, // bodyDescTemplate + { TYPE_STRUCT, false, (size_t)(&((BodyDescTemplate_Type*)0)->flags), CHILDREN(179), 4 }, // bodyDescTemplate.flags + { TYPE_BOOL, false, (size_t)(&((BodyDescFlags_Type*)0)->NX_BF_DISABLE_GRAVITY), NULL, 0 }, // bodyDescTemplate.flags.NX_BF_DISABLE_GRAVITY + { TYPE_BOOL, false, (size_t)(&((BodyDescFlags_Type*)0)->NX_BF_FILTER_SLEEP_VEL), NULL, 0 }, // bodyDescTemplate.flags.NX_BF_FILTER_SLEEP_VEL + { TYPE_BOOL, false, (size_t)(&((BodyDescFlags_Type*)0)->NX_BF_ENERGY_SLEEP_TEST), NULL, 0 }, // bodyDescTemplate.flags.NX_BF_ENERGY_SLEEP_TEST + { TYPE_BOOL, false, (size_t)(&((BodyDescFlags_Type*)0)->NX_BF_VISUALIZATION), NULL, 0 }, // bodyDescTemplate.flags.NX_BF_VISUALIZATION + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->wakeUpCounter), NULL, 0 }, // bodyDescTemplate.wakeUpCounter + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->linearDamping), NULL, 0 }, // bodyDescTemplate.linearDamping + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->angularDamping), NULL, 0 }, // bodyDescTemplate.angularDamping + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->maxAngularVelocity), NULL, 0 }, // bodyDescTemplate.maxAngularVelocity + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->CCDMotionThreshold), NULL, 0 }, // bodyDescTemplate.CCDMotionThreshold + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->sleepLinearVelocity), NULL, 0 }, // bodyDescTemplate.sleepLinearVelocity + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->sleepAngularVelocity), NULL, 0 }, // bodyDescTemplate.sleepAngularVelocity + { TYPE_U32, false, (size_t)(&((BodyDescTemplate_Type*)0)->solverIterationCount), NULL, 0 }, // bodyDescTemplate.solverIterationCount + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->sleepEnergyThreshold), NULL, 0 }, // bodyDescTemplate.sleepEnergyThreshold + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->sleepDamping), NULL, 0 }, // bodyDescTemplate.sleepDamping + { TYPE_F32, false, (size_t)(&((BodyDescTemplate_Type*)0)->contactReportThreshold), NULL, 0 }, // bodyDescTemplate.contactReportThreshold + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->p3ShapeDescTemplate), CHILDREN(183), 8 }, // p3ShapeDescTemplate + { TYPE_STRUCT, false, (size_t)(&((P3ShapeDescTemplate_Type*)0)->flags), CHILDREN(191), 6 }, // p3ShapeDescTemplate.flags + { TYPE_BOOL, false, (size_t)(&((P3ShapeFlags_Type*)0)->eSIMULATION_SHAPE), NULL, 0 }, // p3ShapeDescTemplate.flags.eSIMULATION_SHAPE + { TYPE_BOOL, false, (size_t)(&((P3ShapeFlags_Type*)0)->eSCENE_QUERY_SHAPE), NULL, 0 }, // p3ShapeDescTemplate.flags.eSCENE_QUERY_SHAPE + { TYPE_BOOL, false, (size_t)(&((P3ShapeFlags_Type*)0)->eTRIGGER_SHAPE), NULL, 0 }, // p3ShapeDescTemplate.flags.eTRIGGER_SHAPE + { TYPE_BOOL, false, (size_t)(&((P3ShapeFlags_Type*)0)->eVISUALIZATION), NULL, 0 }, // p3ShapeDescTemplate.flags.eVISUALIZATION + { TYPE_BOOL, false, (size_t)(&((P3ShapeFlags_Type*)0)->ePARTICLE_DRAIN), NULL, 0 }, // p3ShapeDescTemplate.flags.ePARTICLE_DRAIN + { TYPE_BOOL, false, (size_t)(&((P3ShapeFlags_Type*)0)->eDEFORMABLE_DRAIN), NULL, 0 }, // p3ShapeDescTemplate.flags.eDEFORMABLE_DRAIN + { TYPE_STRUCT, false, (size_t)(&((P3ShapeDescTemplate_Type*)0)->simulationFilterData), CHILDREN(197), 4 }, // p3ShapeDescTemplate.simulationFilterData + { TYPE_U32, false, (size_t)(&((P3FilterData_Type*)0)->word0), NULL, 0 }, // p3ShapeDescTemplate.simulationFilterData.word0 + { TYPE_U32, false, (size_t)(&((P3FilterData_Type*)0)->word1), NULL, 0 }, // p3ShapeDescTemplate.simulationFilterData.word1 + { TYPE_U32, false, (size_t)(&((P3FilterData_Type*)0)->word2), NULL, 0 }, // p3ShapeDescTemplate.simulationFilterData.word2 + { TYPE_U32, false, (size_t)(&((P3FilterData_Type*)0)->word3), NULL, 0 }, // p3ShapeDescTemplate.simulationFilterData.word3 + { TYPE_STRUCT, false, (size_t)(&((P3ShapeDescTemplate_Type*)0)->queryFilterData), CHILDREN(201), 4 }, // p3ShapeDescTemplate.queryFilterData + { TYPE_U32, false, (size_t)(&((P3FilterData_Type*)0)->word0), NULL, 0 }, // p3ShapeDescTemplate.queryFilterData.word0 + { TYPE_U32, false, (size_t)(&((P3FilterData_Type*)0)->word1), NULL, 0 }, // p3ShapeDescTemplate.queryFilterData.word1 + { TYPE_U32, false, (size_t)(&((P3FilterData_Type*)0)->word2), NULL, 0 }, // p3ShapeDescTemplate.queryFilterData.word2 + { TYPE_U32, false, (size_t)(&((P3FilterData_Type*)0)->word3), NULL, 0 }, // p3ShapeDescTemplate.queryFilterData.word3 + { TYPE_U64, false, (size_t)(&((P3ShapeDescTemplate_Type*)0)->material), NULL, 0 }, // p3ShapeDescTemplate.material + { TYPE_F32, false, (size_t)(&((P3ShapeDescTemplate_Type*)0)->contactOffset), NULL, 0 }, // p3ShapeDescTemplate.contactOffset + { TYPE_F32, false, (size_t)(&((P3ShapeDescTemplate_Type*)0)->restOffset), NULL, 0 }, // p3ShapeDescTemplate.restOffset + { TYPE_U64, false, (size_t)(&((P3ShapeDescTemplate_Type*)0)->userData), NULL, 0 }, // p3ShapeDescTemplate.userData + { TYPE_U64, false, (size_t)(&((P3ShapeDescTemplate_Type*)0)->name), NULL, 0 }, // p3ShapeDescTemplate.name + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->p3ActorDescTemplate), CHILDREN(205), 7 }, // p3ActorDescTemplate + { TYPE_STRUCT, false, (size_t)(&((P3ActorDescTemplate_Type*)0)->flags), CHILDREN(212), 3 }, // p3ActorDescTemplate.flags + { TYPE_BOOL, false, (size_t)(&((P3ActorFlags_Type*)0)->eVISUALIZATION), NULL, 0 }, // p3ActorDescTemplate.flags.eVISUALIZATION + { TYPE_BOOL, false, (size_t)(&((P3ActorFlags_Type*)0)->eDISABLE_GRAVITY), NULL, 0 }, // p3ActorDescTemplate.flags.eDISABLE_GRAVITY + { TYPE_BOOL, false, (size_t)(&((P3ActorFlags_Type*)0)->eSEND_SLEEP_NOTIFIES), NULL, 0 }, // p3ActorDescTemplate.flags.eSEND_SLEEP_NOTIFIES + { TYPE_U8, false, (size_t)(&((P3ActorDescTemplate_Type*)0)->dominanceGroup), NULL, 0 }, // p3ActorDescTemplate.dominanceGroup + { TYPE_U8, false, (size_t)(&((P3ActorDescTemplate_Type*)0)->ownerClient), NULL, 0 }, // p3ActorDescTemplate.ownerClient + { TYPE_U32, false, (size_t)(&((P3ActorDescTemplate_Type*)0)->clientBehaviorBits), NULL, 0 }, // p3ActorDescTemplate.clientBehaviorBits + { TYPE_STRUCT, false, (size_t)(&((P3ActorDescTemplate_Type*)0)->contactReportFlags), CHILDREN(215), 15 }, // p3ActorDescTemplate.contactReportFlags + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eSOLVE_CONTACT), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eSOLVE_CONTACT + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eMODIFY_CONTACTS), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eMODIFY_CONTACTS + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_TOUCH_FOUND), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_TOUCH_FOUND + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_TOUCH_PERSISTS), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_TOUCH_PERSISTS + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_TOUCH_LOST), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_TOUCH_LOST + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_THRESHOLD_FORCE_FOUND), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_FOUND + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_THRESHOLD_FORCE_PERSISTS), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_PERSISTS + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_THRESHOLD_FORCE_LOST), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_LOST + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_CONTACT_POINTS), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_POINTS + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_CONTACT_FORCES), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_FORCES + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_CONTACT_FORCE_PER_POINT), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_FORCE_PER_POINT + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eNOTIFY_CONTACT_FEATURE_INDICES_PER_POINT), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_FEATURE_INDICES_PER_POINT + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eDETECT_CCD_CONTACT), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eDETECT_CCD_CONTACT + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eCONTACT_DEFAULT), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eCONTACT_DEFAULT + { TYPE_BOOL, false, (size_t)(&((P3PairFlag_Type*)0)->eTRIGGER_DEFAULT), NULL, 0 }, // p3ActorDescTemplate.contactReportFlags.eTRIGGER_DEFAULT + { TYPE_U64, false, (size_t)(&((P3ActorDescTemplate_Type*)0)->userData), NULL, 0 }, // p3ActorDescTemplate.userData + { TYPE_U64, false, (size_t)(&((P3ActorDescTemplate_Type*)0)->name), NULL, 0 }, // p3ActorDescTemplate.name + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->p3BodyDescTemplate), CHILDREN(230), 11 }, // p3BodyDescTemplate + { TYPE_F32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->density), NULL, 0 }, // p3BodyDescTemplate.density + { TYPE_STRUCT, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->flags), CHILDREN(241), 2 }, // p3BodyDescTemplate.flags + { TYPE_BOOL, false, (size_t)(&((P3BodyDescFlags_Type*)0)->eKINEMATIC), NULL, 0 }, // p3BodyDescTemplate.flags.eKINEMATIC + { TYPE_BOOL, false, (size_t)(&((P3BodyDescFlags_Type*)0)->eENABLE_CCD), NULL, 0 }, // p3BodyDescTemplate.flags.eENABLE_CCD + { TYPE_F32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->sleepThreshold), NULL, 0 }, // p3BodyDescTemplate.sleepThreshold + { TYPE_F32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->wakeUpCounter), NULL, 0 }, // p3BodyDescTemplate.wakeUpCounter + { TYPE_F32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->linearDamping), NULL, 0 }, // p3BodyDescTemplate.linearDamping + { TYPE_F32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->angularDamping), NULL, 0 }, // p3BodyDescTemplate.angularDamping + { TYPE_F32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->maxAngularVelocity), NULL, 0 }, // p3BodyDescTemplate.maxAngularVelocity + { TYPE_U32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->solverIterationCount), NULL, 0 }, // p3BodyDescTemplate.solverIterationCount + { TYPE_U32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->velocityIterationCount), NULL, 0 }, // p3BodyDescTemplate.velocityIterationCount + { TYPE_F32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->contactReportThreshold), NULL, 0 }, // p3BodyDescTemplate.contactReportThreshold + { TYPE_F32, false, (size_t)(&((P3BodyDescTemplate_Type*)0)->sleepLinearVelocity), NULL, 0 }, // p3BodyDescTemplate.sleepLinearVelocity + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->structureSettings), CHILDREN(243), 3 }, // structureSettings + { TYPE_BOOL, false, (size_t)(&((StructureSettings_Type*)0)->useStressSolver), NULL, 0 }, // structureSettings.useStressSolver + { TYPE_F32, false, (size_t)(&((StructureSettings_Type*)0)->stressSolverTimeDelay), NULL, 0 }, // structureSettings.stressSolverTimeDelay + { TYPE_F32, false, (size_t)(&((StructureSettings_Type*)0)->stressSolverMassThreshold), NULL, 0 }, // structureSettings.stressSolverMassThreshold + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->defaultBehaviorGroup), CHILDREN(246), 12 }, // defaultBehaviorGroup + { TYPE_STRING, false, (size_t)(&((BehaviorGroup_Type*)0)->name), NULL, 0 }, // defaultBehaviorGroup.name + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->damageThreshold), NULL, 0 }, // defaultBehaviorGroup.damageThreshold + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->damageToRadius), NULL, 0 }, // defaultBehaviorGroup.damageToRadius + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->damageSpread), CHILDREN(258), 3 }, // defaultBehaviorGroup.damageSpread + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->minimumRadius), NULL, 0 }, // defaultBehaviorGroup.damageSpread.minimumRadius + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->radiusMultiplier), NULL, 0 }, // defaultBehaviorGroup.damageSpread.radiusMultiplier + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->falloffExponent), NULL, 0 }, // defaultBehaviorGroup.damageSpread.falloffExponent + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->damageColorSpread), CHILDREN(261), 3 }, // defaultBehaviorGroup.damageColorSpread + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->minimumRadius), NULL, 0 }, // defaultBehaviorGroup.damageColorSpread.minimumRadius + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->radiusMultiplier), NULL, 0 }, // defaultBehaviorGroup.damageColorSpread.radiusMultiplier + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->falloffExponent), NULL, 0 }, // defaultBehaviorGroup.damageColorSpread.falloffExponent + { TYPE_VEC4, false, (size_t)(&((BehaviorGroup_Type*)0)->damageColorChange), NULL, 0 }, // defaultBehaviorGroup.damageColorChange + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->materialStrength), NULL, 0 }, // defaultBehaviorGroup.materialStrength + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->density), NULL, 0 }, // defaultBehaviorGroup.density + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->fadeOut), NULL, 0 }, // defaultBehaviorGroup.fadeOut + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->maxDepenetrationVelocity), NULL, 0 }, // defaultBehaviorGroup.maxDepenetrationVelocity + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->groupsMask), CHILDREN(264), 5 }, // defaultBehaviorGroup.groupsMask + { TYPE_BOOL, false, (size_t)(&((GroupsMask_Type*)0)->useGroupsMask), NULL, 0 }, // defaultBehaviorGroup.groupsMask.useGroupsMask + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits0), NULL, 0 }, // defaultBehaviorGroup.groupsMask.bits0 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits1), NULL, 0 }, // defaultBehaviorGroup.groupsMask.bits1 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits2), NULL, 0 }, // defaultBehaviorGroup.groupsMask.bits2 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits3), NULL, 0 }, // defaultBehaviorGroup.groupsMask.bits3 + { TYPE_U64, false, (size_t)(&((BehaviorGroup_Type*)0)->userData), NULL, 0 }, // defaultBehaviorGroup.userData + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->behaviorGroups), CHILDREN(269), 1 }, // behaviorGroups + { TYPE_STRUCT, false, 1 * sizeof(BehaviorGroup_Type), CHILDREN(270), 12 }, // behaviorGroups[] + { TYPE_STRING, false, (size_t)(&((BehaviorGroup_Type*)0)->name), NULL, 0 }, // behaviorGroups[].name + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->damageThreshold), NULL, 0 }, // behaviorGroups[].damageThreshold + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->damageToRadius), NULL, 0 }, // behaviorGroups[].damageToRadius + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->damageSpread), CHILDREN(282), 3 }, // behaviorGroups[].damageSpread + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->minimumRadius), NULL, 0 }, // behaviorGroups[].damageSpread.minimumRadius + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->radiusMultiplier), NULL, 0 }, // behaviorGroups[].damageSpread.radiusMultiplier + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->falloffExponent), NULL, 0 }, // behaviorGroups[].damageSpread.falloffExponent + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->damageColorSpread), CHILDREN(285), 3 }, // behaviorGroups[].damageColorSpread + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->minimumRadius), NULL, 0 }, // behaviorGroups[].damageColorSpread.minimumRadius + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->radiusMultiplier), NULL, 0 }, // behaviorGroups[].damageColorSpread.radiusMultiplier + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->falloffExponent), NULL, 0 }, // behaviorGroups[].damageColorSpread.falloffExponent + { TYPE_VEC4, false, (size_t)(&((BehaviorGroup_Type*)0)->damageColorChange), NULL, 0 }, // behaviorGroups[].damageColorChange + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->materialStrength), NULL, 0 }, // behaviorGroups[].materialStrength + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->density), NULL, 0 }, // behaviorGroups[].density + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->fadeOut), NULL, 0 }, // behaviorGroups[].fadeOut + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->maxDepenetrationVelocity), NULL, 0 }, // behaviorGroups[].maxDepenetrationVelocity + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->groupsMask), CHILDREN(288), 5 }, // behaviorGroups[].groupsMask + { TYPE_BOOL, false, (size_t)(&((GroupsMask_Type*)0)->useGroupsMask), NULL, 0 }, // behaviorGroups[].groupsMask.useGroupsMask + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits0), NULL, 0 }, // behaviorGroups[].groupsMask.bits0 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits1), NULL, 0 }, // behaviorGroups[].groupsMask.bits1 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits2), NULL, 0 }, // behaviorGroups[].groupsMask.bits2 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits3), NULL, 0 }, // behaviorGroups[].groupsMask.bits3 + { TYPE_U64, false, (size_t)(&((BehaviorGroup_Type*)0)->userData), NULL, 0 }, // behaviorGroups[].userData + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->deleteChunksLeavingUserDefinedBB), NULL, 0 }, // deleteChunksLeavingUserDefinedBB + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->deleteChunksEnteringUserDefinedBB), NULL, 0 }, // deleteChunksEnteringUserDefinedBB +}; + + +bool DestructibleActorParam::mBuiltFlag = false; +NvParameterized::MutexType DestructibleActorParam::mBuiltFlagMutex; + +DestructibleActorParam::DestructibleActorParam(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &DestructibleActorParamFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +DestructibleActorParam::~DestructibleActorParam() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void DestructibleActorParam::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~DestructibleActorParam(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* DestructibleActorParam::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* DestructibleActorParam::getParameterDefinitionTree(void) const +{ + DestructibleActorParam* tmpParam = const_cast<DestructibleActorParam*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType DestructibleActorParam::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType DestructibleActorParam::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void DestructibleActorParam::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<DestructibleActorParam::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ +/* [0] - overrideSkinnedMaterialNames (not an array of structs) */ +/* [0] - overrideStaticMaterialNames (not an array of structs) */ +/* [1,0] - behaviorGroups.name */ + +void DestructibleActorParam::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void DestructibleActorParam::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="crumbleEmitterName" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("crumbleEmitterName", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The name of the MeshParticleSystem to use for crumbling. This overrides the crumble system defined\nin the DestructibleAsset if specified.\n", true); + HintTable[1].init("shortDescription", "The name of the MeshParticleSystem to use for crumbling", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="crumbleParticleSpacing" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("crumbleParticleSpacing", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How far apart to space the particles when crumling. If set to zero or a negative value, then the spacing is taken to be the crumble emitter's particle radius, if the\ncrumble emitter exists. This spacing will be used when placing particle positions in the crumble emitter and the crumble buffer callback. Note - if there is no crumble emitter\nbut there is a crumble buffer callback, then this value must be positive in order to have a proper spacing for the callback. Otherwise, the callback will not be called.\nThe default value is 0.\n", true); + HintTable[1].init("shortDescription", "How far apart to space the particles when crumbling", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="dustEmitterName" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("dustEmitterName", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The name of the MeshParticleSystem to use for fracture-line dust. This overrides the dust system defined\nin the DestructibleAsset if specified.\n", true); + HintTable[1].init("shortDescription", "The name of the MeshParticleSystem to use for fracture-line dust", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="dustParticleSpacing" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("dustParticleSpacing", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How far apart to space the particles when crumling. If set to zero or a negative value, then the spacing is taken to be the dust emitter's particle radius, if the\ndust emitter exists. This spacing will be used when placing particle positions in the dust emitter and the dust particle buffer callback. Note - if there is no dust emitter\nbut there is a dust particle buffer callback, then this value must be positive in order to have a proper spacing for the callback. Otherwise, the callback will not be called.\nThe default value is 0.\n", true); + HintTable[1].init("shortDescription", "How far apart to space the particles when creating dust particles", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="globalPose" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("globalPose", TYPE_TRANSFORM, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Initial global pose of undamaged destructible\n", true); + HintTable[1].init("shortDescription", "The initial pose where the destructible actor will be put into the scene", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=6, longName="scale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6]; + ParamDef->init("scale", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "3D Scale\n", true); + HintTable[1].init("shortDescription", "3D Scale", true); + ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=7, longName="dynamic" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7]; + ParamDef->init("dynamic", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not the destructible starts life as a dynamic actor\n", true); + HintTable[1].init("shortDescription", "Whether or not the destructible starts life as a dynamic actor", true); + ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=8, longName="supportDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8]; + ParamDef->init("supportDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The chunk hierarchy depth at which to create a support graph. Higher depth levels give more detailed support,\nbut will give a higher computational load. Chunks below the support depth will never be supported.\n", true); + HintTable[1].init("shortDescription", "The chunk hierarchy depth at which to create a support graph.", true); + ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=9, longName="formExtendedStructures" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9]; + ParamDef->init("formExtendedStructures", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If initially static, the destructible will become part of an extended support structure if it is\nin contact with another static destructible that also has this flag set.\n", true); + HintTable[1].init("shortDescription", "If initially static, the destructible will become part of an extended support structure if it is in contact with another static destructible that also has this flag set.", true); + ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=10, longName="performDetailedOverlapTestForExtendedStructures" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10]; + ParamDef->init("performDetailedOverlapTestForExtendedStructures", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "When testing for chunk overlap with other destructibles in an extended structure (see formExtendedStructures), perform detailed collision test. Otherwise, just test AABBs.\nDefault = TRUE.\n", true); + HintTable[1].init("shortDescription", "When testing for chunk overlap with other destructibles, perform detailed collision test. Otherwise, just test AABBs.", true); + ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=11, longName="keepPreviousFrameBoneBuffer" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11]; + ParamDef->init("keepPreviousFrameBoneBuffer", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, the skinned mesh will hold a bone buffer for the last frame. The poses in the new buffer correspond the poses in the current frame buffer,\n chunk was not visible in the last frame.", true); + HintTable[1].init("shortDescription", "If true, the skinned mesh will hold a bone buffer for the last frame", true); + ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=12, longName="doNotCreateRenderable" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12]; + ParamDef->init("doNotCreateRenderable", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, a renderable will not be created for the destructible actor. This prevents unnecessary updates when the APEX render API is not being used.", true); + HintTable[1].init("shortDescription", "If true, a renderable will not be created for the destructible actor", true); + ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=13, longName="useAssetDefinedSupport" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13]; + ParamDef->init("useAssetDefinedSupport", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, then chunks which are tagged as 'support' chunks (via DestructibleChunkDesc::isSupportChunk)\nwill have environmental support in static destructibles.\nNote: if both ASSET_DEFINED_SUPPORT and WORLD_SUPPORT are set, then chunks must be tagged as\n'support' chunks AND overlap the PxScene's static geometry in order to be environmentally supported.\n", true); + HintTable[1].init("shortDescription", "If set, then chunks which are tagged as 'support' chunks", true); + ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=14, longName="useWorldSupport" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14]; + ParamDef->init("useWorldSupport", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, then chunks which overlap the PxScene\'s static geometry will have environmental support in\nstatic destructibles.\nNote: if both ASSET_DEFINED_SUPPORT and WORLD_SUPPORT are set, then chunks must be tagged as\n'support' chunks AND overlap the PxScene's static geometry in order to be environmentally supported.\n", true); + HintTable[1].init("shortDescription", "If set, then chunks which overlap the PxScene's static geometry will have environmental support", true); + ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=15, longName="renderStaticChunksSeparately" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15]; + ParamDef->init("renderStaticChunksSeparately", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, static chunks will be renderered separately from dynamic chunks, as a single mesh (not using skinning).\nThis parameter is ignored if the \'dynamic\' parameter is true.\nDefault value = false.\n", true); + HintTable[1].init("shortDescription", "Whether or not to render static chunks in a separate mesh", true); + ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=16, longName="keepVisibleBonesPacked" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16]; + ParamDef->init("keepVisibleBonesPacked", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Parameter passed into skinned ApexRenderMeshActor. If true, visible bone matrices are packed into the bone render buffer, and a per-actor vertex buffer is created to handle re-indexed bones.\nDefault value = true.\n", true); + HintTable[1].init("shortDescription", "Parameter passed into skinned ApexRenderMeshActor", true); + ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=17, longName="createChunkEvents" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17]; + ParamDef->init("createChunkEvents", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not to create an event buffer for chunk.\nIf true, the user has access to a chunk event buffer, which currently holds visibility state change events.\nThe user must empty this buffer themselves after reading, otherwise it will continue to grow as new events are added.\nDefault value = false.\n", true); + HintTable[1].init("shortDescription", "Whether or not to create an event buffer for chunks", true); + ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=18, longName="overrideSkinnedMaterialNames" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18]; + ParamDef->init("overrideSkinnedMaterialNames", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-actor material names, to override those in the asset, for skinned rendering.", true); + HintTable[1].init("shortDescription", "Per-actor material names, to override those in the asset, for skinned rendering", true); + ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=19, longName="overrideSkinnedMaterialNames[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19]; + ParamDef->init("overrideSkinnedMaterialNames", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-actor material names, to override those in the asset, for skinned rendering.", true); + HintTable[1].init("shortDescription", "Per-actor material names, to override those in the asset, for skinned rendering", true); + ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=20, longName="overrideStaticMaterialNames" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20]; + ParamDef->init("overrideStaticMaterialNames", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-actor material names, to override those in the asset, for static rendering.", true); + HintTable[1].init("shortDescription", "Per-actor material names, to override those in the asset, for static rendering", true); + ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=21, longName="overrideStaticMaterialNames[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21]; + ParamDef->init("overrideStaticMaterialNames", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-actor material names, to override those in the asset, for static rendering.", true); + HintTable[1].init("shortDescription", "Per-actor material names, to override those in the asset, for static rendering", true); + ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=22, longName="sleepVelocityFrameDecayConstant" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22]; + ParamDef->init("sleepVelocityFrameDecayConstant", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Frame memory decay constant used for actor velocity smoothing. Valid range: [1.0,infinity). Roughly speaking,\n the number of frames for which past velocities have significance. A value of 1.0 (or less) gives no smoothing.", true); + HintTable[1].init("shortDescription", "Frame memory decay constant used for actor velocity smoothing. Valid range: [1.0,infinity).", true); + ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=23, longName="useHardSleeping" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23]; + ParamDef->init("useHardSleeping", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, turn chunk islands kinematic when they sleep. These islands may be turned dynamic again if enough damage is applied.", true); + HintTable[1].init("shortDescription", "If true, turn chunk islands kinematic when they sleep.", true); + ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=24, longName="destructibleParameters" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24]; + ParamDef->init("destructibleParameters", TYPE_STRUCT, "DestructibleParameters", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Parameters controlling the destruction properties - damage thresholds, damage radius multipliers, etc.\n", true); + HintTable[1].init("shortDescription", "Parameters controlling the destruction properties - damage thresholds, damage radius multipliers, etc.", true); + ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=25, longName="destructibleParameters.damageCap" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25]; + ParamDef->init("damageCap", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Limits the amount of damage applied to a chunk. This is useful for preventing the entire destructible\nfrom getting pulverized by a very large application of damage. This can easily happen when impact damage is\nused, and the damage amount is proportional to the impact force (see forceToDamage).\n", true); + HintTable[1].init("shortDescription", "Limits the amount of damage applied to a chunk.", true); + ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=26, longName="destructibleParameters.forceToDamage" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26]; + ParamDef->init("forceToDamage", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If a chunk is at a depth which takes impact damage (see NxDestructibleDepthParameters),\nthen when a chunk has a collision in the NxScene, it will take damage equal to forceToDamage mulitplied by\nthe impact force.\nThe default value is zero, which effectively disables impact damage.\n", true); + HintTable[1].init("shortDescription", "Multiplier to calculate applied damage from an impact.", true); + ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=27, longName="destructibleParameters.impactVelocityThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27]; + ParamDef->init("impactVelocityThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Large impact force may be reported if rigid bodies are spawned inside one another. In this case the relative velocity of the two\nobjects will be low. This variable allows the user to set a minimum velocity threshold for impacts to ensure that the objects are\nmoving at a min velocity in order for the impact force to be considered.\n", true); + HintTable[1].init("shortDescription", "Large impact force may be reported if rigid bodies are spawned inside one another.", true); + ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=28, longName="destructibleParameters.minimumFractureDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28]; + ParamDef->init("minimumFractureDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks will not be broken free below this depth.\n", true); + HintTable[1].init("shortDescription", "The chunks will not be broken free below this depth.", true); + ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=29, longName="destructibleParameters.impactDamageDefaultDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29]; + ParamDef->init("impactDamageDefaultDepth", TYPE_I32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The default depth to which chunks will take impact damage. This default may be overridden in the depth settings.\n", true); + HintTable[1].init("shortDescription", "The default depth to which chunks will take impact damage.", true); + ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=30, longName="destructibleParameters.debrisDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30]; + ParamDef->init("debrisDepth", TYPE_I32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The chunk hierarchy depth at which chunks are considered to be 'debris.' Chunks at this depth or\nbelow will be considered for various debris settings, such as debrisLifetime.\nNegative values indicate that no chunk depth is considered debris.\nDefault value is -1.\n", true); + HintTable[1].init("shortDescription", "The chunk hierarchy depth at which chunks are considered to be 'debris.'", true); + ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=31, longName="destructibleParameters.essentialDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31]; + ParamDef->init("essentialDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The chunk hierarchy depth up to which chunks will always be processed. These chunks are considered\nto be essential either for gameplay or visually.\nThe minimum value is 0, meaning the level 0 chunk is always considered essential.\nDefault value is 0.\n", true); + HintTable[1].init("shortDescription", "The chunk hierarchy depth up to which chunks will always be processed", true); + ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=32, longName="destructibleParameters.debrisLifetimeMin" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32]; + ParamDef->init("debrisLifetimeMin", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed after a time (in seconds)\nseparated from non-debris chunks. The actual lifetime is interpolated between\ndebrisLifetimeMin and debrisLifetimeMax (see below), based upon the module\'s LOD setting.\nTo disable lifetime, clear the NxDestructibleDepthParametersFlag::DEBRIS_TIMEOUT\nflag in the flags field. If debrisLifetimeMax < debrisLifetimeMin, the mean of the two\nis used for both.\nDefault debrisLifetimeMin = 1.0, debrisLifetimeMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Minimum time to destroy debris", true); + ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=33, longName="destructibleParameters.debrisLifetimeMax" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33]; + ParamDef->init("debrisLifetimeMax", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed after a time (in seconds)\nseparated from non-debris chunks. The actual lifetime is interpolated between\ndebrisLifetimeMin (see above) and debrisLifetimeMax, based upon the module\'s LOD setting.\nTo disable lifetime, clear the NxDestructibleDepthParametersFlag::DEBRIS_TIMEOUT\nflag in the flags field. If debrisLifetimeMax < debrisLifetimeMin, the mean of the two\nis used for both.\nDefault debrisLifetimeMin = 1.0, debrisLifetimeMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Maximum time to destroy debris", true); + ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=34, longName="destructibleParameters.debrisMaxSeparationMin" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34]; + ParamDef->init("debrisMaxSeparationMin", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed if they are separated from\ntheir origin by a distance greater than maxSeparation. The actual maxSeparation is\ninterpolated between debrisMaxSeparationMin and debrisMaxSeparationMax (see below),\nbased upon the module\'s LOD setting. To disable maxSeparation, clear the\nNX_DESTRUCTIBLE_DEBRIS_MAX_SEPARATION flag in the flags field.\nIf debrisMaxSeparationMax < debrisMaxSeparationMin, the mean of the two is used for both.\nDefault debrisMaxSeparationMin = 1.0, debrisMaxSeparationMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Minimum separation distance", true); + ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=35, longName="destructibleParameters.debrisMaxSeparationMax" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35]; + ParamDef->init("debrisMaxSeparationMax", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed if they are separated from\ntheir origin by a distance greater than maxSeparation. The actual maxSeparation is\ninterpolated between debrisMaxSeparationMin (see above) and debrisMaxSeparationMax,\nbased upon the module\'s LOD setting. To disable maxSeparation, clear the\nNX_DESTRUCTIBLE_DEBRIS_MAX_SEPARATION flag in the flags field.\nIf debrisMaxSeparationMax < debrisMaxSeparationMin, the mean of the two is used for both.\nDefault debrisMaxSeparationMin = 1.0, debrisMaxSeparationMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Minimum separation distance", true); + ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=36, longName="destructibleParameters.debrisDestructionProbability" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36]; + ParamDef->init("debrisDestructionProbability", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The probablity that a debris chunk, when fractured, will simply be destroyed instead of becoming dynamic or breaking down\n further into child chunks. Valid range = [0.0,1.0]. Default value = 0.0.", true); + HintTable[1].init("shortDescription", "The probablity that a debris chunk, when fractured, will simply be destroyed", true); + ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=37, longName="destructibleParameters.validBounds" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37]; + ParamDef->init("validBounds", TYPE_BOUNDS3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A bounding box around each NxDestructibleActor created, defining a range of validity\nfor chunks that break free. These bounds are scaled and translated with the\nNxDestructibleActor\'s scale and position, but they are not rotated with the\nNxDestructibleActor.\n", true); + HintTable[1].init("shortDescription", "valid bounding region for debris", true); + ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=38, longName="destructibleParameters.maxChunkSpeed" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38]; + ParamDef->init("maxChunkSpeed", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If greater than 0, the chunks' speeds will not be allowed to exceed this value. Use 0\nto disable this feature (this is the default).\n", true); + HintTable[1].init("shortDescription", "Maximum speed of a chunk", true); + ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=39, longName="destructibleParameters.flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39]; + ParamDef->init("flags", TYPE_STRUCT, "DestructibleParametersFlag", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A collection of flags defined in NxDestructibleParametersFlag.\n", true); + HintTable[1].init("shortDescription", "A collection of flags defined in DestructibleParametersFlag.", true); + ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=40, longName="destructibleParameters.flags.ACCUMULATE_DAMAGE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40]; + ParamDef->init("ACCUMULATE_DAMAGE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, chunks will 'remember' damage applied to them, so that many applications of a damage amount\nbelow damageThreshold will eventually fracture the chunk. If not set, a single application of\ndamage must exceed damageThreshold in order to fracture the chunk.\n", true); + HintTable[1].init("shortDescription", "Determines if chunks accumulate damage", true); + ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=41, longName="destructibleParameters.flags.DEBRIS_TIMEOUT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[41]; + ParamDef->init("DEBRIS_TIMEOUT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not chunks at or deeper than the 'debris' depth (see NxDestructibleParameters::debrisDepth)\nwill time out. The lifetime is a value between NxDestructibleParameters::debrisLifetimeMin and\nNxDestructibleParameters::debrisLifetimeMax, based upon the destructible module\'s LOD setting.\n", true); + HintTable[1].init("shortDescription", "Whether or not chunks at or deeper than the 'debris' depth will timeout", true); + ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=42, longName="destructibleParameters.flags.DEBRIS_MAX_SEPARATION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[42]; + ParamDef->init("DEBRIS_MAX_SEPARATION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not chunks at or deeper than the 'debris' depth (see NxDestructibleParameters::debrisDepth)\nwill be removed if they separate too far from their origins. The maxSeparation is a value between\nNxDestructibleParameters::debrisMaxSeparationMin and NxDestructibleParameters::debrisMaxSeparationMax,\nbased upon the destructible module\'s LOD setting.\n", true); + HintTable[1].init("shortDescription", "Whether or not chunks at or deeper than the 'debris' depth will be removed if separated too far", true); + ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=43, longName="destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[43]; + ParamDef->init("CRUMBLE_SMALLEST_CHUNKS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, the smallest chunks may be further broken down, either by fluid crumbles (if a crumble particle\nsystem is specified in the NxDestructibleActorDesc), or by simply removing the chunk if no crumble\nparticle system is specified. Note: the 'smallest chunks' are normally defined to be the deepest level\nof the fracture hierarchy. However, they may be taken from higher levels of the hierarchy if\nNxModuleDestructible::setMaxChunkDepthOffset is called with a non-zero value.\n", true); + HintTable[1].init("shortDescription", "If set, the smallest chunks may be further broken down", true); + ParamDefTable[43].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=44, longName="destructibleParameters.flags.ACCURATE_RAYCASTS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[44]; + ParamDef->init("ACCURATE_RAYCASTS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, the NxDestructibleActor::rayCast function will search within the nearest visible chunk hit\nfor collisions with child chunks. This is used to get a better raycast position and normal, in\ncase the parent collision volume does not tightly fit the graphics mesh. The returned chunk index\nwill always be that of the visible parent that is intersected, however.\n", true); + HintTable[1].init("shortDescription", "If set, the NxDestructibleActor::rayCast function will search within the nearest visible chunk hit", true); + ParamDefTable[44].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=45, longName="destructibleParameters.flags.USE_VALID_BOUNDS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[45]; + ParamDef->init("USE_VALID_BOUNDS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, the validBounds field of NxDestructibleParameters will be used. These bounds are translated\n(but not scaled or rotated) to the origin of the destructible actor. If a chunk or chunk island moves\noutside of those bounds, it is destroyed.\n", true); + HintTable[1].init("shortDescription", "If set, the validBounds field of NxDestructibleParameters will be used.", true); + ParamDefTable[45].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=46, longName="destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[46]; + ParamDef->init("CRUMBLE_VIA_RUNTIME_FRACTURE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, crumbled chunks will use the runtime fracture pipeline. The chunk will be procedurally broken\ndestroyed using either the default or a specified fracture pattern.\n", true); + HintTable[1].init("shortDescription", "If set, crumbled chunks will use the runtime fracture pipeline.", true); + ParamDefTable[46].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=47, longName="destructibleParameters.fractureImpulseScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[47]; + ParamDef->init("fractureImpulseScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scale factor used to apply an impulse force along the normal of chunk when fractured. This is used\nin order to 'push' the pieces out as they fracture.\n", true); + HintTable[1].init("shortDescription", "Scale factor used to apply an impulse force along the normal of chunk when fractured.", true); + ParamDefTable[47].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=48, longName="destructibleParameters.damageDepthLimit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[48]; + ParamDef->init("damageDepthLimit", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How deep in the hierarchy damage will be propagated, relative to the chunk hit.", true); + HintTable[1].init("shortDescription", "How deep in the hierarchy damage will be propagated, relative to the chunk hit.", true); + ParamDefTable[48].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=49, longName="destructibleParameters.dynamicChunkDominanceGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[49]; + ParamDef->init("dynamicChunkDominanceGroup", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Optional dominance group for dynamic chunks created when fractured. (ignored if > 31)\n", true); + HintTable[1].init("shortDescription", "Optional dominance group for dynamic chunks created when fractured.", true); + ParamDefTable[49].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=50, longName="destructibleParameters.dynamicChunksGroupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[50]; + ParamDef->init("dynamicChunksGroupsMask", TYPE_STRUCT, "GroupsMask", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Optional groups mask for dynamic chunks created when fractured.\n", true); + HintTable[1].init("shortDescription", "Optional groups mask for dynamic chunks created when fractured.", true); + ParamDefTable[50].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=51, longName="destructibleParameters.dynamicChunksGroupsMask.useGroupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[51]; + ParamDef->init("useGroupsMask", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not the groupsMask should be used. If so, then this will be applied to all NxShapes\n created to represent this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Whether or not the groupsMask should be used", true); + ParamDefTable[51].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=52, longName="destructibleParameters.dynamicChunksGroupsMask.bits0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[52]; + ParamDef->init("bits0", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits0 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits0 of the groups mask", true); + ParamDefTable[52].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=53, longName="destructibleParameters.dynamicChunksGroupsMask.bits1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[53]; + ParamDef->init("bits1", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits1 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits1 of the groups mask", true); + ParamDefTable[53].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=54, longName="destructibleParameters.dynamicChunksGroupsMask.bits2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[54]; + ParamDef->init("bits2", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits2 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits2 of the groups mask", true); + ParamDefTable[54].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=55, longName="destructibleParameters.dynamicChunksGroupsMask.bits3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[55]; + ParamDef->init("bits3", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits3 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits3 of the groups mask", true); + ParamDefTable[55].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=56, longName="destructibleParameters.runtimeFracture" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[56]; + ParamDef->init("runtimeFracture", TYPE_STRUCT, "RuntimeFracture", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Runtime Fracture Settings. 'CRUMBLE_VIA_RUNTIME_FRACTURE' must be set for this to do anything.\n", true); + HintTable[1].init("shortDescription", "Runtime Fracture Settings", true); + ParamDefTable[56].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=57, longName="destructibleParameters.runtimeFracture.RuntimeFractureType" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[57]; + ParamDef->init("RuntimeFractureType", TYPE_ENUM, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Which type of fracture pattern to choose", true); + ParamDefTable[57].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + static const char* const EnumVals[] = { "VORONOI", "GLASS" }; + ParamDefTable[57].setEnumVals((const char**)EnumVals, 2); + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=58, longName="destructibleParameters.runtimeFracture.sheetFracture" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[58]; + ParamDef->init("sheetFracture", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, align fracture pattern to largest face. \nIf false, the fracture pattern will be aligned to the hit normal with each fracture.\n", true); + HintTable[1].init("shortDescription", "If true, align fracture pattern to largest face", true); + ParamDefTable[58].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=59, longName="destructibleParameters.runtimeFracture.depthLimit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[59]; + ParamDef->init("depthLimit", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of times deep a chunk can be fractured. Can help limit the number of chunks produced by\nruntime fracture.\n", true); + HintTable[1].init("shortDescription", "Number of times deep a chunk can be fractured.", true); + ParamDefTable[59].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=60, longName="destructibleParameters.runtimeFracture.destroyIfAtDepthLimit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[60]; + ParamDef->init("destroyIfAtDepthLimit", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, destroy chunks when they hit their depth limit. \nIf false, then chunks at their depth limit will not fracture but will have a force applied.\n", true); + HintTable[1].init("shortDescription", "Destroy chunk if at depth limit", true); + ParamDefTable[60].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=61, longName="destructibleParameters.runtimeFracture.minConvexSize" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[61]; + ParamDef->init("minConvexSize", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Minimum Convex Size. Minimum size of convex produced by a fracture.\n", true); + HintTable[1].init("shortDescription", "Minimum Convex Size.", true); + ParamDefTable[61].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=62, longName="destructibleParameters.runtimeFracture.impulseScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[62]; + ParamDef->init("impulseScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scales impulse applied by a fracture.\n", true); + HintTable[1].init("shortDescription", "Scales impulse applied by a fracture.", true); + ParamDefTable[62].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=63, longName="destructibleParameters.runtimeFracture.glass" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[63]; + ParamDef->init("glass", TYPE_STRUCT, "FractureGlass", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Glass Fracture Pattern Settings.\n", true); + HintTable[1].init("shortDescription", "Glass Fracture Pattern Settings.", true); + ParamDefTable[63].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=64, longName="destructibleParameters.runtimeFracture.glass.numSectors" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[64]; + ParamDef->init("numSectors", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of angular slices in the glass fracture pattern. \n", true); + HintTable[1].init("shortDescription", "Number of angular slices.", true); + ParamDefTable[64].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=65, longName="destructibleParameters.runtimeFracture.glass.sectorRand" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[65]; + ParamDef->init("sectorRand", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Creates variance in the angle of slices. A value of zero results in all angular slices having the same angle.\n", true); + HintTable[1].init("shortDescription", "Creates variance in the angle of slices.", true); + ParamDefTable[65].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=66, longName="destructibleParameters.runtimeFracture.glass.firstSegmentSize" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[66]; + ParamDef->init("firstSegmentSize", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum shard size. Shards below this size will not be created and thus not visible.\n", true); + HintTable[1].init("shortDescription", "The minimum shard size.", true); + ParamDefTable[66].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=67, longName="destructibleParameters.runtimeFracture.glass.segmentScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[67]; + ParamDef->init("segmentScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scales the radial spacing in the glass fracture pattern. A larger value results in radially longer shards.\n", true); + HintTable[1].init("shortDescription", "Scales the radial spacing.", true); + ParamDefTable[67].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=68, longName="destructibleParameters.runtimeFracture.glass.segmentRand" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[68]; + ParamDef->init("segmentRand", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Creates variance in the radial size of shards. A value of zero results in a low noise circular pattern.\n", true); + HintTable[1].init("shortDescription", "Creates variance in the radial size of shards.", true); + ParamDefTable[68].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=69, longName="destructibleParameters.runtimeFracture.voronoi" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[69]; + ParamDef->init("voronoi", TYPE_STRUCT, "FractureVoronoi", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Voronoi Fracture Pattern Settings.\n", true); + HintTable[1].init("shortDescription", "Voronoi Fracture Pattern Settings.", true); + ParamDefTable[69].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=70, longName="destructibleParameters.runtimeFracture.voronoi.dimensions" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[70]; + ParamDef->init("dimensions", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The size of the entire block. \n", true); + HintTable[1].init("shortDescription", "The size of the entire block", true); + ParamDefTable[70].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=71, longName="destructibleParameters.runtimeFracture.voronoi.numCells" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[71]; + ParamDef->init("numCells", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of Cells corresponds to the number of chunks to create during the fracture, default value is only one chunk.\n", true); + HintTable[1].init("shortDescription", "Max Number of Cells to create.", true); + ParamDefTable[71].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=72, longName="destructibleParameters.runtimeFracture.voronoi.biasExp" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[72]; + ParamDef->init("biasExp", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Bias Exponential value is used in distributing voronoi points which is used to fracture the original chunk.\n", true); + HintTable[1].init("shortDescription", "Bias Exponential value.", true); + ParamDefTable[72].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=73, longName="destructibleParameters.runtimeFracture.voronoi.maxDist" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[73]; + ParamDef->init("maxDist", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "This is to prevent a illegal voronoi point that's used to generate voronoi chunks.\n", true); + HintTable[1].init("shortDescription", "The max distance a Voronoi point away from origin.", true); + ParamDefTable[73].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=74, longName="destructibleParameters.runtimeFracture.attachment" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[74]; + ParamDef->init("attachment", TYPE_STRUCT, "FractureAttachment", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Attachment Settings. Allows the sides of a runtime fracture chunk to be kinematic rather than dynamic.\n", true); + HintTable[1].init("shortDescription", "Attachment Settings", true); + ParamDefTable[74].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=75, longName="destructibleParameters.runtimeFracture.attachment.posX" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[75]; + ParamDef->init("posX", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the positive x side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to positive x side of sheet.", true); + ParamDefTable[75].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=76, longName="destructibleParameters.runtimeFracture.attachment.negX" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[76]; + ParamDef->init("negX", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the negative x side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to negative x side of sheet.", true); + ParamDefTable[76].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=77, longName="destructibleParameters.runtimeFracture.attachment.posY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[77]; + ParamDef->init("posY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the positive y side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to positive y side of sheet.", true); + ParamDefTable[77].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=78, longName="destructibleParameters.runtimeFracture.attachment.negY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[78]; + ParamDef->init("negY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the negative y side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to negative y side of sheet.", true); + ParamDefTable[78].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=79, longName="destructibleParameters.runtimeFracture.attachment.posZ" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[79]; + ParamDef->init("posZ", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the positive z side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to positive z side of sheet.", true); + ParamDefTable[79].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=80, longName="destructibleParameters.runtimeFracture.attachment.negZ" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[80]; + ParamDef->init("negZ", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the negative z side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to negative z side of sheet.", true); + ParamDefTable[80].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=81, longName="destructibleParameters.supportStrength" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[81]; + ParamDef->init("supportStrength", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The larger the supportStrength is, the harder it will break under stressSolver. SupportStrength should be larger\nthan 0.0 so that it is not extremely fragile.\nDefault supportStrength = -1.0 which means strength is turned off initially.\n", true); + HintTable[1].init("shortDescription", "The support strength threshold for breaking chunks in stressSolver", true); + ParamDefTable[81].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=82, longName="destructibleParameters.legacyChunkBoundsTestSetting" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[82]; + ParamDef->init("legacyChunkBoundsTestSetting", TYPE_I8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not to use the old chunk bounds testing for damage, or use the module setting. A value of 0 forces the new method to be used.\nA positive value forces the old method to be used. Negative values cause the global (NxModuleDestructible) setting to be used.\n", true); + HintTable[1].init("shortDescription", "Whether or not to use the old chunk bounds testing for damage, or use the module setting.", true); + ParamDefTable[82].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=83, longName="destructibleParameters.legacyDamageRadiusSpreadSetting" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[83]; + ParamDef->init("legacyDamageRadiusSpreadSetting", TYPE_I8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("END", "", true); + ParamDefTable[83].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("END", "", true); + HintTable[1].init("longDescription", "Whether or not to use the old damage spread method, or use the module setting. A value of 0 forces the new method to be used.\nA positive value forces the old method to be used. Negative values cause the global (NxModuleDestructible) setting to be used.\n", true); + HintTable[2].init("shortDescription", "Whether or not to use the old damage spread method, or use the module setting.", true); + ParamDefTable[83].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=84, longName="destructibleParameters.alwaysDrawScatterMesh" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[84]; + ParamDef->init("alwaysDrawScatterMesh", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scatter mesh visibility is controlled by LOD. If asset has more than one depth level, scatter mesh is not drawn.\n This flag forces drawing of scatter mesh on chunks with depth > 1.", true); + HintTable[1].init("shortDescription", "Always draw scatter mesh on the chunks with depth > 1", true); + ParamDefTable[84].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=85, longName="depthParameters" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[85]; + ParamDef->init("depthParameters", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Parameters that apply to every chunk at a given level (see DestructibleDepthParameters)\nthe element [0] of the array applies to the level 0 (unfractured) chunk, element [1] applies\nto the level 1 chunks, etc.\n", true); + HintTable[1].init("shortDescription", "Parameters that apply to every chunk at a given level (see DestructibleDepthParameters).", true); + ParamDefTable[85].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=86, longName="depthParameters[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[86]; + ParamDef->init("depthParameters", TYPE_STRUCT, "DestructibleDepthParameters", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Parameters that apply to every chunk at a given level (see DestructibleDepthParameters)\nthe element [0] of the array applies to the level 0 (unfractured) chunk, element [1] applies\nto the level 1 chunks, etc.\n", true); + HintTable[1].init("shortDescription", "Parameters that apply to every chunk at a given level (see DestructibleDepthParameters).", true); + ParamDefTable[86].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=87, longName="depthParameters[].OVERRIDE_IMPACT_DAMAGE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[87]; + ParamDef->init("OVERRIDE_IMPACT_DAMAGE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks at this hierarchy depth level will take impact damage iff OVERRIDE_IMPACT_DAMAGE_VALUE = TRUE, no matter the setting of impactDamageDefaultDepth.\n", true); + HintTable[1].init("shortDescription", "If true, chunks at this hierarchy depth level will take impact damage iff OVERRIDE_IMPACT_DAMAGE_VALUE = TRUE, no matter the setting of impactDamageDefaultDepth.", true); + ParamDefTable[87].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=88, longName="depthParameters[].OVERRIDE_IMPACT_DAMAGE_VALUE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[88]; + ParamDef->init("OVERRIDE_IMPACT_DAMAGE_VALUE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If OVERRIDE_IMPACT_DAMAGE = TRUE, chunks at this hierarchy depth level will take impact damage iff OVERRIDE_IMPACT_DAMAGE_VALUE = TRUE.\n", true); + HintTable[1].init("shortDescription", "If OVERRIDE_IMPACT_DAMAGE = TRUE, chunks at this hierarchy depth level will take impact damage iff OVERRIDE_IMPACT_DAMAGE_VALUE = TRUE.", true); + ParamDefTable[88].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=89, longName="depthParameters[].IGNORE_POSE_UPDATES" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[89]; + ParamDef->init("IGNORE_POSE_UPDATES", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks at this depth should have pose updates ignored.\n", true); + HintTable[1].init("shortDescription", "Chunks at this depth should have pose updates ignored.", true); + ParamDefTable[89].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=90, longName="depthParameters[].IGNORE_RAYCAST_CALLBACKS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[90]; + ParamDef->init("IGNORE_RAYCAST_CALLBACKS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks at this depth should be ignored in raycast callbacks.\n", true); + HintTable[1].init("shortDescription", "Chunks at this depth should be ignored in raycast callbacks.", true); + ParamDefTable[90].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=91, longName="depthParameters[].IGNORE_CONTACT_CALLBACKS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[91]; + ParamDef->init("IGNORE_CONTACT_CALLBACKS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks at this depth should be ignored in contact callbacks.\n", true); + HintTable[1].init("shortDescription", "Chunks at this depth should be ignored in contact callbacks.", true); + ParamDefTable[91].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=92, longName="depthParameters[].USER_FLAG_0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[92]; + ParamDef->init("USER_FLAG_0", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User defined flag.\n", true); + HintTable[1].init("shortDescription", "User defined flag.", true); + ParamDefTable[92].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=93, longName="depthParameters[].USER_FLAG_1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[93]; + ParamDef->init("USER_FLAG_1", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User defined flag.\n", true); + HintTable[1].init("shortDescription", "User defined flag.", true); + ParamDefTable[93].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=94, longName="depthParameters[].USER_FLAG_2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[94]; + ParamDef->init("USER_FLAG_2", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User defined flag.\n", true); + HintTable[1].init("shortDescription", "User defined flag.", true); + ParamDefTable[94].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=95, longName="depthParameters[].USER_FLAG_3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[95]; + ParamDef->init("USER_FLAG_3", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User defined flag.\n", true); + HintTable[1].init("shortDescription", "User defined flag.", true); + ParamDefTable[95].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=96, longName="shapeDescTemplate" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[96]; + ParamDef->init("shapeDescTemplate", TYPE_STRUCT, "ShapeDescTemplate", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[96].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Contains the parameters the application can override on any actor shapes created.", true); + HintTable[2].init("shortDescription", "Contains the parameters the application can override on any actor shapes created", true); + ParamDefTable[96].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=97, longName="shapeDescTemplate.flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[97]; + ParamDef->init("flags", TYPE_STRUCT, "ShapeDescFlags", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=98, longName="shapeDescTemplate.flags.NX_TRIGGER_ON_ENTER" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[98]; + ParamDef->init("NX_TRIGGER_ON_ENTER", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Trigger callback will be called when a shape enters the trigger volume. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Trigger callback will be called when a shape enters the trigger volume.", true); + ParamDefTable[98].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=99, longName="shapeDescTemplate.flags.NX_TRIGGER_ON_LEAVE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[99]; + ParamDef->init("NX_TRIGGER_ON_LEAVE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Trigger callback will be called after a shape leaves the trigger volume. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Trigger callback will be called after a shape leaves the trigger volume.", true); + ParamDefTable[99].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=100, longName="shapeDescTemplate.flags.NX_TRIGGER_ON_STAY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[100]; + ParamDef->init("NX_TRIGGER_ON_STAY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Trigger callback will be called while a shape is intersecting the trigger volume. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Trigger callback will be called while a shape is intersecting the trigger volume.", true); + ParamDefTable[100].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=101, longName="shapeDescTemplate.flags.NX_SF_VISUALIZATION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[101]; + ParamDef->init("NX_SF_VISUALIZATION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enable debug renderer for shapes. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enable debug renderer for shapes", true); + ParamDefTable[101].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=102, longName="shapeDescTemplate.flags.NX_SF_DISABLE_COLLISION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[102]; + ParamDef->init("NX_SF_DISABLE_COLLISION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disable collision detection for shapes (counterpart of NX_AF_DISABLE_COLLISION). This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disable collision detection for shapes (counterpart of NX_AF_DISABLE_COLLISION)", true); + ParamDefTable[102].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=103, longName="shapeDescTemplate.flags.NX_SF_FEATURE_INDICES" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[103]; + ParamDef->init("NX_SF_FEATURE_INDICES", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enable feature indices in contact stream. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enable feature indices in contact stream.", true); + ParamDefTable[103].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=104, longName="shapeDescTemplate.flags.NX_SF_DISABLE_RAYCASTING" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[104]; + ParamDef->init("NX_SF_DISABLE_RAYCASTING", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disable raycasting for shapes. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disable raycasting for shapes", true); + ParamDefTable[104].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=105, longName="shapeDescTemplate.flags.NX_SF_POINT_CONTACT_FORCE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[105]; + ParamDef->init("NX_SF_POINT_CONTACT_FORCE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enable contact force reporting per contact point in contact stream (otherwise we only report force per actor pair). This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enable contact force reporting per contact point in contact stream (otherwise we only report force per actor pair)", true); + ParamDefTable[105].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=106, longName="shapeDescTemplate.flags.NX_SF_FLUID_DRAIN" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[106]; + ParamDef->init("NX_SF_FLUID_DRAIN", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets a shape to be a fluid drain. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets a shape to be a fluid drain.", true); + ParamDefTable[106].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=107, longName="shapeDescTemplate.flags.NX_SF_FLUID_DISABLE_COLLISION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[107]; + ParamDef->init("NX_SF_FLUID_DISABLE_COLLISION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disable collision with fluids. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disable collision with fluids.", true); + ParamDefTable[107].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=108, longName="shapeDescTemplate.flags.NX_SF_FLUID_TWOWAY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[108]; + ParamDef->init("NX_SF_FLUID_TWOWAY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enables the reaction of a shapes actor on fluid collision. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enables the reaction of a shapes actor on fluid collision.", true); + ParamDefTable[108].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=109, longName="shapeDescTemplate.flags.NX_SF_DISABLE_RESPONSE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[109]; + ParamDef->init("NX_SF_DISABLE_RESPONSE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disable collision response for shapes (counterpart of NX_AF_DISABLE_RESPONSE). This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disable collision response for shapes (counterpart of NX_AF_DISABLE_RESPONSE)", true); + ParamDefTable[109].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=110, longName="shapeDescTemplate.flags.NX_SF_DYNAMIC_DYNAMIC_CCD" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[110]; + ParamDef->init("NX_SF_DYNAMIC_DYNAMIC_CCD", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enable dynamic-dynamic CCD for shapes. Used only when CCD is globally enabled and shape have a CCD skeleton. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enable dynamic-dynamic CCD for shapes. Used only when CCD is globally enabled and shape have a CCD skeleton.", true); + ParamDefTable[110].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=111, longName="shapeDescTemplate.flags.NX_SF_DISABLE_SCENE_QUERIES" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[111]; + ParamDef->init("NX_SF_DISABLE_SCENE_QUERIES", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disable participation in ray casts, overlap tests and sweeps. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disable participation in ray casts, overlap tests and sweeps.", true); + ParamDefTable[111].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=112, longName="shapeDescTemplate.flags.NX_SF_CLOTH_DRAIN" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[112]; + ParamDef->init("NX_SF_CLOTH_DRAIN", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets a shape to be a cloth drain. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets a shape to be a cloth drain.", true); + ParamDefTable[112].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=113, longName="shapeDescTemplate.flags.NX_SF_CLOTH_DISABLE_COLLISION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[113]; + ParamDef->init("NX_SF_CLOTH_DISABLE_COLLISION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disable collision with cloths. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disable collision with cloths.", true); + ParamDefTable[113].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=114, longName="shapeDescTemplate.flags.NX_SF_CLOTH_TWOWAY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[114]; + ParamDef->init("NX_SF_CLOTH_TWOWAY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enables the reaction of a shapes actor on cloth collision. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enables the reaction of a shapes actor on cloth collision.", true); + ParamDefTable[114].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=115, longName="shapeDescTemplate.flags.NX_SF_SOFTBODY_DRAIN" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[115]; + ParamDef->init("NX_SF_SOFTBODY_DRAIN", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets a shape to be a soft body drain. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets a shape to be a soft body drain.", true); + ParamDefTable[115].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=116, longName="shapeDescTemplate.flags.NX_SF_SOFTBODY_DISABLE_COLLISION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[116]; + ParamDef->init("NX_SF_SOFTBODY_DISABLE_COLLISION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disable collision with soft bodies. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disable collision with soft bodies.", true); + ParamDefTable[116].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=117, longName="shapeDescTemplate.flags.NX_SF_SOFTBODY_TWOWAY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[117]; + ParamDef->init("NX_SF_SOFTBODY_TWOWAY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enables the reaction of a shape's actor on soft body collision. This flag is applied to all\n NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enables the reaction of a shape's actor on soft body collision.", true); + ParamDefTable[117].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=118, longName="shapeDescTemplate.collisionGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[118]; + ParamDef->init("collisionGroup", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets which collision group shapes are part of.\n Default group is 0. Maximum possible group is 31. Collision groups are sets of shapes which may or may not be set to collision detect with each other; this can be set using NxScene::setGroupCollisionFlag() Sleeping: Does NOT wake the associated actor up automatically. param[in] collisionGroup The collision group for shapes.\n This is applied to all NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets which collision group shapes are part of.", true); + ParamDefTable[118].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=119, longName="shapeDescTemplate.groupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[119]; + ParamDef->init("groupsMask", TYPE_STRUCT, "GroupsMask", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the 128-bit mask used for collision filtering.\n This is applied to all NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets the 128-bit mask used for collision filtering.", true); + ParamDefTable[119].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=120, longName="shapeDescTemplate.groupsMask.useGroupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[120]; + ParamDef->init("useGroupsMask", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not the groupsMask should be used. If so, then this will be applied to all NxShapes\n created to represent this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Whether or not the groupsMask should be used", true); + ParamDefTable[120].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=121, longName="shapeDescTemplate.groupsMask.bits0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[121]; + ParamDef->init("bits0", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits0 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits0 of the groups mask", true); + ParamDefTable[121].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=122, longName="shapeDescTemplate.groupsMask.bits1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[122]; + ParamDef->init("bits1", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits1 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits1 of the groups mask", true); + ParamDefTable[122].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=123, longName="shapeDescTemplate.groupsMask.bits2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[123]; + ParamDef->init("bits2", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits2 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits2 of the groups mask", true); + ParamDefTable[123].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=124, longName="shapeDescTemplate.groupsMask.bits3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[124]; + ParamDef->init("bits3", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits3 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits3 of the groups mask", true); + ParamDefTable[124].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=125, longName="shapeDescTemplate.materialIndex" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[125]; + ParamDef->init("materialIndex", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The material index of a shape.\n This is applied to all NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "The material index of a shape.", true); + ParamDefTable[125].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=126, longName="shapeDescTemplate.density" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[126]; + ParamDef->init("density", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The density of this individual shape when computing mass inertial properties for a rigidbody (unless a valid mass >0.0 is provided). Note that this will only be used if the body has a zero inertia tensor, or if you call NxActor::updateMassFromShapes explicitly.\n This is applied to all NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "The density of an individual shape.", true); + ParamDefTable[126].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=127, longName="shapeDescTemplate.skinWidth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[127]; + ParamDef->init("skinWidth", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Specifies by how much shapes can interpenetrate; if -1 it uses the global default.\n This is applied to all NxShapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Specifies by how much shapes can interpenetrate; if -1 it uses the global default", true); + ParamDefTable[127].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=128, longName="shapeDescTemplate.userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[128]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[128].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional user data pointer.\n This is applied to all NxShapes generated for this destructible's chunks.", true); + HintTable[2].init("shortDescription", "Optional user data pointer", true); + ParamDefTable[128].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=129, longName="shapeDescTemplate.name" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[129]; + ParamDef->init("name", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[129].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional name string for a shape; must be set by the application and must be a persistent pointer.\n This is applied to all NxShapes generated for this destructible's chunks.", true); + HintTable[2].init("shortDescription", "Optional name string for a shape.", true); + ParamDefTable[129].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=130, longName="actorDescTemplate" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[130]; + ParamDef->init("actorDescTemplate", TYPE_STRUCT, "ActorDescTemplate", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[130].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Contains the parameters the application can override on any actors created.", true); + HintTable[2].init("shortDescription", "Contains the parameters the application can override on any actors created", true); + ParamDefTable[130].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=131, longName="actorDescTemplate.flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[131]; + ParamDef->init("flags", TYPE_STRUCT, "ActorDescFlags", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=132, longName="actorDescTemplate.flags.NX_AF_DISABLE_COLLISION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[132]; + ParamDef->init("NX_AF_DISABLE_COLLISION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enable/disable collision detection.\n This flag will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enable/disable collision detection", true); + ParamDefTable[132].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=133, longName="actorDescTemplate.flags.NX_AF_DISABLE_RESPONSE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[133]; + ParamDef->init("NX_AF_DISABLE_RESPONSE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enable/disable collision response (reports contacts but dont use them).\n This flag will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enable/disable collision response (reports contacts but dont use them)", true); + ParamDefTable[133].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=134, longName="actorDescTemplate.flags.NX_AF_LOCK_COM" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[134]; + ParamDef->init("NX_AF_LOCK_COM", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disables COM update when computing inertial properties at creation time.\n This flag will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disables COM update when computing inertial properties at creation time.", true); + ParamDefTable[134].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=135, longName="actorDescTemplate.flags.NX_AF_FLUID_DISABLE_COLLISION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[135]; + ParamDef->init("NX_AF_FLUID_DISABLE_COLLISION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disables COM update when computing inertial properties at creation time.\n This flag will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disables COM update when computing inertial properties at creation time.", true); + ParamDefTable[135].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=136, longName="actorDescTemplate.flags.NX_AF_CONTACT_MODIFICATION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[136]; + ParamDef->init("NX_AF_CONTACT_MODIFICATION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Turn on contact modification callback for the actor.\n This flag will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Turn on contact modification callback for the actor.", true); + ParamDefTable[136].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=137, longName="actorDescTemplate.flags.NX_AF_FORCE_CONE_FRICTION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[137]; + ParamDef->init("NX_AF_FORCE_CONE_FRICTION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Force cone friction to be used for this actor.\n This flag will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Force cone friction to be used for this actor.", true); + ParamDefTable[137].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=138, longName="actorDescTemplate.flags.NX_AF_USER_ACTOR_PAIR_FILTERING" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[138]; + ParamDef->init("NX_AF_USER_ACTOR_PAIR_FILTERING", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enable/disable custom contact filtering.\n This flag will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enable/disable custom contact filtering.", true); + ParamDefTable[138].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=139, longName="actorDescTemplate.density" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[139]; + ParamDef->init("density", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Density to be applied to the whole actor. If the body descriptor contains a zero mass but the actor descriptor contains a non-zero density, we compute a new mass automatically from the density and a shapes.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Density to be applied to the whole actor.", true); + ParamDefTable[139].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=140, longName="actorDescTemplate.actorCollisionGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[140]; + ParamDef->init("actorCollisionGroup", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets which NxActorGroup an actor is part of.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets which NxActorGroup an actor is part of", true); + ParamDefTable[140].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=141, longName="actorDescTemplate.dominanceGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[141]; + ParamDef->init("dominanceGroup", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Dominance group for an actor.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Dominance group for an actor.", true); + ParamDefTable[141].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=142, longName="actorDescTemplate.contactReportFlags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[142]; + ParamDef->init("contactReportFlags", TYPE_STRUCT, "ContactPairFlag", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Combination of ContactPairFlag flags.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Combination of ContactPairFlag flags", true); + ParamDefTable[142].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=143, longName="actorDescTemplate.contactReportFlags.NX_IGNORE_PAIR" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[143]; + ParamDef->init("NX_IGNORE_PAIR", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disable contact generation for this pair. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "Disable contact generation for this pair", true); + ParamDefTable[143].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=144, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_START_TOUCH" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[144]; + ParamDef->init("NX_NOTIFY_ON_START_TOUCH", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Pair callback will be called when the pair starts to be in contact. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "Pair callback will be called when the pair starts to be in contact", true); + ParamDefTable[144].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=145, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_END_TOUCH" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[145]; + ParamDef->init("NX_NOTIFY_ON_END_TOUCH", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Pair callback will be called when the pair stops to be in contact. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "Pair callback will be called when the pair stops to be in contact", true); + ParamDefTable[145].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=146, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_TOUCH" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[146]; + ParamDef->init("NX_NOTIFY_ON_TOUCH", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Pair callback will keep getting called while the pair is in contact. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "Pair callback will keep getting called while the pair is in contact", true); + ParamDefTable[146].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=147, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_IMPACT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[147]; + ParamDef->init("NX_NOTIFY_ON_IMPACT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "[Not yet implemented] pair callback will be called when it may be appropriate for the pair to play an impact sound. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "[Not yet implemented] pair callback will be called when it may be appropriate for the pair to play an impact sound", true); + ParamDefTable[147].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=148, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_ROLL" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[148]; + ParamDef->init("NX_NOTIFY_ON_ROLL", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "[Not yet implemented] pair callback will be called when the pair is in contact and rolling. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "[Not yet implemented] pair callback will be called when the pair is in contact and rolling.", true); + ParamDefTable[148].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=149, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_SLIDE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[149]; + ParamDef->init("NX_NOTIFY_ON_SLIDE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "[Not yet implemented] pair callback will be called when the pair is in contact and sliding (and not rolling). See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "[Not yet implemented] pair callback will be called when the pair is in contact and sliding (and not rolling).", true); + ParamDefTable[149].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=150, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_FORCES" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[150]; + ParamDef->init("NX_NOTIFY_FORCES", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The (summed total) friction force and normal force will be given in the NxContactPair variable in the contact report. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "The (summed total) friction force and normal force will be given in the NxContactPair variable in the contact report.", true); + ParamDefTable[150].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=151, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[151]; + ParamDef->init("NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Pair callback will be called when the contact force between two actors falls below the actor-defined force thresholds. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "Pair callback will be called when the contact force between two actors falls below the actor-defined force thresholds", true); + ParamDefTable[151].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=152, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_END_TOUCH_FORCE_THRESHOLD" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[152]; + ParamDef->init("NX_NOTIFY_ON_END_TOUCH_FORCE_THRESHOLD", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Pair callback will be called when the contact force between two actors falls below the actor-defined force thresholds. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "Pair callback will be called when the contact force between two actors falls below the actor-defined force thresholds", true); + ParamDefTable[152].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=153, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_TOUCH_FORCE_THRESHOLD" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[153]; + ParamDef->init("NX_NOTIFY_ON_TOUCH_FORCE_THRESHOLD", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Pair callback will keep getting called while the contact force between two actors exceeds one of the actor-defined force thresholds. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "Pair callback will keep getting called while the contact force between two actors exceeds one of the actor-defined force thresholds", true); + ParamDefTable[153].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=154, longName="actorDescTemplate.contactReportFlags.NX_NOTIFY_CONTACT_MODIFICATION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[154]; + ParamDef->init("NX_NOTIFY_CONTACT_MODIFICATION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Generate a callback for all associated contact constraints, making it possible to edit the constraint. This flag is not included in NX_NOTIFY_ALL for performance reasons. see NxUserContactModify. See the PhysX documentation for more about contact reporting.", true); + HintTable[1].init("shortDescription", "Generate a callback for all associated contact constraints, making it possible to edit the constraint. This flag is not included in NX_NOTIFY_ALL for performance reasons. see NxUserContactModify.", true); + ParamDefTable[154].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=155, longName="actorDescTemplate.forceFieldMaterial" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[155]; + ParamDef->init("forceFieldMaterial", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Force Field Material Index, index != 0 has to be created.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Force Field Material Index", true); + ParamDefTable[155].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=156, longName="actorDescTemplate.userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[156]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[156].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional user data pointer.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[2].init("shortDescription", "Optional user data pointer", true); + ParamDefTable[156].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=157, longName="actorDescTemplate.name" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[157]; + ParamDef->init("name", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[157].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional name string for a shape; must be set by the application and must be a persistent pointer.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[2].init("shortDescription", "Optional name string for a shape; must be set by the application and must be a persistent pointer.", true); + ParamDefTable[157].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=158, longName="actorDescTemplate.compartment" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[158]; + ParamDef->init("compartment", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[158].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional compartment pointer; must be set by the application.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[2].init("shortDescription", "Optional compartment pointer", true); + ParamDefTable[158].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=159, longName="bodyDescTemplate" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[159]; + ParamDef->init("bodyDescTemplate", TYPE_STRUCT, "BodyDescTemplate", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[159].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Contains the parameterse that the application can override for the body descriptor of rigid body actors created.", true); + HintTable[2].init("shortDescription", "Contains the parameterse that the application can override for the body descriptor of rigid body actors created", true); + ParamDefTable[159].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=160, longName="bodyDescTemplate.flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[160]; + ParamDef->init("flags", TYPE_STRUCT, "BodyDescFlags", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Combination of body descriptor flags.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Combination of body descriptor flags", true); + ParamDefTable[160].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=161, longName="bodyDescTemplate.flags.NX_BF_DISABLE_GRAVITY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[161]; + ParamDef->init("NX_BF_DISABLE_GRAVITY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Set if gravity should not be applied on this body.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Set if gravity should not be applied on this body", true); + ParamDefTable[161].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=162, longName="bodyDescTemplate.flags.NX_BF_FILTER_SLEEP_VEL" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[162]; + ParamDef->init("NX_BF_FILTER_SLEEP_VEL", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Filter velocities used keep body awake. The filter reduces rapid oscillations and transient spikes.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Filter velocities used keep body awake. The filter reduces rapid oscillations and transient spikes", true); + ParamDefTable[162].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=163, longName="bodyDescTemplate.flags.NX_BF_ENERGY_SLEEP_TEST" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[163]; + ParamDef->init("NX_BF_ENERGY_SLEEP_TEST", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enables energy-based sleeping algorithm.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enables energy-based sleeping algorithm", true); + ParamDefTable[163].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=164, longName="bodyDescTemplate.flags.NX_BF_VISUALIZATION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[164]; + ParamDef->init("NX_BF_VISUALIZATION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enables debug visualization for this body.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enables debug visualization for this body", true); + ParamDefTable[164].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=165, longName="bodyDescTemplate.wakeUpCounter" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[165]; + ParamDef->init("wakeUpCounter", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The bodys initial wake up counter.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "The bodys initial wake up counter", true); + ParamDefTable[165].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=166, longName="bodyDescTemplate.linearDamping" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[166]; + ParamDef->init("linearDamping", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Linear damping applied to the body.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Linear damping applied to the body", true); + ParamDefTable[166].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=167, longName="bodyDescTemplate.angularDamping" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[167]; + ParamDef->init("angularDamping", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Angular damping applied to the body.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Angular damping applied to the body", true); + ParamDefTable[167].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=168, longName="bodyDescTemplate.maxAngularVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[168]; + ParamDef->init("maxAngularVelocity", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Maximum allowed angular velocity.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Maximum allowed angular velocity", true); + ParamDefTable[168].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=169, longName="bodyDescTemplate.CCDMotionThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[169]; + ParamDef->init("CCDMotionThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "When CCD is globally enabled, it is still not performed if the motion distance of all points on the body is below this threshold.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Distance threshold for CCD", true); + ParamDefTable[169].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=170, longName="bodyDescTemplate.sleepLinearVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[170]; + ParamDef->init("sleepLinearVelocity", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Maximum linear velocity at which body can go to sleep.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Maximum linear velocity at which body can go to sleep", true); + ParamDefTable[170].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=171, longName="bodyDescTemplate.sleepAngularVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[171]; + ParamDef->init("sleepAngularVelocity", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Maximum angular velocity at which body can go to sleep.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Maximum angular velocity at which body can go to sleep", true); + ParamDefTable[171].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=172, longName="bodyDescTemplate.solverIterationCount" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[172]; + ParamDef->init("solverIterationCount", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of solver iterations performed when processing joint/contacts connected to this body.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Number of solver iterations performed when processing joint/contacts connected to this body", true); + ParamDefTable[172].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=173, longName="bodyDescTemplate.sleepEnergyThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[173]; + ParamDef->init("sleepEnergyThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Threshold for the energy-based sleeping algorithm. Only used when the NX_BF_ENERGY_SLEEP_TEST flag is set.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Threshold for the energy-based sleeping algorithm. Only used when the NX_BF_ENERGY_SLEEP_TEST flag is set", true); + ParamDefTable[173].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=174, longName="bodyDescTemplate.sleepDamping" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[174]; + ParamDef->init("sleepDamping", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Damping factor for bodies that are about to sleep.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Damping factor for bodies that are about to sleep", true); + ParamDefTable[174].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=175, longName="bodyDescTemplate.contactReportThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[175]; + ParamDef->init("contactReportThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The force threshold for contact reports.\n This will be applied to all NxActors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "The force threshold for contact reports", true); + ParamDefTable[175].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=176, longName="p3ShapeDescTemplate" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[176]; + ParamDef->init("p3ShapeDescTemplate", TYPE_STRUCT, "P3ShapeDescTemplate", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[176].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Contains the parameters the application can override on any actor shapes created.", true); + HintTable[2].init("shortDescription", "Contains the parameters the application can override on any actor shapes created", true); + ParamDefTable[176].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=177, longName="p3ShapeDescTemplate.flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[177]; + ParamDef->init("flags", TYPE_STRUCT, "P3ShapeFlags", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=178, longName="p3ShapeDescTemplate.flags.eSIMULATION_SHAPE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[178]; + ParamDef->init("eSIMULATION_SHAPE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "The shape will partake in collision in the physical simulation.", true); + ParamDefTable[178].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=179, longName="p3ShapeDescTemplate.flags.eSCENE_QUERY_SHAPE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[179]; + ParamDef->init("eSCENE_QUERY_SHAPE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "The shape will partake in scene queries (ray casts, overlap tests, sweeps, ...). ", true); + ParamDefTable[179].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=180, longName="p3ShapeDescTemplate.flags.eTRIGGER_SHAPE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[180]; + ParamDef->init("eTRIGGER_SHAPE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The shape is a trigger which can send reports whenever other shapes enter/leave its volume.\n\nNote:\nTriangle meshes and heightfields can not be triggers. Shape creation will fail in these cases.\nShapes marked as triggers do not collide with other objects. If an object should act both as a trigger shape and a collision shape then create a rigid body with two shapes, one being a trigger shape and the other a collision shape.\n", true); + HintTable[1].init("shortDescription", "The shape is a trigger which can send reports whenever other shapes enter/leave its volume. ", true); + ParamDefTable[180].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=181, longName="p3ShapeDescTemplate.flags.eVISUALIZATION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[181]; + ParamDef->init("eVISUALIZATION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Enable debug renderer for this shape", true); + ParamDefTable[181].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=182, longName="p3ShapeDescTemplate.flags.ePARTICLE_DRAIN" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[182]; + ParamDef->init("ePARTICLE_DRAIN", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Sets the shape to be a particle drain", true); + ParamDefTable[182].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=183, longName="p3ShapeDescTemplate.flags.eDEFORMABLE_DRAIN" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[183]; + ParamDef->init("eDEFORMABLE_DRAIN", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Sets the shape to be a deformable drain", true); + ParamDefTable[183].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=184, longName="p3ShapeDescTemplate.simulationFilterData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[184]; + ParamDef->init("simulationFilterData", TYPE_STRUCT, "P3FilterData", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the user definable collision filter data.\n This is applied to all shapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets the user definable collision filter data", true); + ParamDefTable[184].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=185, longName="p3ShapeDescTemplate.simulationFilterData.word0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[185]; + ParamDef->init("word0", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "word0 of the filter data", true); + ParamDefTable[185].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=186, longName="p3ShapeDescTemplate.simulationFilterData.word1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[186]; + ParamDef->init("word1", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "word1 of the filter data", true); + ParamDefTable[186].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=187, longName="p3ShapeDescTemplate.simulationFilterData.word2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[187]; + ParamDef->init("word2", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "word2 of the filter data", true); + ParamDefTable[187].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=188, longName="p3ShapeDescTemplate.simulationFilterData.word3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[188]; + ParamDef->init("word3", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "word3 of the filter data", true); + ParamDefTable[188].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=189, longName="p3ShapeDescTemplate.queryFilterData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[189]; + ParamDef->init("queryFilterData", TYPE_STRUCT, "P3FilterData", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the user definable query filter data.\n This is applied to all shapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets the user definable query filter data", true); + ParamDefTable[189].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=190, longName="p3ShapeDescTemplate.queryFilterData.word0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[190]; + ParamDef->init("word0", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "word0 of the filter data", true); + ParamDefTable[190].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=191, longName="p3ShapeDescTemplate.queryFilterData.word1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[191]; + ParamDef->init("word1", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "word1 of the filter data", true); + ParamDefTable[191].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=192, longName="p3ShapeDescTemplate.queryFilterData.word2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[192]; + ParamDef->init("word2", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "word2 of the filter data", true); + ParamDefTable[192].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=193, longName="p3ShapeDescTemplate.queryFilterData.word3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[193]; + ParamDef->init("word3", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "word3 of the filter data", true); + ParamDefTable[193].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=194, longName="p3ShapeDescTemplate.material" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[194]; + ParamDef->init("material", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A PxMaterial pointer for the shape.\n This is applied to all shapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "A PxMaterial pointer for the shape", true); + ParamDefTable[194].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=195, longName="p3ShapeDescTemplate.contactOffset" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[195]; + ParamDef->init("contactOffset", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the contact offset; if -1 it uses the global default.\n This is applied to all shapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets the contact offset", true); + ParamDefTable[195].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=196, longName="p3ShapeDescTemplate.restOffset" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[196]; + ParamDef->init("restOffset", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the rest offset; if -1 it uses the global default.\n This is applied to all shapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets the rest offset", true); + ParamDefTable[196].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=197, longName="p3ShapeDescTemplate.userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[197]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[197].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional user data pointer.\n This is applied to all shapes generated for this destructible's chunks.", true); + HintTable[2].init("shortDescription", "Optional user data pointer", true); + ParamDefTable[197].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=198, longName="p3ShapeDescTemplate.name" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[198]; + ParamDef->init("name", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[198].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional name string for a shape; must be set by the application and must be a persistent pointer.\n This is applied to all shapes generated for this destructible's chunks.", true); + HintTable[2].init("shortDescription", "Optional name string for a shape.", true); + ParamDefTable[198].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=199, longName="p3ActorDescTemplate" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[199]; + ParamDef->init("p3ActorDescTemplate", TYPE_STRUCT, "P3ActorDescTemplate", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[199].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Contains the parameters the application can override on any actors created.", true); + HintTable[2].init("shortDescription", "Contains the parameters the application can override on any actors created", true); + ParamDefTable[199].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=200, longName="p3ActorDescTemplate.flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[200]; + ParamDef->init("flags", TYPE_STRUCT, "P3ActorFlags", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=201, longName="p3ActorDescTemplate.flags.eVISUALIZATION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[201]; + ParamDef->init("eVISUALIZATION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enable debug renderer for this actor.\n This flag will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enable debug renderer for this actor", true); + ParamDefTable[201].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=202, longName="p3ActorDescTemplate.flags.eDISABLE_GRAVITY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[202]; + ParamDef->init("eDISABLE_GRAVITY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Disables scene gravity for this actor.\n This flag will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Disables scene gravity for this actor", true); + ParamDefTable[202].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=203, longName="p3ActorDescTemplate.flags.eSEND_SLEEP_NOTIFIES" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[203]; + ParamDef->init("eSEND_SLEEP_NOTIFIES", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enables the sending of PxSimulationEventCallback::onWake() and PxSimulationEventCallback::onSleep() notify events.\n This flag will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enables the sending of PxSimulationEventCallback::onWake() and PxSimulationEventCallback::onSleep() notify events", true); + ParamDefTable[203].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=204, longName="p3ActorDescTemplate.dominanceGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[204]; + ParamDef->init("dominanceGroup", TYPE_U8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Assigns dynamic actors a dominance group identifier.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Assigns dynamic actors a dominance group identifier.", true); + ParamDefTable[204].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=205, longName="p3ActorDescTemplate.ownerClient" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[205]; + ParamDef->init("ownerClient", TYPE_U8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the owner client of an actor.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets the owner client of an actor.", true); + ParamDefTable[205].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=206, longName="p3ActorDescTemplate.clientBehaviorBits" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[206]; + ParamDef->init("clientBehaviorBits", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Changes the behavior bits initially specified with PxActorDesc::clientBehaviorBits.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Changes the behavior bits initially specified with PxActorDesc::clientBehaviorBits.", true); + ParamDefTable[206].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=207, longName="p3ActorDescTemplate.contactReportFlags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[207]; + ParamDef->init("contactReportFlags", TYPE_STRUCT, "P3PairFlag", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Combination of P3PairFlag flags.\n This will be applied to all shapes generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Combination of P3PairFlag flags", true); + ParamDefTable[207].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=208, longName="p3ActorDescTemplate.contactReportFlags.eSOLVE_CONTACT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[208]; + ParamDef->init("eSOLVE_CONTACT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Process the contacts of this collision pair in the dynamics solver.\n\nNote: Only takes effect if the colliding actors are rigid bodies.\n", true); + HintTable[1].init("shortDescription", "Process the contacts of this collision pair in the dynamics solver. ", true); + ParamDefTable[208].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=209, longName="p3ActorDescTemplate.contactReportFlags.eMODIFY_CONTACTS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[209]; + ParamDef->init("eMODIFY_CONTACTS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Call contact modification callback for this collision pair.\n\nNote: Only takes effect if the colliding actors are rigid bodies.\n", true); + HintTable[1].init("shortDescription", "Call contact modification callback for this collision pair. ", true); + ParamDefTable[209].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=210, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_TOUCH_FOUND" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[210]; + ParamDef->init("eNOTIFY_TOUCH_FOUND", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Call contact report callback or trigger callback when this collision pair starts to be in contact.\nIf one of the two collision objects is a trigger shape (see PxShapeFlag::eTRIGGER_SHAPE) then the trigger callback will get called as soon as the other object enters the trigger volume. If none of the two collision objects is a trigger shape then the contact report callback will get called when the actors of this collision pair start to be in contact.\n\nNote: Only takes effect if the colliding actors are rigid bodies.\n", true); + HintTable[1].init("shortDescription", "Call contact report callback or trigger callback when this collision pair starts to be in contact", true); + ParamDefTable[210].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=211, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_TOUCH_PERSISTS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[211]; + ParamDef->init("eNOTIFY_TOUCH_PERSISTS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Process the contacts of this collision pair in the dynamics solver.\n\nNote: Only takes effect if the colliding actors are rigid bodies.\n", true); + HintTable[1].init("shortDescription", "Call contact report callback or trigger callback while this collision pair is in contact", true); + ParamDefTable[211].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=212, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_TOUCH_LOST" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[212]; + ParamDef->init("eNOTIFY_TOUCH_LOST", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Call contact report callback or trigger callback when this collision pair stops to be in contact.\nIf one of the two collision objects is a trigger shape (see PxShapeFlag::eTRIGGER_SHAPE) then the trigger callback will get called as soon as the other object leaves the trigger volume. If none of the two collision objects is a trigger shape then the contact report callback will get called when the actors of this collision pair stop to be in contact.\n\nNote: Only takes effect if the colliding actors are rigid bodies.\n", true); + HintTable[1].init("shortDescription", " Call contact report callback or trigger callback when this collision pair stops to be in contact.", true); + ParamDefTable[212].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=213, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_FOUND" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[213]; + ParamDef->init("eNOTIFY_THRESHOLD_FORCE_FOUND", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Call contact report callback when the contact force between the actors of this collision pair exceeds one of the actor-defined force thresholds.\n\nNote: Only takes effect if the colliding actors are rigid bodies\n", true); + HintTable[1].init("shortDescription", "Call contact report callback when the contact force between the actors of this collision pair exceeds one of the actor-defined force thresholds.", true); + ParamDefTable[213].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=214, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_PERSISTS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[214]; + ParamDef->init("eNOTIFY_THRESHOLD_FORCE_PERSISTS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Call contact report callback when the contact force between the actors of this collision pair continues to exceed one of the actor-defined force thresholds.\n\nNote: Only takes effect if the colliding actors are rigid bodies.\n", true); + HintTable[1].init("shortDescription", "Call contact report callback when the contact force between the actors of this collision pair continues to exceed one of the actor-defined force thresholds", true); + ParamDefTable[214].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=215, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_LOST" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[215]; + ParamDef->init("eNOTIFY_THRESHOLD_FORCE_LOST", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Call contact report callback when the contact force between the actors of this collision pair falls below one of the actor-defined force thresholds (includes the case where this collision pair stops being in contact).\n\nNote: Only takes effect if the colliding actors are rigid bodies\n", true); + HintTable[1].init("shortDescription", "Call contact report callback when the contact force between the actors of this collision pair falls below one of the actor-defined force thresholds (includes the case where this collision pair stops being in contact).", true); + ParamDefTable[215].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=216, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_POINTS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[216]; + ParamDef->init("eNOTIFY_CONTACT_POINTS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Provide contact points in contact reports for this collision pair.\n\nNote: Only takes effect if the colliding actors are rigid bodies.\n", true); + HintTable[1].init("shortDescription", "Provide contact points in contact reports for this collision pair.", true); + ParamDefTable[216].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=217, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_FORCES" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[217]; + ParamDef->init("eNOTIFY_CONTACT_FORCES", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Provide the (summed total) friction force and normal force in contact reports for this collision pair (see PxContactPair).\n\nNote: Only takes effect if the colliding actors are rigid bodies\n", true); + HintTable[1].init("shortDescription", "Provide the (summed total) friction force and normal force in contact reports for this collision pair (see PxContactPair).", true); + ParamDefTable[217].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=218, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_FORCE_PER_POINT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[218]; + ParamDef->init("eNOTIFY_CONTACT_FORCE_PER_POINT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Provide contact forces per contact point in contact reports for this collision pair.\n\nNote: Only takes effect if the colliding actors are rigid bodies.\n", true); + HintTable[1].init("shortDescription", "Provide contact forces per contact point in contact reports for this collision pair.", true); + ParamDefTable[218].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=219, longName="p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_FEATURE_INDICES_PER_POINT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[219]; + ParamDef->init("eNOTIFY_CONTACT_FEATURE_INDICES_PER_POINT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Provide feature indices per contact point in contact reports for this collision pair.\n\nNote: Only takes effect if the colliding actors are rigid bodies.\n", true); + HintTable[1].init("shortDescription", "Provide feature indices per contact point in contact reports for this collision pair.", true); + ParamDefTable[219].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=220, longName="p3ActorDescTemplate.contactReportFlags.eDETECT_CCD_CONTACT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[220]; + ParamDef->init("eDETECT_CCD_CONTACT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "This flag is used to indicate whether this pair generates CCD contacts. \n\nThe contacts will only be responded to if eSOLVE_CONTACT is enabled on this pair.\nThe scene must have PxSceneFlag::eENABLE_CCD enabled to use this feature.\nNon-static bodies of the pair should have PxRigidBodyFlag::eENABLE_CCD specified for this feature to work correctly.\nThis flag is not supported with trigger shapes. However, CCD trigger events can be emulated using non-trigger shapes \nand requesting eNOTIFY_TOUCH_FOUND and eNOTIFY_TOUCH_LOST and not raising eSOLVE_CONTACT on the pair.\n", true); + HintTable[1].init("shortDescription", "This flag is used to indicate whether this pair generates CCD contacts.", true); + ParamDefTable[220].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=221, longName="p3ActorDescTemplate.contactReportFlags.eCONTACT_DEFAULT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[221]; + ParamDef->init("eCONTACT_DEFAULT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Provided default flag to do simple contact processing for this collision pair.", true); + ParamDefTable[221].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=222, longName="p3ActorDescTemplate.contactReportFlags.eTRIGGER_DEFAULT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[222]; + ParamDef->init("eTRIGGER_DEFAULT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Provided default flag to get commonly used trigger behavior for this collision pair.", true); + ParamDefTable[222].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=223, longName="p3ActorDescTemplate.userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[223]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[223].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional user data pointer.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[2].init("shortDescription", "Optional user data pointer", true); + ParamDefTable[223].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=224, longName="p3ActorDescTemplate.name" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[224]; + ParamDef->init("name", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[224].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional name string for a shape; must be set by the application and must be a persistent pointer.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[2].init("shortDescription", "Optional name string for a shape; must be set by the application and must be a persistent pointer.", true); + ParamDefTable[224].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=225, longName="p3BodyDescTemplate" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[225]; + ParamDef->init("p3BodyDescTemplate", TYPE_STRUCT, "P3BodyDescTemplate", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[225].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Contains the parameterse that the application can override for the body descriptor of rigid body actors created.", true); + HintTable[2].init("shortDescription", "Contains the parameterse that the application can override for the body descriptor of rigid body actors created", true); + ParamDefTable[225].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=226, longName="p3BodyDescTemplate.density" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[226]; + ParamDef->init("density", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The density of the body. Used to compute the mass of the body. If the body descriptor contains a zero mass but the actor descriptor contains a non-zero density, we compute a new mass automatically from the density and a shapes.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "The density of the body. Used to compute the mass of the body.", true); + ParamDefTable[226].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=227, longName="p3BodyDescTemplate.flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[227]; + ParamDef->init("flags", TYPE_STRUCT, "P3BodyDescFlags", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Combination of body descriptor flags.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Combination of body descriptor flags", true); + ParamDefTable[227].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=228, longName="p3BodyDescTemplate.flags.eKINEMATIC" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[228]; + ParamDef->init("eKINEMATIC", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Kinematic actors are special dynamic actors that are not influenced by forces (such as gravity), and have no momentum. They are considered to have infinite mass and can be moved around the world using the moveKinematic() method. They will push regular dynamic actors out of the way. Kinematics will not collide with static or other kinematic objects.\nKinematic actors are great for moving platforms or characters, where direct motion control is desired.\nYou can not connect Reduced joints to kinematic actors. Lagrange joints work ok if the platform is moving with a relatively low, uniform velocity.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Enables kinematic mode for the actor", true); + ParamDefTable[228].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=229, longName="p3BodyDescTemplate.flags.eENABLE_CCD" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[229]; + ParamDef->init("eENABLE_CCD", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Enables swept integration for the actor.\n If this flag is raised and swept integration is enabled on the scene, then this body will be simulated by the CCD system to ensure that collisions are not missed due to \n high-speed motion. Note, individual shape pairs still need to enable PxPairFlag::eDETECT_CCD_CONTACT in the collision filtering to enable the CCD to respond to \n individual interactions.", true); + HintTable[1].init("shortDescription", "Enables swept integration for the actor.", true); + ParamDefTable[229].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=230, longName="p3BodyDescTemplate.sleepThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[230]; + ParamDef->init("sleepThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the mass-normalized kinetic energy threshold below which an actor may go to sleep.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets the mass-normalized kinetic energy threshold below which an actor may go to sleep.", true); + ParamDefTable[230].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=231, longName="p3BodyDescTemplate.wakeUpCounter" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[231]; + ParamDef->init("wakeUpCounter", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The bodys initial wake up counter.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "The bodys initial wake up counter", true); + ParamDefTable[231].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=232, longName="p3BodyDescTemplate.linearDamping" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[232]; + ParamDef->init("linearDamping", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Linear damping applied to the body.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Linear damping applied to the body", true); + ParamDefTable[232].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=233, longName="p3BodyDescTemplate.angularDamping" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[233]; + ParamDef->init("angularDamping", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the angular damping coefficient.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Sets the angular damping coefficient", true); + ParamDefTable[233].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=234, longName="p3BodyDescTemplate.maxAngularVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[234]; + ParamDef->init("maxAngularVelocity", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Maximum allowed angular velocity.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Maximum allowed angular velocity", true); + ParamDefTable[234].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=235, longName="p3BodyDescTemplate.solverIterationCount" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[235]; + ParamDef->init("solverIterationCount", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the solver iteration counts for the body.\nThe solver iteration count determines how accurately joints and contacts are resolved. If you are having trouble with jointed bodies oscillating and behaving erratically, then setting a higher position iteration count may improve their stability.\nIf intersecting bodies are being depenetrated too violently, increase the number of velocity iterations.", true); + HintTable[1].init("shortDescription", "Sets the solver iteration counts for the body", true); + ParamDefTable[235].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=236, longName="p3BodyDescTemplate.velocityIterationCount" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[236]; + ParamDef->init("velocityIterationCount", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Sets the velocity solver iteration counts for the body.\nThe solver iteration count determines how accurately joints and contacts are resolved. If you are having trouble with jointed bodies oscillating and behaving erratically, then setting a higher position iteration count may improve their stability.\nIf intersecting bodies are being depenetrated too violently, increase the number of velocity iterations.", true); + HintTable[1].init("shortDescription", "Sets the velocity solver iteration counts for the body", true); + ParamDefTable[236].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=237, longName="p3BodyDescTemplate.contactReportThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[237]; + ParamDef->init("contactReportThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The force threshold for contact reports.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "The force threshold for contact reports", true); + ParamDefTable[237].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=238, longName="p3BodyDescTemplate.sleepLinearVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[238]; + ParamDef->init("sleepLinearVelocity", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Maximum linear velocity at which body can go to sleep.\n This will be applied to all actors generated for this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Maximum linear velocity at which body can go to sleep", true); + ParamDefTable[238].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=239, longName="structureSettings" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[239]; + ParamDef->init("structureSettings", TYPE_STRUCT, "StructureSettings", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[239].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Contains parameters that affect structure-wide settings.", true); + HintTable[2].init("shortDescription", "Contains parameters that affect structure-wide settings", true); + ParamDefTable[239].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=240, longName="structureSettings.useStressSolver" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[240]; + ParamDef->init("useStressSolver", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Determines whether to invoke the use of the stress solver. The stress solver is a self-checking mechanism\nemployed within the structure, with the purpose of detecting and breaking off overly-strained links to masses\nof chunks. Its behavior can be tweaked by customizing the parameters stressSolverTimeDelay and stressSolverMassThreshold.\n", true); + HintTable[1].init("shortDescription", "If true, the structure containing this actor will use the stress solver.", true); + ParamDefTable[240].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=241, longName="structureSettings.stressSolverTimeDelay" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[241]; + ParamDef->init("stressSolverTimeDelay", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Determines the amount of time to run down until an identified overly-strained link breaks. From the time the stress\nsolver qualifies a link as being overly-strained, this value will be used to count down to the actual breaking-off\nevent being executed. This should always be some positive value.\n", true); + HintTable[1].init("shortDescription", "The structure containing this actor will use the minimum stressSolverTimeDelay of all actors in the structure.", true); + ParamDefTable[241].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=242, longName="structureSettings.stressSolverMassThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[242]; + ParamDef->init("stressSolverMassThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Determines the minimum threshold mass to meet before an indentified overly-strained link breaks. This mass threshold\nis part of the condition that the stress solver uses to qualify whether a link is overly-strained. The accumulated sum\nof the chunk masses that the link is supporting will be used against this value. This should always be some positive value.\n", true); + HintTable[1].init("shortDescription", "The structure containing this actor will use the minimum stressSolverMassThreshold of all actors in the structure.", true); + ParamDefTable[242].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=243, longName="defaultBehaviorGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[243]; + ParamDef->init("defaultBehaviorGroup", TYPE_STRUCT, "BehaviorGroup", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The default behavior group referenced by chunks. Each chunk references a behavior group for chunk-specific reactions.", true); + HintTable[1].init("shortDescription", "The default behavior group referenced by chunks", true); + ParamDefTable[243].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=244, longName="defaultBehaviorGroup.name" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[244]; + ParamDef->init("name", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Name of behavior group, eg Concrete or Glass.", true); + HintTable[1].init("shortDescription", "Name of behavior group", true); + ParamDefTable[244].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=245, longName="defaultBehaviorGroup.damageThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[245]; + ParamDef->init("damageThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The damage amount which will cause a chunk to fracture (break free) from the destructible.\n This is obtained from the damage value passed into the DestructibleActor::applyDamage,\n or DestructibleActor::applyRadiusDamage, or via impact (see 'forceToDamage', below).", true); + HintTable[1].init("shortDescription", "The damage amount which will cause a chunk to fracture (break free) from the destructible.", true); + ParamDefTable[245].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=246, longName="defaultBehaviorGroup.damageToRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[246]; + ParamDef->init("damageToRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Controls the distance into the destructible to propagate damage. The damage applied to the chunk\n is multiplied by damageToRadius, to get the propagation distance. All chunks within the radius\n will have damage applied to them. The damage applied to each chunk varies with distance to the damage\n application position. Full damage is taken at zero distance, and zero damage at the damage radius.\n NOTE: This parameter is deprecated for point and radius damage. It will be used for those types of damage if legacy damage\n behavior is enabled with ModuleDestructible::setUseLegacyDamageRadiusSpread. Otherwise, the new parameters\n damageSpread.minimumRadius, damageSpread.radiusMultiplier, and damageSpread.falloffExponent are used. For impact damage, this parameter\n will continue to be used, however the radius will no longer scale with object size. The radius will continue\n to scale with the damage as a fraction of damageThreshold, however. If legacy damage behavior is used, this parameter\n will behave as before with respect to impact damage as well (scaling with object size).", true); + HintTable[1].init("shortDescription", "Controls the distance into the destructible to propagate damage.", true); + ParamDefTable[246].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=247, longName="defaultBehaviorGroup.damageSpread" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[247]; + ParamDef->init("damageSpread", TYPE_STRUCT, "DamageSpreadFunction", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes the radius and damage envelope function for damage applied to the destructible.", true); + HintTable[1].init("shortDescription", "Describes the radius and damage envelope function for damage applied to the destructible.", true); + ParamDefTable[247].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=248, longName="defaultBehaviorGroup.damageSpread.minimumRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[248]; + ParamDef->init("minimumRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum radius of damage spread when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "The minimum radius of damage spread when damage is applied.", true); + ParamDefTable[248].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=249, longName="defaultBehaviorGroup.damageSpread.radiusMultiplier" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[249]; + ParamDef->init("radiusMultiplier", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A scale to apply to the input damage radius when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "A scale to apply to the input damage radius when damage is applied.", true); + ParamDefTable[249].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=250, longName="defaultBehaviorGroup.damageSpread.falloffExponent" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[250]; + ParamDef->init("falloffExponent", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How damage varies between the minimum radius and the calculated damage radius. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.\n Within the minimumRadius, the full damage is applied to chunks. Past the minimumRadius, the formla for damage is:\n damage = (input damage) * ((radius - distance)/(radius - minimumRadius))^falloffExponent.\n Note: falloffExponent = 0.0 gives no falloff, so that damage = (input damage) over the entire range [0, radius).\n falloffExponent = 1.0 gives linear falloff.", true); + HintTable[1].init("shortDescription", "How damage varies between the minimum radius and the calculated damage radius.", true); + ParamDefTable[250].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=251, longName="defaultBehaviorGroup.damageColorSpread" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[251]; + ParamDef->init("damageColorSpread", TYPE_STRUCT, "DamageSpreadFunction", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes the radius and damage envelope function for color channel damage modification applied to the destructible.", true); + HintTable[1].init("shortDescription", "Describes the radius and damage envelope function for color channel damage modification applied to the destructible.", true); + ParamDefTable[251].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=252, longName="defaultBehaviorGroup.damageColorSpread.minimumRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[252]; + ParamDef->init("minimumRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum radius of damage spread when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "The minimum radius of damage spread when damage is applied.", true); + ParamDefTable[252].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=253, longName="defaultBehaviorGroup.damageColorSpread.radiusMultiplier" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[253]; + ParamDef->init("radiusMultiplier", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A scale to apply to the input damage radius when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "A scale to apply to the input damage radius when damage is applied.", true); + ParamDefTable[253].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=254, longName="defaultBehaviorGroup.damageColorSpread.falloffExponent" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[254]; + ParamDef->init("falloffExponent", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How damage varies between the minimum radius and the calculated damage radius. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.\n Within the minimumRadius, the full damage is applied to chunks. Past the minimumRadius, the formla for damage is:\n damage = (input damage) * ((radius - distance)/(radius - minimumRadius))^falloffExponent.\n Note: falloffExponent = 0.0 gives no falloff, so that damage = (input damage) over the entire range [0, radius).\n falloffExponent = 1.0 gives linear falloff.", true); + HintTable[1].init("shortDescription", "How damage varies between the minimum radius and the calculated damage radius.", true); + ParamDefTable[254].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=255, longName="defaultBehaviorGroup.damageColorChange" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[255]; + ParamDef->init("damageColorChange", TYPE_VEC4, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes how damage changes the color of vertices in the render mesh. If this vector is non-zero, then a dynamic\n (per-actor) color channel will be created and initialized to the asset's color channel, if it exists. Damage taken will go through\n the spread and envelope function described by damageColorSpread, and each color will be modified by the resulting damage, scaled\n by the values in damageColorChange. The change to color channel C is given by\n color[C] = clamp(color[C] + damageColorChange[C]*255*min(1.0, damage/damageThreshold), 0, 255).", true); + HintTable[1].init("shortDescription", "Describes how damage changes the color of vertices in the render mesh.", true); + ParamDefTable[255].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=256, longName="defaultBehaviorGroup.materialStrength" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[256]; + ParamDef->init("materialStrength", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "When a chunk takes impact damage due to physical contact (see see DestructibleDepthParameters), this parameter\n is the maximum impulse the contact can generate. Weak materials such as glass may have this set to a low value, so that\n heavier objects will pass through them during fracture.\n N.B.: Setting this parameter to 0 disables the impulse cap; that is, zero is interpreted as infinite.\n Default value = 0.0f.", true); + HintTable[1].init("shortDescription", "When a chunk takes impact, this is the maximum impulse the contact can generate.", true); + ParamDefTable[256].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=257, longName="defaultBehaviorGroup.density" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[257]; + ParamDef->init("density", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk density. (TODO: better description)", true); + HintTable[1].init("shortDescription", "Chunk density", true); + ParamDefTable[257].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=258, longName="defaultBehaviorGroup.fadeOut" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[258]; + ParamDef->init("fadeOut", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk fade out. (TODO: better description)", true); + HintTable[1].init("shortDescription", "Chunk fade out", true); + ParamDefTable[258].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=259, longName="defaultBehaviorGroup.maxDepenetrationVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[259]; + ParamDef->init("maxDepenetrationVelocity", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "In case some chunk is created inside static geometry it will be pushed out of it without limiting it's velocity. Sometimes it's not desirable, \n so this parameter can limit depenetration velocity. Keep in mind, that for low values you can see chunks 'floating' off the static meshes, which is also not always desirable.", true); + HintTable[1].init("shortDescription", "Chunk maximum depenetration velocity", true); + ParamDefTable[259].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=260, longName="defaultBehaviorGroup.groupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[260]; + ParamDef->init("groupsMask", TYPE_STRUCT, "GroupsMask", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Optional groups mask for dynamic chunks created when fractured.", true); + HintTable[1].init("shortDescription", "Optional groups mask for dynamic chunks created when fractured", true); + ParamDefTable[260].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=261, longName="defaultBehaviorGroup.groupsMask.useGroupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[261]; + ParamDef->init("useGroupsMask", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not the groupsMask should be used. If so, then this will be applied to all NxShapes\n created to represent this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Whether or not the groupsMask should be used", true); + ParamDefTable[261].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=262, longName="defaultBehaviorGroup.groupsMask.bits0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[262]; + ParamDef->init("bits0", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits0 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits0 of the groups mask", true); + ParamDefTable[262].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=263, longName="defaultBehaviorGroup.groupsMask.bits1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[263]; + ParamDef->init("bits1", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits1 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits1 of the groups mask", true); + ParamDefTable[263].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=264, longName="defaultBehaviorGroup.groupsMask.bits2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[264]; + ParamDef->init("bits2", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits2 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits2 of the groups mask", true); + ParamDefTable[264].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=265, longName="defaultBehaviorGroup.groupsMask.bits3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[265]; + ParamDef->init("bits3", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits3 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits3 of the groups mask", true); + ParamDefTable[265].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=266, longName="defaultBehaviorGroup.userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[266]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User data field. This 64-bit field can be set and retrieved by the user at runtime.", true); + HintTable[1].init("shortDescription", "User data field.", true); + ParamDefTable[266].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=267, longName="behaviorGroups" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[267]; + ParamDef->init("behaviorGroups", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The array of behavior groups referenced by chunks. Each chunk references a behavior group for chunk-specific reactions.", true); + HintTable[1].init("shortDescription", "The array of behavior groups referenced by chunks", true); + ParamDefTable[267].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[2] = { 1, 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 2); + + } + + // Initialize DefinitionImpl node: nodeIndex=268, longName="behaviorGroups[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[268]; + ParamDef->init("behaviorGroups", TYPE_STRUCT, "BehaviorGroup", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The array of behavior groups referenced by chunks. Each chunk references a behavior group for chunk-specific reactions.", true); + HintTable[1].init("shortDescription", "The array of behavior groups referenced by chunks", true); + ParamDefTable[268].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=269, longName="behaviorGroups[].name" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[269]; + ParamDef->init("name", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Name of behavior group, eg Concrete or Glass.", true); + HintTable[1].init("shortDescription", "Name of behavior group", true); + ParamDefTable[269].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=270, longName="behaviorGroups[].damageThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[270]; + ParamDef->init("damageThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The damage amount which will cause a chunk to fracture (break free) from the destructible.\n This is obtained from the damage value passed into the DestructibleActor::applyDamage,\n or DestructibleActor::applyRadiusDamage, or via impact (see 'forceToDamage', below).", true); + HintTable[1].init("shortDescription", "The damage amount which will cause a chunk to fracture (break free) from the destructible.", true); + ParamDefTable[270].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=271, longName="behaviorGroups[].damageToRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[271]; + ParamDef->init("damageToRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Controls the distance into the destructible to propagate damage. The damage applied to the chunk\n is multiplied by damageToRadius, to get the propagation distance. All chunks within the radius\n will have damage applied to them. The damage applied to each chunk varies with distance to the damage\n application position. Full damage is taken at zero distance, and zero damage at the damage radius.\n NOTE: This parameter is deprecated for point and radius damage. It will be used for those types of damage if legacy damage\n behavior is enabled with ModuleDestructible::setUseLegacyDamageRadiusSpread. Otherwise, the new parameters\n damageSpread.minimumRadius, damageSpread.radiusMultiplier, and damageSpread.falloffExponent are used. For impact damage, this parameter\n will continue to be used, however the radius will no longer scale with object size. The radius will continue\n to scale with the damage as a fraction of damageThreshold, however. If legacy damage behavior is used, this parameter\n will behave as before with respect to impact damage as well (scaling with object size).", true); + HintTable[1].init("shortDescription", "Controls the distance into the destructible to propagate damage.", true); + ParamDefTable[271].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=272, longName="behaviorGroups[].damageSpread" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[272]; + ParamDef->init("damageSpread", TYPE_STRUCT, "DamageSpreadFunction", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes the radius and damage envelope function for damage applied to the destructible.", true); + HintTable[1].init("shortDescription", "Describes the radius and damage envelope function for damage applied to the destructible.", true); + ParamDefTable[272].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=273, longName="behaviorGroups[].damageSpread.minimumRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[273]; + ParamDef->init("minimumRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum radius of damage spread when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "The minimum radius of damage spread when damage is applied.", true); + ParamDefTable[273].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=274, longName="behaviorGroups[].damageSpread.radiusMultiplier" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[274]; + ParamDef->init("radiusMultiplier", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A scale to apply to the input damage radius when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "A scale to apply to the input damage radius when damage is applied.", true); + ParamDefTable[274].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=275, longName="behaviorGroups[].damageSpread.falloffExponent" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[275]; + ParamDef->init("falloffExponent", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How damage varies between the minimum radius and the calculated damage radius. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.\n Within the minimumRadius, the full damage is applied to chunks. Past the minimumRadius, the formla for damage is:\n damage = (input damage) * ((radius - distance)/(radius - minimumRadius))^falloffExponent.\n Note: falloffExponent = 0.0 gives no falloff, so that damage = (input damage) over the entire range [0, radius).\n falloffExponent = 1.0 gives linear falloff.", true); + HintTable[1].init("shortDescription", "How damage varies between the minimum radius and the calculated damage radius.", true); + ParamDefTable[275].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=276, longName="behaviorGroups[].damageColorSpread" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[276]; + ParamDef->init("damageColorSpread", TYPE_STRUCT, "DamageSpreadFunction", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes the radius and damage envelope function for color channel damage modification applied to the destructible.", true); + HintTable[1].init("shortDescription", "Describes the radius and damage envelope function for color channel damage modification applied to the destructible.", true); + ParamDefTable[276].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=277, longName="behaviorGroups[].damageColorSpread.minimumRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[277]; + ParamDef->init("minimumRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum radius of damage spread when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "The minimum radius of damage spread when damage is applied.", true); + ParamDefTable[277].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=278, longName="behaviorGroups[].damageColorSpread.radiusMultiplier" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[278]; + ParamDef->init("radiusMultiplier", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A scale to apply to the input damage radius when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "A scale to apply to the input damage radius when damage is applied.", true); + ParamDefTable[278].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=279, longName="behaviorGroups[].damageColorSpread.falloffExponent" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[279]; + ParamDef->init("falloffExponent", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How damage varies between the minimum radius and the calculated damage radius. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.\n Within the minimumRadius, the full damage is applied to chunks. Past the minimumRadius, the formla for damage is:\n damage = (input damage) * ((radius - distance)/(radius - minimumRadius))^falloffExponent.\n Note: falloffExponent = 0.0 gives no falloff, so that damage = (input damage) over the entire range [0, radius).\n falloffExponent = 1.0 gives linear falloff.", true); + HintTable[1].init("shortDescription", "How damage varies between the minimum radius and the calculated damage radius.", true); + ParamDefTable[279].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=280, longName="behaviorGroups[].damageColorChange" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[280]; + ParamDef->init("damageColorChange", TYPE_VEC4, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes how damage changes the color of vertices in the render mesh. If this vector is non-zero, then a dynamic\n (per-actor) color channel will be created and initialized to the asset's color channel, if it exists. Damage taken will go through\n the spread and envelope function described by damageColorSpread, and each color will be modified by the resulting damage, scaled\n by the values in damageColorChange. The change to color channel C is given by\n color[C] = clamp(color[C] + damageColorChange[C]*255*min(1.0, damage/damageThreshold), 0, 255).", true); + HintTable[1].init("shortDescription", "Describes how damage changes the color of vertices in the render mesh.", true); + ParamDefTable[280].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=281, longName="behaviorGroups[].materialStrength" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[281]; + ParamDef->init("materialStrength", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "When a chunk takes impact damage due to physical contact (see see DestructibleDepthParameters), this parameter\n is the maximum impulse the contact can generate. Weak materials such as glass may have this set to a low value, so that\n heavier objects will pass through them during fracture.\n N.B.: Setting this parameter to 0 disables the impulse cap; that is, zero is interpreted as infinite.\n Default value = 0.0f.", true); + HintTable[1].init("shortDescription", "When a chunk takes impact, this is the maximum impulse the contact can generate.", true); + ParamDefTable[281].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=282, longName="behaviorGroups[].density" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[282]; + ParamDef->init("density", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk density. (TODO: better description)", true); + HintTable[1].init("shortDescription", "Chunk density", true); + ParamDefTable[282].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=283, longName="behaviorGroups[].fadeOut" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[283]; + ParamDef->init("fadeOut", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk fade out. (TODO: better description)", true); + HintTable[1].init("shortDescription", "Chunk fade out", true); + ParamDefTable[283].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=284, longName="behaviorGroups[].maxDepenetrationVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[284]; + ParamDef->init("maxDepenetrationVelocity", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "In case some chunk is created inside static geometry it will be pushed out of it without limiting it's velocity. Sometimes it's not desirable, \n so this parameter can limit depenetration velocity. Keep in mind, that for low values you can see chunks 'floating' off the static meshes, which is also not always desirable.", true); + HintTable[1].init("shortDescription", "Chunk maximum depenetration velocity", true); + ParamDefTable[284].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=285, longName="behaviorGroups[].groupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[285]; + ParamDef->init("groupsMask", TYPE_STRUCT, "GroupsMask", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Optional groups mask for dynamic chunks created when fractured.", true); + HintTable[1].init("shortDescription", "Optional groups mask for dynamic chunks created when fractured", true); + ParamDefTable[285].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=286, longName="behaviorGroups[].groupsMask.useGroupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[286]; + ParamDef->init("useGroupsMask", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not the groupsMask should be used. If so, then this will be applied to all NxShapes\n created to represent this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Whether or not the groupsMask should be used", true); + ParamDefTable[286].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=287, longName="behaviorGroups[].groupsMask.bits0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[287]; + ParamDef->init("bits0", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits0 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits0 of the groups mask", true); + ParamDefTable[287].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=288, longName="behaviorGroups[].groupsMask.bits1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[288]; + ParamDef->init("bits1", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits1 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits1 of the groups mask", true); + ParamDefTable[288].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=289, longName="behaviorGroups[].groupsMask.bits2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[289]; + ParamDef->init("bits2", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits2 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits2 of the groups mask", true); + ParamDefTable[289].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=290, longName="behaviorGroups[].groupsMask.bits3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[290]; + ParamDef->init("bits3", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits3 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits3 of the groups mask", true); + ParamDefTable[290].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=291, longName="behaviorGroups[].userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[291]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User data field. This 64-bit field can be set and retrieved by the user at runtime.", true); + HintTable[1].init("shortDescription", "User data field.", true); + ParamDefTable[291].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=292, longName="deleteChunksLeavingUserDefinedBB" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[292]; + ParamDef->init("deleteChunksLeavingUserDefinedBB", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The user can specify arbitrary number of bounding boxes in the scene using ApexScene::addBoundingBox interface along with the flag, which marks a bounding box \n as either UserBoundingBoxFlags::ENTER or UserBoundingBoxFlags::LEAVE. If user also specifies 'deleteChunksLeavingUserDefinedBB' flag to true, then chunks that are leaving a bounding box marked as\n UserBoundingBoxFlags::LEAVE are going to be deleted. User can specify more complex deletion volumes by combining 2 types of bounding boxes.", true); + HintTable[1].init("shortDescription", "Whether or not the destructible chunks are going to be deleted upon leaving any user-defined bounding box.", true); + ParamDefTable[292].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=293, longName="deleteChunksEnteringUserDefinedBB" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[293]; + ParamDef->init("deleteChunksEnteringUserDefinedBB", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The user can specify arbitrary number of bounding boxes in the scene using ApexScene::addBoundingBox interface along with the flag, which marks a bounding box \n as either UserBoundingBoxFlags::ENTER or UserBoundingBoxFlags::LEAVE. If user also specifies 'deleteChunksEnteringUserDefinedBB' flag to true, then chunks that are entering a bounding box marked as\n UserBoundingBoxFlags::ENTER are going to be deleted. User can specify more complex deletion volumes by combining 2 types of bounding boxes.", true); + HintTable[1].init("shortDescription", "Whether or not the destructible chunks are going to be deleted upon entering any user-defined bounding box.", true); + ParamDefTable[293].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[34]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(2); + Children[2] = PDEF_PTR(3); + Children[3] = PDEF_PTR(4); + Children[4] = PDEF_PTR(5); + Children[5] = PDEF_PTR(6); + Children[6] = PDEF_PTR(7); + Children[7] = PDEF_PTR(8); + Children[8] = PDEF_PTR(9); + Children[9] = PDEF_PTR(10); + Children[10] = PDEF_PTR(11); + Children[11] = PDEF_PTR(12); + Children[12] = PDEF_PTR(13); + Children[13] = PDEF_PTR(14); + Children[14] = PDEF_PTR(15); + Children[15] = PDEF_PTR(16); + Children[16] = PDEF_PTR(17); + Children[17] = PDEF_PTR(18); + Children[18] = PDEF_PTR(20); + Children[19] = PDEF_PTR(22); + Children[20] = PDEF_PTR(23); + Children[21] = PDEF_PTR(24); + Children[22] = PDEF_PTR(85); + Children[23] = PDEF_PTR(96); + Children[24] = PDEF_PTR(130); + Children[25] = PDEF_PTR(159); + Children[26] = PDEF_PTR(176); + Children[27] = PDEF_PTR(199); + Children[28] = PDEF_PTR(225); + Children[29] = PDEF_PTR(239); + Children[30] = PDEF_PTR(243); + Children[31] = PDEF_PTR(267); + Children[32] = PDEF_PTR(292); + Children[33] = PDEF_PTR(293); + + ParamDefTable[0].setChildren(Children, 34); + } + + // SetChildren for: nodeIndex=18, longName="overrideSkinnedMaterialNames" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(19); + + ParamDefTable[18].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=20, longName="overrideStaticMaterialNames" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(21); + + ParamDefTable[20].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=24, longName="destructibleParameters" + { + static Definition* Children[24]; + Children[0] = PDEF_PTR(25); + Children[1] = PDEF_PTR(26); + Children[2] = PDEF_PTR(27); + Children[3] = PDEF_PTR(28); + Children[4] = PDEF_PTR(29); + Children[5] = PDEF_PTR(30); + Children[6] = PDEF_PTR(31); + Children[7] = PDEF_PTR(32); + Children[8] = PDEF_PTR(33); + Children[9] = PDEF_PTR(34); + Children[10] = PDEF_PTR(35); + Children[11] = PDEF_PTR(36); + Children[12] = PDEF_PTR(37); + Children[13] = PDEF_PTR(38); + Children[14] = PDEF_PTR(39); + Children[15] = PDEF_PTR(47); + Children[16] = PDEF_PTR(48); + Children[17] = PDEF_PTR(49); + Children[18] = PDEF_PTR(50); + Children[19] = PDEF_PTR(56); + Children[20] = PDEF_PTR(81); + Children[21] = PDEF_PTR(82); + Children[22] = PDEF_PTR(83); + Children[23] = PDEF_PTR(84); + + ParamDefTable[24].setChildren(Children, 24); + } + + // SetChildren for: nodeIndex=39, longName="destructibleParameters.flags" + { + static Definition* Children[7]; + Children[0] = PDEF_PTR(40); + Children[1] = PDEF_PTR(41); + Children[2] = PDEF_PTR(42); + Children[3] = PDEF_PTR(43); + Children[4] = PDEF_PTR(44); + Children[5] = PDEF_PTR(45); + Children[6] = PDEF_PTR(46); + + ParamDefTable[39].setChildren(Children, 7); + } + + // SetChildren for: nodeIndex=50, longName="destructibleParameters.dynamicChunksGroupsMask" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(51); + Children[1] = PDEF_PTR(52); + Children[2] = PDEF_PTR(53); + Children[3] = PDEF_PTR(54); + Children[4] = PDEF_PTR(55); + + ParamDefTable[50].setChildren(Children, 5); + } + + // SetChildren for: nodeIndex=56, longName="destructibleParameters.runtimeFracture" + { + static Definition* Children[9]; + Children[0] = PDEF_PTR(57); + Children[1] = PDEF_PTR(58); + Children[2] = PDEF_PTR(59); + Children[3] = PDEF_PTR(60); + Children[4] = PDEF_PTR(61); + Children[5] = PDEF_PTR(62); + Children[6] = PDEF_PTR(63); + Children[7] = PDEF_PTR(69); + Children[8] = PDEF_PTR(74); + + ParamDefTable[56].setChildren(Children, 9); + } + + // SetChildren for: nodeIndex=63, longName="destructibleParameters.runtimeFracture.glass" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(64); + Children[1] = PDEF_PTR(65); + Children[2] = PDEF_PTR(66); + Children[3] = PDEF_PTR(67); + Children[4] = PDEF_PTR(68); + + ParamDefTable[63].setChildren(Children, 5); + } + + // SetChildren for: nodeIndex=69, longName="destructibleParameters.runtimeFracture.voronoi" + { + static Definition* Children[4]; + Children[0] = PDEF_PTR(70); + Children[1] = PDEF_PTR(71); + Children[2] = PDEF_PTR(72); + Children[3] = PDEF_PTR(73); + + ParamDefTable[69].setChildren(Children, 4); + } + + // SetChildren for: nodeIndex=74, longName="destructibleParameters.runtimeFracture.attachment" + { + static Definition* Children[6]; + Children[0] = PDEF_PTR(75); + Children[1] = PDEF_PTR(76); + Children[2] = PDEF_PTR(77); + Children[3] = PDEF_PTR(78); + Children[4] = PDEF_PTR(79); + Children[5] = PDEF_PTR(80); + + ParamDefTable[74].setChildren(Children, 6); + } + + // SetChildren for: nodeIndex=85, longName="depthParameters" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(86); + + ParamDefTable[85].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=86, longName="depthParameters[]" + { + static Definition* Children[9]; + Children[0] = PDEF_PTR(87); + Children[1] = PDEF_PTR(88); + Children[2] = PDEF_PTR(89); + Children[3] = PDEF_PTR(90); + Children[4] = PDEF_PTR(91); + Children[5] = PDEF_PTR(92); + Children[6] = PDEF_PTR(93); + Children[7] = PDEF_PTR(94); + Children[8] = PDEF_PTR(95); + + ParamDefTable[86].setChildren(Children, 9); + } + + // SetChildren for: nodeIndex=96, longName="shapeDescTemplate" + { + static Definition* Children[8]; + Children[0] = PDEF_PTR(97); + Children[1] = PDEF_PTR(118); + Children[2] = PDEF_PTR(119); + Children[3] = PDEF_PTR(125); + Children[4] = PDEF_PTR(126); + Children[5] = PDEF_PTR(127); + Children[6] = PDEF_PTR(128); + Children[7] = PDEF_PTR(129); + + ParamDefTable[96].setChildren(Children, 8); + } + + // SetChildren for: nodeIndex=97, longName="shapeDescTemplate.flags" + { + static Definition* Children[20]; + Children[0] = PDEF_PTR(98); + Children[1] = PDEF_PTR(99); + Children[2] = PDEF_PTR(100); + Children[3] = PDEF_PTR(101); + Children[4] = PDEF_PTR(102); + Children[5] = PDEF_PTR(103); + Children[6] = PDEF_PTR(104); + Children[7] = PDEF_PTR(105); + Children[8] = PDEF_PTR(106); + Children[9] = PDEF_PTR(107); + Children[10] = PDEF_PTR(108); + Children[11] = PDEF_PTR(109); + Children[12] = PDEF_PTR(110); + Children[13] = PDEF_PTR(111); + Children[14] = PDEF_PTR(112); + Children[15] = PDEF_PTR(113); + Children[16] = PDEF_PTR(114); + Children[17] = PDEF_PTR(115); + Children[18] = PDEF_PTR(116); + Children[19] = PDEF_PTR(117); + + ParamDefTable[97].setChildren(Children, 20); + } + + // SetChildren for: nodeIndex=119, longName="shapeDescTemplate.groupsMask" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(120); + Children[1] = PDEF_PTR(121); + Children[2] = PDEF_PTR(122); + Children[3] = PDEF_PTR(123); + Children[4] = PDEF_PTR(124); + + ParamDefTable[119].setChildren(Children, 5); + } + + // SetChildren for: nodeIndex=130, longName="actorDescTemplate" + { + static Definition* Children[9]; + Children[0] = PDEF_PTR(131); + Children[1] = PDEF_PTR(139); + Children[2] = PDEF_PTR(140); + Children[3] = PDEF_PTR(141); + Children[4] = PDEF_PTR(142); + Children[5] = PDEF_PTR(155); + Children[6] = PDEF_PTR(156); + Children[7] = PDEF_PTR(157); + Children[8] = PDEF_PTR(158); + + ParamDefTable[130].setChildren(Children, 9); + } + + // SetChildren for: nodeIndex=131, longName="actorDescTemplate.flags" + { + static Definition* Children[7]; + Children[0] = PDEF_PTR(132); + Children[1] = PDEF_PTR(133); + Children[2] = PDEF_PTR(134); + Children[3] = PDEF_PTR(135); + Children[4] = PDEF_PTR(136); + Children[5] = PDEF_PTR(137); + Children[6] = PDEF_PTR(138); + + ParamDefTable[131].setChildren(Children, 7); + } + + // SetChildren for: nodeIndex=142, longName="actorDescTemplate.contactReportFlags" + { + static Definition* Children[12]; + Children[0] = PDEF_PTR(143); + Children[1] = PDEF_PTR(144); + Children[2] = PDEF_PTR(145); + Children[3] = PDEF_PTR(146); + Children[4] = PDEF_PTR(147); + Children[5] = PDEF_PTR(148); + Children[6] = PDEF_PTR(149); + Children[7] = PDEF_PTR(150); + Children[8] = PDEF_PTR(151); + Children[9] = PDEF_PTR(152); + Children[10] = PDEF_PTR(153); + Children[11] = PDEF_PTR(154); + + ParamDefTable[142].setChildren(Children, 12); + } + + // SetChildren for: nodeIndex=159, longName="bodyDescTemplate" + { + static Definition* Children[12]; + Children[0] = PDEF_PTR(160); + Children[1] = PDEF_PTR(165); + Children[2] = PDEF_PTR(166); + Children[3] = PDEF_PTR(167); + Children[4] = PDEF_PTR(168); + Children[5] = PDEF_PTR(169); + Children[6] = PDEF_PTR(170); + Children[7] = PDEF_PTR(171); + Children[8] = PDEF_PTR(172); + Children[9] = PDEF_PTR(173); + Children[10] = PDEF_PTR(174); + Children[11] = PDEF_PTR(175); + + ParamDefTable[159].setChildren(Children, 12); + } + + // SetChildren for: nodeIndex=160, longName="bodyDescTemplate.flags" + { + static Definition* Children[4]; + Children[0] = PDEF_PTR(161); + Children[1] = PDEF_PTR(162); + Children[2] = PDEF_PTR(163); + Children[3] = PDEF_PTR(164); + + ParamDefTable[160].setChildren(Children, 4); + } + + // SetChildren for: nodeIndex=176, longName="p3ShapeDescTemplate" + { + static Definition* Children[8]; + Children[0] = PDEF_PTR(177); + Children[1] = PDEF_PTR(184); + Children[2] = PDEF_PTR(189); + Children[3] = PDEF_PTR(194); + Children[4] = PDEF_PTR(195); + Children[5] = PDEF_PTR(196); + Children[6] = PDEF_PTR(197); + Children[7] = PDEF_PTR(198); + + ParamDefTable[176].setChildren(Children, 8); + } + + // SetChildren for: nodeIndex=177, longName="p3ShapeDescTemplate.flags" + { + static Definition* Children[6]; + Children[0] = PDEF_PTR(178); + Children[1] = PDEF_PTR(179); + Children[2] = PDEF_PTR(180); + Children[3] = PDEF_PTR(181); + Children[4] = PDEF_PTR(182); + Children[5] = PDEF_PTR(183); + + ParamDefTable[177].setChildren(Children, 6); + } + + // SetChildren for: nodeIndex=184, longName="p3ShapeDescTemplate.simulationFilterData" + { + static Definition* Children[4]; + Children[0] = PDEF_PTR(185); + Children[1] = PDEF_PTR(186); + Children[2] = PDEF_PTR(187); + Children[3] = PDEF_PTR(188); + + ParamDefTable[184].setChildren(Children, 4); + } + + // SetChildren for: nodeIndex=189, longName="p3ShapeDescTemplate.queryFilterData" + { + static Definition* Children[4]; + Children[0] = PDEF_PTR(190); + Children[1] = PDEF_PTR(191); + Children[2] = PDEF_PTR(192); + Children[3] = PDEF_PTR(193); + + ParamDefTable[189].setChildren(Children, 4); + } + + // SetChildren for: nodeIndex=199, longName="p3ActorDescTemplate" + { + static Definition* Children[7]; + Children[0] = PDEF_PTR(200); + Children[1] = PDEF_PTR(204); + Children[2] = PDEF_PTR(205); + Children[3] = PDEF_PTR(206); + Children[4] = PDEF_PTR(207); + Children[5] = PDEF_PTR(223); + Children[6] = PDEF_PTR(224); + + ParamDefTable[199].setChildren(Children, 7); + } + + // SetChildren for: nodeIndex=200, longName="p3ActorDescTemplate.flags" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(201); + Children[1] = PDEF_PTR(202); + Children[2] = PDEF_PTR(203); + + ParamDefTable[200].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=207, longName="p3ActorDescTemplate.contactReportFlags" + { + static Definition* Children[15]; + Children[0] = PDEF_PTR(208); + Children[1] = PDEF_PTR(209); + Children[2] = PDEF_PTR(210); + Children[3] = PDEF_PTR(211); + Children[4] = PDEF_PTR(212); + Children[5] = PDEF_PTR(213); + Children[6] = PDEF_PTR(214); + Children[7] = PDEF_PTR(215); + Children[8] = PDEF_PTR(216); + Children[9] = PDEF_PTR(217); + Children[10] = PDEF_PTR(218); + Children[11] = PDEF_PTR(219); + Children[12] = PDEF_PTR(220); + Children[13] = PDEF_PTR(221); + Children[14] = PDEF_PTR(222); + + ParamDefTable[207].setChildren(Children, 15); + } + + // SetChildren for: nodeIndex=225, longName="p3BodyDescTemplate" + { + static Definition* Children[11]; + Children[0] = PDEF_PTR(226); + Children[1] = PDEF_PTR(227); + Children[2] = PDEF_PTR(230); + Children[3] = PDEF_PTR(231); + Children[4] = PDEF_PTR(232); + Children[5] = PDEF_PTR(233); + Children[6] = PDEF_PTR(234); + Children[7] = PDEF_PTR(235); + Children[8] = PDEF_PTR(236); + Children[9] = PDEF_PTR(237); + Children[10] = PDEF_PTR(238); + + ParamDefTable[225].setChildren(Children, 11); + } + + // SetChildren for: nodeIndex=227, longName="p3BodyDescTemplate.flags" + { + static Definition* Children[2]; + Children[0] = PDEF_PTR(228); + Children[1] = PDEF_PTR(229); + + ParamDefTable[227].setChildren(Children, 2); + } + + // SetChildren for: nodeIndex=239, longName="structureSettings" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(240); + Children[1] = PDEF_PTR(241); + Children[2] = PDEF_PTR(242); + + ParamDefTable[239].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=243, longName="defaultBehaviorGroup" + { + static Definition* Children[12]; + Children[0] = PDEF_PTR(244); + Children[1] = PDEF_PTR(245); + Children[2] = PDEF_PTR(246); + Children[3] = PDEF_PTR(247); + Children[4] = PDEF_PTR(251); + Children[5] = PDEF_PTR(255); + Children[6] = PDEF_PTR(256); + Children[7] = PDEF_PTR(257); + Children[8] = PDEF_PTR(258); + Children[9] = PDEF_PTR(259); + Children[10] = PDEF_PTR(260); + Children[11] = PDEF_PTR(266); + + ParamDefTable[243].setChildren(Children, 12); + } + + // SetChildren for: nodeIndex=247, longName="defaultBehaviorGroup.damageSpread" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(248); + Children[1] = PDEF_PTR(249); + Children[2] = PDEF_PTR(250); + + ParamDefTable[247].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=251, longName="defaultBehaviorGroup.damageColorSpread" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(252); + Children[1] = PDEF_PTR(253); + Children[2] = PDEF_PTR(254); + + ParamDefTable[251].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=260, longName="defaultBehaviorGroup.groupsMask" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(261); + Children[1] = PDEF_PTR(262); + Children[2] = PDEF_PTR(263); + Children[3] = PDEF_PTR(264); + Children[4] = PDEF_PTR(265); + + ParamDefTable[260].setChildren(Children, 5); + } + + // SetChildren for: nodeIndex=267, longName="behaviorGroups" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(268); + + ParamDefTable[267].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=268, longName="behaviorGroups[]" + { + static Definition* Children[12]; + Children[0] = PDEF_PTR(269); + Children[1] = PDEF_PTR(270); + Children[2] = PDEF_PTR(271); + Children[3] = PDEF_PTR(272); + Children[4] = PDEF_PTR(276); + Children[5] = PDEF_PTR(280); + Children[6] = PDEF_PTR(281); + Children[7] = PDEF_PTR(282); + Children[8] = PDEF_PTR(283); + Children[9] = PDEF_PTR(284); + Children[10] = PDEF_PTR(285); + Children[11] = PDEF_PTR(291); + + ParamDefTable[268].setChildren(Children, 12); + } + + // SetChildren for: nodeIndex=272, longName="behaviorGroups[].damageSpread" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(273); + Children[1] = PDEF_PTR(274); + Children[2] = PDEF_PTR(275); + + ParamDefTable[272].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=276, longName="behaviorGroups[].damageColorSpread" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(277); + Children[1] = PDEF_PTR(278); + Children[2] = PDEF_PTR(279); + + ParamDefTable[276].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=285, longName="behaviorGroups[].groupsMask" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(286); + Children[1] = PDEF_PTR(287); + Children[2] = PDEF_PTR(288); + Children[3] = PDEF_PTR(289); + Children[4] = PDEF_PTR(290); + + ParamDefTable[285].setChildren(Children, 5); + } + + mBuiltFlag = true; + +} +void DestructibleActorParam::initStrings(void) +{ + crumbleEmitterName.isAllocated = false; + crumbleEmitterName.buf = (const char*)0; + dustEmitterName.isAllocated = false; + dustEmitterName.buf = (const char*)0; + defaultBehaviorGroup.name.isAllocated = true; + defaultBehaviorGroup.name.buf = NULL; +} + +void DestructibleActorParam::initDynamicArrays(void) +{ + overrideSkinnedMaterialNames.buf = NULL; + overrideSkinnedMaterialNames.isAllocated = true; + overrideSkinnedMaterialNames.elementSize = sizeof(NvParameterized::DummyStringStruct); + overrideSkinnedMaterialNames.arraySizes[0] = 0; + overrideStaticMaterialNames.buf = NULL; + overrideStaticMaterialNames.isAllocated = true; + overrideStaticMaterialNames.elementSize = sizeof(NvParameterized::DummyStringStruct); + overrideStaticMaterialNames.arraySizes[0] = 0; + depthParameters.buf = NULL; + depthParameters.isAllocated = true; + depthParameters.elementSize = sizeof(DestructibleDepthParameters_Type); + depthParameters.arraySizes[0] = 0; + behaviorGroups.buf = NULL; + behaviorGroups.isAllocated = true; + behaviorGroups.elementSize = sizeof(BehaviorGroup_Type); + behaviorGroups.arraySizes[0] = 0; +} + +void DestructibleActorParam::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + crumbleParticleSpacing = float(0); + dustParticleSpacing = float(0); + globalPose = physx::PxTransform(physx::PxIdentity); + scale = physx::PxVec3(init(1, 1, 1)); + dynamic = bool(true); + supportDepth = uint32_t(0); + formExtendedStructures = bool(false); + performDetailedOverlapTestForExtendedStructures = bool(true); + keepPreviousFrameBoneBuffer = bool(false); + doNotCreateRenderable = bool(false); + useAssetDefinedSupport = bool(false); + useWorldSupport = bool(false); + renderStaticChunksSeparately = bool(false); + keepVisibleBonesPacked = bool(true); + createChunkEvents = bool(false); + sleepVelocityFrameDecayConstant = float(1); + useHardSleeping = bool(false); + destructibleParameters.damageCap = float(0); + destructibleParameters.forceToDamage = float(0); + destructibleParameters.impactVelocityThreshold = float(0); + destructibleParameters.minimumFractureDepth = uint32_t(0); + destructibleParameters.impactDamageDefaultDepth = int32_t(-1); + destructibleParameters.debrisDepth = int32_t(-1); + destructibleParameters.essentialDepth = uint32_t(0); + destructibleParameters.debrisLifetimeMin = float(1); + destructibleParameters.debrisLifetimeMax = float(10); + destructibleParameters.debrisMaxSeparationMin = float(1); + destructibleParameters.debrisMaxSeparationMax = float(10); + destructibleParameters.debrisDestructionProbability = float(0); + destructibleParameters.validBounds = physx::PxBounds3(init(-1000, -1000, -1000, 1000, 1000, 1000)); + destructibleParameters.maxChunkSpeed = float(0); + destructibleParameters.flags.ACCUMULATE_DAMAGE = bool(true); + destructibleParameters.flags.DEBRIS_TIMEOUT = bool(false); + destructibleParameters.flags.DEBRIS_MAX_SEPARATION = bool(false); + destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS = bool(false); + destructibleParameters.flags.ACCURATE_RAYCASTS = bool(false); + destructibleParameters.flags.USE_VALID_BOUNDS = bool(false); + destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE = bool(false); + destructibleParameters.fractureImpulseScale = float(0); + destructibleParameters.damageDepthLimit = uint16_t(UINT16_MAX); + destructibleParameters.dynamicChunkDominanceGroup = uint16_t(UINT16_MAX); + destructibleParameters.dynamicChunksGroupsMask.useGroupsMask = bool(false); + destructibleParameters.dynamicChunksGroupsMask.bits0 = uint32_t(0); + destructibleParameters.dynamicChunksGroupsMask.bits1 = uint32_t(0); + destructibleParameters.dynamicChunksGroupsMask.bits2 = uint32_t(0); + destructibleParameters.dynamicChunksGroupsMask.bits3 = uint32_t(0); + destructibleParameters.runtimeFracture.RuntimeFractureType = (const char*)"VORONOI"; + destructibleParameters.runtimeFracture.sheetFracture = bool(true); + destructibleParameters.runtimeFracture.depthLimit = uint32_t(2); + destructibleParameters.runtimeFracture.destroyIfAtDepthLimit = bool(false); + destructibleParameters.runtimeFracture.minConvexSize = float(0.02); + destructibleParameters.runtimeFracture.impulseScale = float(1); + destructibleParameters.runtimeFracture.glass.numSectors = uint32_t(10); + destructibleParameters.runtimeFracture.glass.sectorRand = float(0.3); + destructibleParameters.runtimeFracture.glass.firstSegmentSize = float(0.06); + destructibleParameters.runtimeFracture.glass.segmentScale = float(1.4); + destructibleParameters.runtimeFracture.glass.segmentRand = float(0.3); + destructibleParameters.runtimeFracture.voronoi.dimensions = physx::PxVec3(physx::PxVec3(10.0f)); + destructibleParameters.runtimeFracture.voronoi.numCells = uint32_t(1); + destructibleParameters.runtimeFracture.voronoi.biasExp = float(10); + destructibleParameters.runtimeFracture.voronoi.maxDist = float(PX_MAX_F32); + destructibleParameters.runtimeFracture.attachment.posX = bool(false); + destructibleParameters.runtimeFracture.attachment.negX = bool(false); + destructibleParameters.runtimeFracture.attachment.posY = bool(false); + destructibleParameters.runtimeFracture.attachment.negY = bool(false); + destructibleParameters.runtimeFracture.attachment.posZ = bool(false); + destructibleParameters.runtimeFracture.attachment.negZ = bool(false); + destructibleParameters.supportStrength = float(-1); + destructibleParameters.legacyChunkBoundsTestSetting = int8_t(-1); + destructibleParameters.legacyDamageRadiusSpreadSetting = int8_t(-1); + destructibleParameters.alwaysDrawScatterMesh = bool(false); + shapeDescTemplate.flags.NX_TRIGGER_ON_ENTER = bool(false); + shapeDescTemplate.flags.NX_TRIGGER_ON_LEAVE = bool(false); + shapeDescTemplate.flags.NX_TRIGGER_ON_STAY = bool(false); + shapeDescTemplate.flags.NX_SF_VISUALIZATION = bool(true); + shapeDescTemplate.flags.NX_SF_DISABLE_COLLISION = bool(false); + shapeDescTemplate.flags.NX_SF_FEATURE_INDICES = bool(false); + shapeDescTemplate.flags.NX_SF_DISABLE_RAYCASTING = bool(false); + shapeDescTemplate.flags.NX_SF_POINT_CONTACT_FORCE = bool(false); + shapeDescTemplate.flags.NX_SF_FLUID_DRAIN = bool(false); + shapeDescTemplate.flags.NX_SF_FLUID_DISABLE_COLLISION = bool(false); + shapeDescTemplate.flags.NX_SF_FLUID_TWOWAY = bool(false); + shapeDescTemplate.flags.NX_SF_DISABLE_RESPONSE = bool(false); + shapeDescTemplate.flags.NX_SF_DYNAMIC_DYNAMIC_CCD = bool(false); + shapeDescTemplate.flags.NX_SF_DISABLE_SCENE_QUERIES = bool(false); + shapeDescTemplate.flags.NX_SF_CLOTH_DRAIN = bool(false); + shapeDescTemplate.flags.NX_SF_CLOTH_DISABLE_COLLISION = bool(false); + shapeDescTemplate.flags.NX_SF_CLOTH_TWOWAY = bool(true); + shapeDescTemplate.flags.NX_SF_SOFTBODY_DRAIN = bool(false); + shapeDescTemplate.flags.NX_SF_SOFTBODY_DISABLE_COLLISION = bool(false); + shapeDescTemplate.flags.NX_SF_SOFTBODY_TWOWAY = bool(true); + shapeDescTemplate.collisionGroup = uint16_t(0); + shapeDescTemplate.groupsMask.useGroupsMask = bool(false); + shapeDescTemplate.groupsMask.bits0 = uint32_t(0); + shapeDescTemplate.groupsMask.bits1 = uint32_t(0); + shapeDescTemplate.groupsMask.bits2 = uint32_t(0); + shapeDescTemplate.groupsMask.bits3 = uint32_t(0); + shapeDescTemplate.materialIndex = uint16_t(0); + shapeDescTemplate.density = float(1); + shapeDescTemplate.skinWidth = float(-1); + shapeDescTemplate.userData = uint64_t(0); + shapeDescTemplate.name = uint64_t(0); + actorDescTemplate.flags.NX_AF_DISABLE_COLLISION = bool(false); + actorDescTemplate.flags.NX_AF_DISABLE_RESPONSE = bool(false); + actorDescTemplate.flags.NX_AF_LOCK_COM = bool(false); + actorDescTemplate.flags.NX_AF_FLUID_DISABLE_COLLISION = bool(false); + actorDescTemplate.flags.NX_AF_CONTACT_MODIFICATION = bool(false); + actorDescTemplate.flags.NX_AF_FORCE_CONE_FRICTION = bool(false); + actorDescTemplate.flags.NX_AF_USER_ACTOR_PAIR_FILTERING = bool(false); + actorDescTemplate.density = float(1); + actorDescTemplate.actorCollisionGroup = uint16_t(0); + actorDescTemplate.dominanceGroup = uint16_t(0); + actorDescTemplate.contactReportFlags.NX_IGNORE_PAIR = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_START_TOUCH = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_END_TOUCH = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_TOUCH = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_IMPACT = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_ROLL = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_SLIDE = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_FORCES = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_END_TOUCH_FORCE_THRESHOLD = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_ON_TOUCH_FORCE_THRESHOLD = bool(false); + actorDescTemplate.contactReportFlags.NX_NOTIFY_CONTACT_MODIFICATION = bool(false); + actorDescTemplate.forceFieldMaterial = uint16_t(0); + actorDescTemplate.userData = uint64_t(0); + actorDescTemplate.name = uint64_t(0); + actorDescTemplate.compartment = uint64_t(0); + bodyDescTemplate.flags.NX_BF_DISABLE_GRAVITY = bool(false); + bodyDescTemplate.flags.NX_BF_FILTER_SLEEP_VEL = bool(false); + bodyDescTemplate.flags.NX_BF_ENERGY_SLEEP_TEST = bool(true); + bodyDescTemplate.flags.NX_BF_VISUALIZATION = bool(true); + bodyDescTemplate.wakeUpCounter = float(0.4); + bodyDescTemplate.linearDamping = float(0); + bodyDescTemplate.angularDamping = float(0.05); + bodyDescTemplate.maxAngularVelocity = float(-1); + bodyDescTemplate.CCDMotionThreshold = float(0); + bodyDescTemplate.sleepLinearVelocity = float(-1); + bodyDescTemplate.sleepAngularVelocity = float(-1); + bodyDescTemplate.solverIterationCount = uint32_t(4); + bodyDescTemplate.sleepEnergyThreshold = float(0.005); + bodyDescTemplate.sleepDamping = float(0); + bodyDescTemplate.contactReportThreshold = float(PX_MAX_F32); + p3ShapeDescTemplate.flags.eSIMULATION_SHAPE = bool(true); + p3ShapeDescTemplate.flags.eSCENE_QUERY_SHAPE = bool(true); + p3ShapeDescTemplate.flags.eTRIGGER_SHAPE = bool(false); + p3ShapeDescTemplate.flags.eVISUALIZATION = bool(true); + p3ShapeDescTemplate.flags.ePARTICLE_DRAIN = bool(false); + p3ShapeDescTemplate.flags.eDEFORMABLE_DRAIN = bool(false); + p3ShapeDescTemplate.simulationFilterData.word0 = uint32_t(0); + p3ShapeDescTemplate.simulationFilterData.word1 = uint32_t(0); + p3ShapeDescTemplate.simulationFilterData.word2 = uint32_t(0); + p3ShapeDescTemplate.simulationFilterData.word3 = uint32_t(0); + p3ShapeDescTemplate.queryFilterData.word0 = uint32_t(0); + p3ShapeDescTemplate.queryFilterData.word1 = uint32_t(0); + p3ShapeDescTemplate.queryFilterData.word2 = uint32_t(0); + p3ShapeDescTemplate.queryFilterData.word3 = uint32_t(0); + p3ShapeDescTemplate.material = uint64_t(0); + p3ShapeDescTemplate.contactOffset = float(0.02); + p3ShapeDescTemplate.restOffset = float(0); + p3ShapeDescTemplate.userData = uint64_t(0); + p3ShapeDescTemplate.name = uint64_t(0); + p3ActorDescTemplate.flags.eVISUALIZATION = bool(true); + p3ActorDescTemplate.flags.eDISABLE_GRAVITY = bool(false); + p3ActorDescTemplate.flags.eSEND_SLEEP_NOTIFIES = bool(true); + p3ActorDescTemplate.dominanceGroup = uint8_t(0); + p3ActorDescTemplate.ownerClient = uint8_t(0); + p3ActorDescTemplate.clientBehaviorBits = uint32_t(0); + p3ActorDescTemplate.contactReportFlags.eSOLVE_CONTACT = bool(false); + p3ActorDescTemplate.contactReportFlags.eMODIFY_CONTACTS = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_TOUCH_FOUND = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_TOUCH_PERSISTS = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_TOUCH_LOST = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_FOUND = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_PERSISTS = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_THRESHOLD_FORCE_LOST = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_POINTS = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_FORCES = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_FORCE_PER_POINT = bool(false); + p3ActorDescTemplate.contactReportFlags.eNOTIFY_CONTACT_FEATURE_INDICES_PER_POINT = bool(false); + p3ActorDescTemplate.contactReportFlags.eDETECT_CCD_CONTACT = bool(false); + p3ActorDescTemplate.contactReportFlags.eCONTACT_DEFAULT = bool(false); + p3ActorDescTemplate.contactReportFlags.eTRIGGER_DEFAULT = bool(false); + p3ActorDescTemplate.userData = uint64_t(0); + p3ActorDescTemplate.name = uint64_t(0); + p3BodyDescTemplate.density = float(1); + p3BodyDescTemplate.flags.eKINEMATIC = bool(false); + p3BodyDescTemplate.flags.eENABLE_CCD = bool(false); + p3BodyDescTemplate.sleepThreshold = float(0.005); + p3BodyDescTemplate.wakeUpCounter = float(0.4); + p3BodyDescTemplate.linearDamping = float(0); + p3BodyDescTemplate.angularDamping = float(0.05); + p3BodyDescTemplate.maxAngularVelocity = float(7); + p3BodyDescTemplate.solverIterationCount = uint32_t(4); + p3BodyDescTemplate.velocityIterationCount = uint32_t(1); + p3BodyDescTemplate.contactReportThreshold = float(PX_MAX_F32); + p3BodyDescTemplate.sleepLinearVelocity = float(-1); + structureSettings.useStressSolver = bool(false); + structureSettings.stressSolverTimeDelay = float(1.0); + structureSettings.stressSolverMassThreshold = float(0.0); + defaultBehaviorGroup.damageThreshold = float(1); + defaultBehaviorGroup.damageToRadius = float(0.1); + defaultBehaviorGroup.damageSpread.minimumRadius = float(0); + defaultBehaviorGroup.damageSpread.radiusMultiplier = float(1); + defaultBehaviorGroup.damageSpread.falloffExponent = float(1); + defaultBehaviorGroup.damageColorSpread.minimumRadius = float(0); + defaultBehaviorGroup.damageColorSpread.radiusMultiplier = float(1); + defaultBehaviorGroup.damageColorSpread.falloffExponent = float(1); + defaultBehaviorGroup.damageColorChange = physx::PxVec4(initVec4(0, 0, 0, 0)); + defaultBehaviorGroup.materialStrength = float(0); + defaultBehaviorGroup.density = float(0); + defaultBehaviorGroup.fadeOut = float(1); + defaultBehaviorGroup.maxDepenetrationVelocity = float(PX_MAX_F32); + defaultBehaviorGroup.groupsMask.useGroupsMask = bool(false); + defaultBehaviorGroup.groupsMask.bits0 = uint32_t(0); + defaultBehaviorGroup.groupsMask.bits1 = uint32_t(0); + defaultBehaviorGroup.groupsMask.bits2 = uint32_t(0); + defaultBehaviorGroup.groupsMask.bits3 = uint32_t(0); + defaultBehaviorGroup.userData = uint64_t(0); + deleteChunksLeavingUserDefinedBB = bool(false); + deleteChunksEnteringUserDefinedBB = bool(false); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void DestructibleActorParam::initReferences(void) +{ +} + +void DestructibleActorParam::freeDynamicArrays(void) +{ + if (overrideSkinnedMaterialNames.isAllocated && overrideSkinnedMaterialNames.buf) + { + mParameterizedTraits->free(overrideSkinnedMaterialNames.buf); + } + if (overrideStaticMaterialNames.isAllocated && overrideStaticMaterialNames.buf) + { + mParameterizedTraits->free(overrideStaticMaterialNames.buf); + } + if (depthParameters.isAllocated && depthParameters.buf) + { + mParameterizedTraits->free(depthParameters.buf); + } + if (behaviorGroups.isAllocated && behaviorGroups.buf) + { + mParameterizedTraits->free(behaviorGroups.buf); + } +} + +void DestructibleActorParam::freeStrings(void) +{ + + if (crumbleEmitterName.isAllocated && crumbleEmitterName.buf) + { + mParameterizedTraits->strfree((char*)crumbleEmitterName.buf); + } + + if (dustEmitterName.isAllocated && dustEmitterName.buf) + { + mParameterizedTraits->strfree((char*)dustEmitterName.buf); + } + + for (int i = 0; i < overrideSkinnedMaterialNames.arraySizes[0]; ++i) + { + if (overrideSkinnedMaterialNames.buf[i].isAllocated && overrideSkinnedMaterialNames.buf[i].buf) + { + mParameterizedTraits->strfree((char*)overrideSkinnedMaterialNames.buf[i].buf); + } + } + + for (int i = 0; i < overrideStaticMaterialNames.arraySizes[0]; ++i) + { + if (overrideStaticMaterialNames.buf[i].isAllocated && overrideStaticMaterialNames.buf[i].buf) + { + mParameterizedTraits->strfree((char*)overrideStaticMaterialNames.buf[i].buf); + } + } + + if (defaultBehaviorGroup.name.isAllocated && defaultBehaviorGroup.name.buf) + { + mParameterizedTraits->strfree((char*)defaultBehaviorGroup.name.buf); + } + + for (int i = 0; i < behaviorGroups.arraySizes[0]; ++i) + { + if (behaviorGroups.buf[i].name.isAllocated && behaviorGroups.buf[i].name.buf) + { + mParameterizedTraits->strfree((char*)behaviorGroups.buf[i].name.buf); + } + } +} + +void DestructibleActorParam::freeReferences(void) +{ +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/DestructibleActorState.cpp b/APEX_1.4/module/destructible/src/autogen/DestructibleActorState.cpp new file mode 100644 index 00000000..f8a85c69 --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/DestructibleActorState.cpp @@ -0,0 +1,2137 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "DestructibleActorState.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace DestructibleActorStateNS; + +const char* const DestructibleActorStateFactory::vptr = + NvParameterized::getVptr<DestructibleActorState, DestructibleActorState::ClassAlignment>(); + +const uint32_t NumParamDefs = 69; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, 3, 4, 5, 66, 67, 68, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 28, 29, 30, 31, 37, 62, 63, 64, 65, 21, 22, 23, 24, 25, 26, 27, 32, 33, 34, 35, 36, + 38, 39, 40, 41, 42, 43, 44, 50, 55, 45, 46, 47, 48, 49, 51, 52, 53, 54, 56, 57, 58, + 59, 60, 61, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 8 }, + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->enableCrumbleEmitter), NULL, 0 }, // enableCrumbleEmitter + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->enableDustEmitter), NULL, 0 }, // enableDustEmitter + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->lod), NULL, 0 }, // lod + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->forceLod), NULL, 0 }, // forceLod + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->destructibleParameters), CHILDREN(8), 24 }, // destructibleParameters + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->damageCap), NULL, 0 }, // destructibleParameters.damageCap + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->forceToDamage), NULL, 0 }, // destructibleParameters.forceToDamage + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->impactVelocityThreshold), NULL, 0 }, // destructibleParameters.impactVelocityThreshold + { TYPE_U32, false, (size_t)(&((DestructibleParameters_Type*)0)->minimumFractureDepth), NULL, 0 }, // destructibleParameters.minimumFractureDepth + { TYPE_I32, false, (size_t)(&((DestructibleParameters_Type*)0)->impactDamageDefaultDepth), NULL, 0 }, // destructibleParameters.impactDamageDefaultDepth + { TYPE_I32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisDepth), NULL, 0 }, // destructibleParameters.debrisDepth + { TYPE_U32, false, (size_t)(&((DestructibleParameters_Type*)0)->essentialDepth), NULL, 0 }, // destructibleParameters.essentialDepth + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisLifetimeMin), NULL, 0 }, // destructibleParameters.debrisLifetimeMin + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisLifetimeMax), NULL, 0 }, // destructibleParameters.debrisLifetimeMax + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisMaxSeparationMin), NULL, 0 }, // destructibleParameters.debrisMaxSeparationMin + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisMaxSeparationMax), NULL, 0 }, // destructibleParameters.debrisMaxSeparationMax + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisDestructionProbability), NULL, 0 }, // destructibleParameters.debrisDestructionProbability + { TYPE_BOUNDS3, false, (size_t)(&((DestructibleParameters_Type*)0)->validBounds), NULL, 0 }, // destructibleParameters.validBounds + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->maxChunkSpeed), NULL, 0 }, // destructibleParameters.maxChunkSpeed + { TYPE_STRUCT, false, (size_t)(&((DestructibleParameters_Type*)0)->flags), CHILDREN(32), 7 }, // destructibleParameters.flags + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->ACCUMULATE_DAMAGE), NULL, 0 }, // destructibleParameters.flags.ACCUMULATE_DAMAGE + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->DEBRIS_TIMEOUT), NULL, 0 }, // destructibleParameters.flags.DEBRIS_TIMEOUT + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->DEBRIS_MAX_SEPARATION), NULL, 0 }, // destructibleParameters.flags.DEBRIS_MAX_SEPARATION + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->CRUMBLE_SMALLEST_CHUNKS), NULL, 0 }, // destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->ACCURATE_RAYCASTS), NULL, 0 }, // destructibleParameters.flags.ACCURATE_RAYCASTS + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->USE_VALID_BOUNDS), NULL, 0 }, // destructibleParameters.flags.USE_VALID_BOUNDS + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->CRUMBLE_VIA_RUNTIME_FRACTURE), NULL, 0 }, // destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->fractureImpulseScale), NULL, 0 }, // destructibleParameters.fractureImpulseScale + { TYPE_U16, false, (size_t)(&((DestructibleParameters_Type*)0)->damageDepthLimit), NULL, 0 }, // destructibleParameters.damageDepthLimit + { TYPE_U16, false, (size_t)(&((DestructibleParameters_Type*)0)->dynamicChunkDominanceGroup), NULL, 0 }, // destructibleParameters.dynamicChunkDominanceGroup + { TYPE_STRUCT, false, (size_t)(&((DestructibleParameters_Type*)0)->dynamicChunksGroupsMask), CHILDREN(39), 5 }, // destructibleParameters.dynamicChunksGroupsMask + { TYPE_BOOL, false, (size_t)(&((GroupsMask_Type*)0)->useGroupsMask), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.useGroupsMask + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits0), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits0 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits1), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits1 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits2), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits2 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits3), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits3 + { TYPE_STRUCT, false, (size_t)(&((DestructibleParameters_Type*)0)->runtimeFracture), CHILDREN(44), 9 }, // destructibleParameters.runtimeFracture + { TYPE_ENUM, false, (size_t)(&((RuntimeFracture_Type*)0)->RuntimeFractureType), NULL, 0 }, // destructibleParameters.runtimeFracture.RuntimeFractureType + { TYPE_BOOL, false, (size_t)(&((RuntimeFracture_Type*)0)->sheetFracture), NULL, 0 }, // destructibleParameters.runtimeFracture.sheetFracture + { TYPE_U32, false, (size_t)(&((RuntimeFracture_Type*)0)->depthLimit), NULL, 0 }, // destructibleParameters.runtimeFracture.depthLimit + { TYPE_BOOL, false, (size_t)(&((RuntimeFracture_Type*)0)->destroyIfAtDepthLimit), NULL, 0 }, // destructibleParameters.runtimeFracture.destroyIfAtDepthLimit + { TYPE_F32, false, (size_t)(&((RuntimeFracture_Type*)0)->minConvexSize), NULL, 0 }, // destructibleParameters.runtimeFracture.minConvexSize + { TYPE_F32, false, (size_t)(&((RuntimeFracture_Type*)0)->impulseScale), NULL, 0 }, // destructibleParameters.runtimeFracture.impulseScale + { TYPE_STRUCT, false, (size_t)(&((RuntimeFracture_Type*)0)->glass), CHILDREN(53), 5 }, // destructibleParameters.runtimeFracture.glass + { TYPE_U32, false, (size_t)(&((FractureGlass_Type*)0)->numSectors), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.numSectors + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->sectorRand), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.sectorRand + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->firstSegmentSize), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.firstSegmentSize + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->segmentScale), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.segmentScale + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->segmentRand), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.segmentRand + { TYPE_STRUCT, false, (size_t)(&((RuntimeFracture_Type*)0)->voronoi), CHILDREN(58), 4 }, // destructibleParameters.runtimeFracture.voronoi + { TYPE_VEC3, false, (size_t)(&((FractureVoronoi_Type*)0)->dimensions), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.dimensions + { TYPE_U32, false, (size_t)(&((FractureVoronoi_Type*)0)->numCells), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.numCells + { TYPE_F32, false, (size_t)(&((FractureVoronoi_Type*)0)->biasExp), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.biasExp + { TYPE_F32, false, (size_t)(&((FractureVoronoi_Type*)0)->maxDist), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.maxDist + { TYPE_STRUCT, false, (size_t)(&((RuntimeFracture_Type*)0)->attachment), CHILDREN(62), 6 }, // destructibleParameters.runtimeFracture.attachment + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->posX), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.posX + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->negX), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.negX + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->posY), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.posY + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->negY), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.negY + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->posZ), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.posZ + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->negZ), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.negZ + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->supportStrength), NULL, 0 }, // destructibleParameters.supportStrength + { TYPE_I8, false, (size_t)(&((DestructibleParameters_Type*)0)->legacyChunkBoundsTestSetting), NULL, 0 }, // destructibleParameters.legacyChunkBoundsTestSetting + { TYPE_I8, false, (size_t)(&((DestructibleParameters_Type*)0)->legacyDamageRadiusSpreadSetting), NULL, 0 }, // destructibleParameters.legacyDamageRadiusSpreadSetting + { TYPE_BOOL, false, (size_t)(&((DestructibleParameters_Type*)0)->alwaysDrawScatterMesh), NULL, 0 }, // destructibleParameters.alwaysDrawScatterMesh + { TYPE_U64, false, (size_t)(&((ParametersStruct*)0)->userData), NULL, 0 }, // userData + { TYPE_REF, false, (size_t)(&((ParametersStruct*)0)->actorParameters), NULL, 0 }, // actorParameters + { TYPE_REF, false, (size_t)(&((ParametersStruct*)0)->actorChunks), NULL, 0 }, // actorChunks +}; + + +bool DestructibleActorState::mBuiltFlag = false; +NvParameterized::MutexType DestructibleActorState::mBuiltFlagMutex; + +DestructibleActorState::DestructibleActorState(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &DestructibleActorStateFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +DestructibleActorState::~DestructibleActorState() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void DestructibleActorState::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~DestructibleActorState(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* DestructibleActorState::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* DestructibleActorState::getParameterDefinitionTree(void) const +{ + DestructibleActorState* tmpParam = const_cast<DestructibleActorState*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType DestructibleActorState::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType DestructibleActorState::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void DestructibleActorState::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<DestructibleActorState::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ + +void DestructibleActorState::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void DestructibleActorState::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="enableCrumbleEmitter" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("enableCrumbleEmitter", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not the crumble emitter is active.", true); + HintTable[1].init("shortDescription", "Whether or not the crumble emitter is active", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="enableDustEmitter" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("enableDustEmitter", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not the dust emitter is active.", true); + HintTable[1].init("shortDescription", "Whether or not the dust emitter is active", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="lod" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("lod", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Destructible actor LOD.", true); + HintTable[1].init("shortDescription", "Destructible actor LOD", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="forceLod" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("forceLod", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not to force LOD behavior on the actor.", true); + HintTable[1].init("shortDescription", "Whether or not to force LOD behavior on the actor", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="destructibleParameters" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("destructibleParameters", TYPE_STRUCT, "DestructibleParameters", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Parameters that control destruction of a destructible actor.", true); + HintTable[1].init("shortDescription", "Parameters that control destruction of a destructible actor", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=6, longName="destructibleParameters.damageCap" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6]; + ParamDef->init("damageCap", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Limits the amount of damage applied to a chunk. This is useful for preventing the entire destructible\nfrom getting pulverized by a very large application of damage. This can easily happen when impact damage is\nused, and the damage amount is proportional to the impact force (see forceToDamage).\n", true); + HintTable[1].init("shortDescription", "Limits the amount of damage applied to a chunk.", true); + ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=7, longName="destructibleParameters.forceToDamage" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7]; + ParamDef->init("forceToDamage", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If a chunk is at a depth which takes impact damage (see NxDestructibleDepthParameters),\nthen when a chunk has a collision in the NxScene, it will take damage equal to forceToDamage mulitplied by\nthe impact force.\nThe default value is zero, which effectively disables impact damage.\n", true); + HintTable[1].init("shortDescription", "Multiplier to calculate applied damage from an impact.", true); + ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=8, longName="destructibleParameters.impactVelocityThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8]; + ParamDef->init("impactVelocityThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Large impact force may be reported if rigid bodies are spawned inside one another. In this case the relative velocity of the two\nobjects will be low. This variable allows the user to set a minimum velocity threshold for impacts to ensure that the objects are\nmoving at a min velocity in order for the impact force to be considered.\n", true); + HintTable[1].init("shortDescription", "Large impact force may be reported if rigid bodies are spawned inside one another.", true); + ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=9, longName="destructibleParameters.minimumFractureDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9]; + ParamDef->init("minimumFractureDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks will not be broken free below this depth.\n", true); + HintTable[1].init("shortDescription", "The chunks will not be broken free below this depth.", true); + ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=10, longName="destructibleParameters.impactDamageDefaultDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10]; + ParamDef->init("impactDamageDefaultDepth", TYPE_I32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The default depth to which chunks will take impact damage. This default may be overridden in the depth settings.\n", true); + HintTable[1].init("shortDescription", "The default depth to which chunks will take impact damage.", true); + ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=11, longName="destructibleParameters.debrisDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11]; + ParamDef->init("debrisDepth", TYPE_I32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The chunk hierarchy depth at which chunks are considered to be 'debris.' Chunks at this depth or\nbelow will be considered for various debris settings, such as debrisLifetime.\nNegative values indicate that no chunk depth is considered debris.\nDefault value is -1.\n", true); + HintTable[1].init("shortDescription", "The chunk hierarchy depth at which chunks are considered to be 'debris.'", true); + ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=12, longName="destructibleParameters.essentialDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12]; + ParamDef->init("essentialDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The chunk hierarchy depth up to which chunks will always be processed. These chunks are considered\nto be essential either for gameplay or visually.\nThe minimum value is 0, meaning the level 0 chunk is always considered essential.\nDefault value is 0.\n", true); + HintTable[1].init("shortDescription", "The chunk hierarchy depth up to which chunks will always be processed", true); + ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=13, longName="destructibleParameters.debrisLifetimeMin" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13]; + ParamDef->init("debrisLifetimeMin", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed after a time (in seconds)\nseparated from non-debris chunks. The actual lifetime is interpolated between\ndebrisLifetimeMin and debrisLifetimeMax (see below), based upon the module\'s LOD setting.\nTo disable lifetime, clear the NxDestructibleDepthParametersFlag::DEBRIS_TIMEOUT\nflag in the flags field. If debrisLifetimeMax < debrisLifetimeMin, the mean of the two\nis used for both.\nDefault debrisLifetimeMin = 1.0, debrisLifetimeMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Minimum time to destroy debris", true); + ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=14, longName="destructibleParameters.debrisLifetimeMax" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14]; + ParamDef->init("debrisLifetimeMax", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed after a time (in seconds)\nseparated from non-debris chunks. The actual lifetime is interpolated between\ndebrisLifetimeMin (see above) and debrisLifetimeMax, based upon the module\'s LOD setting.\nTo disable lifetime, clear the NxDestructibleDepthParametersFlag::DEBRIS_TIMEOUT\nflag in the flags field. If debrisLifetimeMax < debrisLifetimeMin, the mean of the two\nis used for both.\nDefault debrisLifetimeMin = 1.0, debrisLifetimeMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Maximum time to destroy debris", true); + ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=15, longName="destructibleParameters.debrisMaxSeparationMin" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15]; + ParamDef->init("debrisMaxSeparationMin", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed if they are separated from\ntheir origin by a distance greater than maxSeparation. The actual maxSeparation is\ninterpolated between debrisMaxSeparationMin and debrisMaxSeparationMax (see below),\nbased upon the module\'s LOD setting. To disable maxSeparation, clear the\nNX_DESTRUCTIBLE_DEBRIS_MAX_SEPARATION flag in the flags field.\nIf debrisMaxSeparationMax < debrisMaxSeparationMin, the mean of the two is used for both.\nDefault debrisMaxSeparationMin = 1.0, debrisMaxSeparationMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Minimum separation distance", true); + ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=16, longName="destructibleParameters.debrisMaxSeparationMax" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16]; + ParamDef->init("debrisMaxSeparationMax", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed if they are separated from\ntheir origin by a distance greater than maxSeparation. The actual maxSeparation is\ninterpolated between debrisMaxSeparationMin (see above) and debrisMaxSeparationMax,\nbased upon the module\'s LOD setting. To disable maxSeparation, clear the\nNX_DESTRUCTIBLE_DEBRIS_MAX_SEPARATION flag in the flags field.\nIf debrisMaxSeparationMax < debrisMaxSeparationMin, the mean of the two is used for both.\nDefault debrisMaxSeparationMin = 1.0, debrisMaxSeparationMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Minimum separation distance", true); + ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=17, longName="destructibleParameters.debrisDestructionProbability" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17]; + ParamDef->init("debrisDestructionProbability", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The probablity that a debris chunk, when fractured, will simply be destroyed instead of becoming dynamic or breaking down\n further into child chunks. Valid range = [0.0,1.0]. Default value = 0.0.", true); + HintTable[1].init("shortDescription", "The probablity that a debris chunk, when fractured, will simply be destroyed", true); + ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=18, longName="destructibleParameters.validBounds" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18]; + ParamDef->init("validBounds", TYPE_BOUNDS3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A bounding box around each NxDestructibleActor created, defining a range of validity\nfor chunks that break free. These bounds are scaled and translated with the\nNxDestructibleActor\'s scale and position, but they are not rotated with the\nNxDestructibleActor.\n", true); + HintTable[1].init("shortDescription", "valid bounding region for debris", true); + ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=19, longName="destructibleParameters.maxChunkSpeed" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19]; + ParamDef->init("maxChunkSpeed", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If greater than 0, the chunks' speeds will not be allowed to exceed this value. Use 0\nto disable this feature (this is the default).\n", true); + HintTable[1].init("shortDescription", "Maximum speed of a chunk", true); + ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=20, longName="destructibleParameters.flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20]; + ParamDef->init("flags", TYPE_STRUCT, "DestructibleParametersFlag", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A collection of flags defined in NxDestructibleParametersFlag.\n", true); + HintTable[1].init("shortDescription", "A collection of flags defined in DestructibleParametersFlag.", true); + ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=21, longName="destructibleParameters.flags.ACCUMULATE_DAMAGE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21]; + ParamDef->init("ACCUMULATE_DAMAGE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, chunks will 'remember' damage applied to them, so that many applications of a damage amount\nbelow damageThreshold will eventually fracture the chunk. If not set, a single application of\ndamage must exceed damageThreshold in order to fracture the chunk.\n", true); + HintTable[1].init("shortDescription", "Determines if chunks accumulate damage", true); + ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=22, longName="destructibleParameters.flags.DEBRIS_TIMEOUT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22]; + ParamDef->init("DEBRIS_TIMEOUT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not chunks at or deeper than the 'debris' depth (see NxDestructibleParameters::debrisDepth)\nwill time out. The lifetime is a value between NxDestructibleParameters::debrisLifetimeMin and\nNxDestructibleParameters::debrisLifetimeMax, based upon the destructible module\'s LOD setting.\n", true); + HintTable[1].init("shortDescription", "Whether or not chunks at or deeper than the 'debris' depth will timeout", true); + ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=23, longName="destructibleParameters.flags.DEBRIS_MAX_SEPARATION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23]; + ParamDef->init("DEBRIS_MAX_SEPARATION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not chunks at or deeper than the 'debris' depth (see NxDestructibleParameters::debrisDepth)\nwill be removed if they separate too far from their origins. The maxSeparation is a value between\nNxDestructibleParameters::debrisMaxSeparationMin and NxDestructibleParameters::debrisMaxSeparationMax,\nbased upon the destructible module\'s LOD setting.\n", true); + HintTable[1].init("shortDescription", "Whether or not chunks at or deeper than the 'debris' depth will be removed if separated too far", true); + ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=24, longName="destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24]; + ParamDef->init("CRUMBLE_SMALLEST_CHUNKS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, the smallest chunks may be further broken down, either by fluid crumbles (if a crumble particle\nsystem is specified in the NxDestructibleActorDesc), or by simply removing the chunk if no crumble\nparticle system is specified. Note: the 'smallest chunks' are normally defined to be the deepest level\nof the fracture hierarchy. However, they may be taken from higher levels of the hierarchy if\nNxModuleDestructible::setMaxChunkDepthOffset is called with a non-zero value.\n", true); + HintTable[1].init("shortDescription", "If set, the smallest chunks may be further broken down", true); + ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=25, longName="destructibleParameters.flags.ACCURATE_RAYCASTS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25]; + ParamDef->init("ACCURATE_RAYCASTS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, the NxDestructibleActor::rayCast function will search within the nearest visible chunk hit\nfor collisions with child chunks. This is used to get a better raycast position and normal, in\ncase the parent collision volume does not tightly fit the graphics mesh. The returned chunk index\nwill always be that of the visible parent that is intersected, however.\n", true); + HintTable[1].init("shortDescription", "If set, the NxDestructibleActor::rayCast function will search within the nearest visible chunk hit", true); + ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=26, longName="destructibleParameters.flags.USE_VALID_BOUNDS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26]; + ParamDef->init("USE_VALID_BOUNDS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, the validBounds field of NxDestructibleParameters will be used. These bounds are translated\n(but not scaled or rotated) to the origin of the destructible actor. If a chunk or chunk island moves\noutside of those bounds, it is destroyed.\n", true); + HintTable[1].init("shortDescription", "If set, the validBounds field of NxDestructibleParameters will be used.", true); + ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=27, longName="destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27]; + ParamDef->init("CRUMBLE_VIA_RUNTIME_FRACTURE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, crumbled chunks will use the runtime fracture pipeline. The chunk will be procedurally broken\ndestroyed using either the default or a specified fracture pattern.\n", true); + HintTable[1].init("shortDescription", "If set, crumbled chunks will use the runtime fracture pipeline.", true); + ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=28, longName="destructibleParameters.fractureImpulseScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28]; + ParamDef->init("fractureImpulseScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scale factor used to apply an impulse force along the normal of chunk when fractured. This is used\nin order to 'push' the pieces out as they fracture.\n", true); + HintTable[1].init("shortDescription", "Scale factor used to apply an impulse force along the normal of chunk when fractured.", true); + ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=29, longName="destructibleParameters.damageDepthLimit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29]; + ParamDef->init("damageDepthLimit", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How deep in the hierarchy damage will be propagated, relative to the chunk hit.", true); + HintTable[1].init("shortDescription", "How deep in the hierarchy damage will be propagated, relative to the chunk hit.", true); + ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=30, longName="destructibleParameters.dynamicChunkDominanceGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30]; + ParamDef->init("dynamicChunkDominanceGroup", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Optional dominance group for dynamic chunks created when fractured. (ignored if > 31)\n", true); + HintTable[1].init("shortDescription", "Optional dominance group for dynamic chunks created when fractured.", true); + ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=31, longName="destructibleParameters.dynamicChunksGroupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31]; + ParamDef->init("dynamicChunksGroupsMask", TYPE_STRUCT, "GroupsMask", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Optional groups mask for dynamic chunks created when fractured.\n", true); + HintTable[1].init("shortDescription", "Optional groups mask for dynamic chunks created when fractured.", true); + ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=32, longName="destructibleParameters.dynamicChunksGroupsMask.useGroupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32]; + ParamDef->init("useGroupsMask", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not the groupsMask should be used. If so, then this will be applied to all NxShapes\n created to represent this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Whether or not the groupsMask should be used", true); + ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=33, longName="destructibleParameters.dynamicChunksGroupsMask.bits0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33]; + ParamDef->init("bits0", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits0 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits0 of the groups mask", true); + ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=34, longName="destructibleParameters.dynamicChunksGroupsMask.bits1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34]; + ParamDef->init("bits1", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits1 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits1 of the groups mask", true); + ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=35, longName="destructibleParameters.dynamicChunksGroupsMask.bits2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35]; + ParamDef->init("bits2", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits2 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits2 of the groups mask", true); + ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=36, longName="destructibleParameters.dynamicChunksGroupsMask.bits3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36]; + ParamDef->init("bits3", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits3 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits3 of the groups mask", true); + ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=37, longName="destructibleParameters.runtimeFracture" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37]; + ParamDef->init("runtimeFracture", TYPE_STRUCT, "RuntimeFracture", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Runtime Fracture Settings. 'CRUMBLE_VIA_RUNTIME_FRACTURE' must be set for this to do anything.\n", true); + HintTable[1].init("shortDescription", "Runtime Fracture Settings", true); + ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=38, longName="destructibleParameters.runtimeFracture.RuntimeFractureType" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38]; + ParamDef->init("RuntimeFractureType", TYPE_ENUM, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Which type of fracture pattern to choose", true); + ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + static const char* const EnumVals[] = { "VORONOI", "GLASS" }; + ParamDefTable[38].setEnumVals((const char**)EnumVals, 2); + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=39, longName="destructibleParameters.runtimeFracture.sheetFracture" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39]; + ParamDef->init("sheetFracture", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, align fracture pattern to largest face. \nIf false, the fracture pattern will be aligned to the hit normal with each fracture.\n", true); + HintTable[1].init("shortDescription", "If true, align fracture pattern to largest face", true); + ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=40, longName="destructibleParameters.runtimeFracture.depthLimit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40]; + ParamDef->init("depthLimit", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of times deep a chunk can be fractured. Can help limit the number of chunks produced by\nruntime fracture.\n", true); + HintTable[1].init("shortDescription", "Number of times deep a chunk can be fractured.", true); + ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=41, longName="destructibleParameters.runtimeFracture.destroyIfAtDepthLimit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[41]; + ParamDef->init("destroyIfAtDepthLimit", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, destroy chunks when they hit their depth limit. \nIf false, then chunks at their depth limit will not fracture but will have a force applied.\n", true); + HintTable[1].init("shortDescription", "Destroy chunk if at depth limit", true); + ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=42, longName="destructibleParameters.runtimeFracture.minConvexSize" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[42]; + ParamDef->init("minConvexSize", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Minimum Convex Size. Minimum size of convex produced by a fracture.\n", true); + HintTable[1].init("shortDescription", "Minimum Convex Size.", true); + ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=43, longName="destructibleParameters.runtimeFracture.impulseScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[43]; + ParamDef->init("impulseScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scales impulse applied by a fracture.\n", true); + HintTable[1].init("shortDescription", "Scales impulse applied by a fracture.", true); + ParamDefTable[43].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=44, longName="destructibleParameters.runtimeFracture.glass" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[44]; + ParamDef->init("glass", TYPE_STRUCT, "FractureGlass", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Glass Fracture Pattern Settings.\n", true); + HintTable[1].init("shortDescription", "Glass Fracture Pattern Settings.", true); + ParamDefTable[44].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=45, longName="destructibleParameters.runtimeFracture.glass.numSectors" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[45]; + ParamDef->init("numSectors", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of angular slices in the glass fracture pattern. \n", true); + HintTable[1].init("shortDescription", "Number of angular slices.", true); + ParamDefTable[45].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=46, longName="destructibleParameters.runtimeFracture.glass.sectorRand" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[46]; + ParamDef->init("sectorRand", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Creates variance in the angle of slices. A value of zero results in all angular slices having the same angle.\n", true); + HintTable[1].init("shortDescription", "Creates variance in the angle of slices.", true); + ParamDefTable[46].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=47, longName="destructibleParameters.runtimeFracture.glass.firstSegmentSize" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[47]; + ParamDef->init("firstSegmentSize", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum shard size. Shards below this size will not be created and thus not visible.\n", true); + HintTable[1].init("shortDescription", "The minimum shard size.", true); + ParamDefTable[47].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=48, longName="destructibleParameters.runtimeFracture.glass.segmentScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[48]; + ParamDef->init("segmentScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scales the radial spacing in the glass fracture pattern. A larger value results in radially longer shards.\n", true); + HintTable[1].init("shortDescription", "Scales the radial spacing.", true); + ParamDefTable[48].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=49, longName="destructibleParameters.runtimeFracture.glass.segmentRand" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[49]; + ParamDef->init("segmentRand", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Creates variance in the radial size of shards. A value of zero results in a low noise circular pattern.\n", true); + HintTable[1].init("shortDescription", "Creates variance in the radial size of shards.", true); + ParamDefTable[49].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=50, longName="destructibleParameters.runtimeFracture.voronoi" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[50]; + ParamDef->init("voronoi", TYPE_STRUCT, "FractureVoronoi", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Voronoi Fracture Pattern Settings.\n", true); + HintTable[1].init("shortDescription", "Voronoi Fracture Pattern Settings.", true); + ParamDefTable[50].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=51, longName="destructibleParameters.runtimeFracture.voronoi.dimensions" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[51]; + ParamDef->init("dimensions", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The size of the entire block. \n", true); + HintTable[1].init("shortDescription", "The size of the entire block", true); + ParamDefTable[51].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=52, longName="destructibleParameters.runtimeFracture.voronoi.numCells" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[52]; + ParamDef->init("numCells", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of Cells corresponds to the number of chunks to create during the fracture, default value is only one chunk.\n", true); + HintTable[1].init("shortDescription", "Max Number of Cells to create.", true); + ParamDefTable[52].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=53, longName="destructibleParameters.runtimeFracture.voronoi.biasExp" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[53]; + ParamDef->init("biasExp", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Bias Exponential value is used in distributing voronoi points which is used to fracture the original chunk.\n", true); + HintTable[1].init("shortDescription", "Bias Exponential value.", true); + ParamDefTable[53].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=54, longName="destructibleParameters.runtimeFracture.voronoi.maxDist" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[54]; + ParamDef->init("maxDist", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "This is to prevent a illegal voronoi point that's used to generate voronoi chunks.\n", true); + HintTable[1].init("shortDescription", "The max distance a Voronoi point away from origin.", true); + ParamDefTable[54].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=55, longName="destructibleParameters.runtimeFracture.attachment" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[55]; + ParamDef->init("attachment", TYPE_STRUCT, "FractureAttachment", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Attachment Settings. Allows the sides of a runtime fracture chunk to be kinematic rather than dynamic.\n", true); + HintTable[1].init("shortDescription", "Attachment Settings", true); + ParamDefTable[55].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=56, longName="destructibleParameters.runtimeFracture.attachment.posX" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[56]; + ParamDef->init("posX", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the positive x side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to positive x side of sheet.", true); + ParamDefTable[56].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=57, longName="destructibleParameters.runtimeFracture.attachment.negX" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[57]; + ParamDef->init("negX", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the negative x side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to negative x side of sheet.", true); + ParamDefTable[57].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=58, longName="destructibleParameters.runtimeFracture.attachment.posY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[58]; + ParamDef->init("posY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the positive y side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to positive y side of sheet.", true); + ParamDefTable[58].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=59, longName="destructibleParameters.runtimeFracture.attachment.negY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[59]; + ParamDef->init("negY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the negative y side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to negative y side of sheet.", true); + ParamDefTable[59].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=60, longName="destructibleParameters.runtimeFracture.attachment.posZ" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[60]; + ParamDef->init("posZ", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the positive z side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to positive z side of sheet.", true); + ParamDefTable[60].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=61, longName="destructibleParameters.runtimeFracture.attachment.negZ" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[61]; + ParamDef->init("negZ", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the negative z side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to negative z side of sheet.", true); + ParamDefTable[61].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=62, longName="destructibleParameters.supportStrength" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[62]; + ParamDef->init("supportStrength", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The larger the supportStrength is, the harder it will break under stressSolver. SupportStrength should be larger\nthan 0.0 so that it is not extremely fragile.\nDefault supportStrength = -1.0 which means strength is turned off initially.\n", true); + HintTable[1].init("shortDescription", "The support strength threshold for breaking chunks in stressSolver", true); + ParamDefTable[62].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=63, longName="destructibleParameters.legacyChunkBoundsTestSetting" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[63]; + ParamDef->init("legacyChunkBoundsTestSetting", TYPE_I8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not to use the old chunk bounds testing for damage, or use the module setting. A value of 0 forces the new method to be used.\nA positive value forces the old method to be used. Negative values cause the global (NxModuleDestructible) setting to be used.\n", true); + HintTable[1].init("shortDescription", "Whether or not to use the old chunk bounds testing for damage, or use the module setting.", true); + ParamDefTable[63].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=64, longName="destructibleParameters.legacyDamageRadiusSpreadSetting" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[64]; + ParamDef->init("legacyDamageRadiusSpreadSetting", TYPE_I8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("END", "", true); + ParamDefTable[64].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("END", "", true); + HintTable[1].init("longDescription", "Whether or not to use the old damage spread method, or use the module setting. A value of 0 forces the new method to be used.\nA positive value forces the old method to be used. Negative values cause the global (NxModuleDestructible) setting to be used.\n", true); + HintTable[2].init("shortDescription", "Whether or not to use the old damage spread method, or use the module setting.", true); + ParamDefTable[64].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=65, longName="destructibleParameters.alwaysDrawScatterMesh" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[65]; + ParamDef->init("alwaysDrawScatterMesh", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scatter mesh visibility is controlled by LOD. If asset has more than one depth level, scatter mesh is not drawn.\n This flag forces drawing of scatter mesh on chunks with depth > 1.", true); + HintTable[1].init("shortDescription", "Always draw scatter mesh on the chunks with depth > 1", true); + ParamDefTable[65].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=66, longName="userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[66]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[66].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Optional user data pointer. Note: Any pointer references will not be properly serialized.", true); + HintTable[2].init("shortDescription", "Optional user data pointer", true); + ParamDefTable[66].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=67, longName="actorParameters" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[67]; + ParamDef->init("actorParameters", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[67].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The destructible actor parameters.", true); + HintTable[2].init("shortDescription", "The destructible actor parameters", true); + ParamDefTable[67].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "DestructibleActorParam" }; + ParamDefTable[67].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // Initialize DefinitionImpl node: nodeIndex=68, longName="actorChunks" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[68]; + ParamDef->init("actorChunks", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[68].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The actor's chunk data.", true); + HintTable[2].init("shortDescription", "The actor's chunk data", true); + ParamDefTable[68].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "DestructibleActorChunks" }; + ParamDefTable[68].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[8]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(2); + Children[2] = PDEF_PTR(3); + Children[3] = PDEF_PTR(4); + Children[4] = PDEF_PTR(5); + Children[5] = PDEF_PTR(66); + Children[6] = PDEF_PTR(67); + Children[7] = PDEF_PTR(68); + + ParamDefTable[0].setChildren(Children, 8); + } + + // SetChildren for: nodeIndex=5, longName="destructibleParameters" + { + static Definition* Children[24]; + Children[0] = PDEF_PTR(6); + Children[1] = PDEF_PTR(7); + Children[2] = PDEF_PTR(8); + Children[3] = PDEF_PTR(9); + Children[4] = PDEF_PTR(10); + Children[5] = PDEF_PTR(11); + Children[6] = PDEF_PTR(12); + Children[7] = PDEF_PTR(13); + Children[8] = PDEF_PTR(14); + Children[9] = PDEF_PTR(15); + Children[10] = PDEF_PTR(16); + Children[11] = PDEF_PTR(17); + Children[12] = PDEF_PTR(18); + Children[13] = PDEF_PTR(19); + Children[14] = PDEF_PTR(20); + Children[15] = PDEF_PTR(28); + Children[16] = PDEF_PTR(29); + Children[17] = PDEF_PTR(30); + Children[18] = PDEF_PTR(31); + Children[19] = PDEF_PTR(37); + Children[20] = PDEF_PTR(62); + Children[21] = PDEF_PTR(63); + Children[22] = PDEF_PTR(64); + Children[23] = PDEF_PTR(65); + + ParamDefTable[5].setChildren(Children, 24); + } + + // SetChildren for: nodeIndex=20, longName="destructibleParameters.flags" + { + static Definition* Children[7]; + Children[0] = PDEF_PTR(21); + Children[1] = PDEF_PTR(22); + Children[2] = PDEF_PTR(23); + Children[3] = PDEF_PTR(24); + Children[4] = PDEF_PTR(25); + Children[5] = PDEF_PTR(26); + Children[6] = PDEF_PTR(27); + + ParamDefTable[20].setChildren(Children, 7); + } + + // SetChildren for: nodeIndex=31, longName="destructibleParameters.dynamicChunksGroupsMask" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(32); + Children[1] = PDEF_PTR(33); + Children[2] = PDEF_PTR(34); + Children[3] = PDEF_PTR(35); + Children[4] = PDEF_PTR(36); + + ParamDefTable[31].setChildren(Children, 5); + } + + // SetChildren for: nodeIndex=37, longName="destructibleParameters.runtimeFracture" + { + static Definition* Children[9]; + Children[0] = PDEF_PTR(38); + Children[1] = PDEF_PTR(39); + Children[2] = PDEF_PTR(40); + Children[3] = PDEF_PTR(41); + Children[4] = PDEF_PTR(42); + Children[5] = PDEF_PTR(43); + Children[6] = PDEF_PTR(44); + Children[7] = PDEF_PTR(50); + Children[8] = PDEF_PTR(55); + + ParamDefTable[37].setChildren(Children, 9); + } + + // SetChildren for: nodeIndex=44, longName="destructibleParameters.runtimeFracture.glass" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(45); + Children[1] = PDEF_PTR(46); + Children[2] = PDEF_PTR(47); + Children[3] = PDEF_PTR(48); + Children[4] = PDEF_PTR(49); + + ParamDefTable[44].setChildren(Children, 5); + } + + // SetChildren for: nodeIndex=50, longName="destructibleParameters.runtimeFracture.voronoi" + { + static Definition* Children[4]; + Children[0] = PDEF_PTR(51); + Children[1] = PDEF_PTR(52); + Children[2] = PDEF_PTR(53); + Children[3] = PDEF_PTR(54); + + ParamDefTable[50].setChildren(Children, 4); + } + + // SetChildren for: nodeIndex=55, longName="destructibleParameters.runtimeFracture.attachment" + { + static Definition* Children[6]; + Children[0] = PDEF_PTR(56); + Children[1] = PDEF_PTR(57); + Children[2] = PDEF_PTR(58); + Children[3] = PDEF_PTR(59); + Children[4] = PDEF_PTR(60); + Children[5] = PDEF_PTR(61); + + ParamDefTable[55].setChildren(Children, 6); + } + + mBuiltFlag = true; + +} +void DestructibleActorState::initStrings(void) +{ +} + +void DestructibleActorState::initDynamicArrays(void) +{ +} + +void DestructibleActorState::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + enableCrumbleEmitter = bool(true); + enableDustEmitter = bool(true); + lod = uint32_t(0); + forceLod = bool(false); + destructibleParameters.damageCap = float(0); + destructibleParameters.forceToDamage = float(0); + destructibleParameters.impactVelocityThreshold = float(0); + destructibleParameters.minimumFractureDepth = uint32_t(0); + destructibleParameters.impactDamageDefaultDepth = int32_t(-1); + destructibleParameters.debrisDepth = int32_t(-1); + destructibleParameters.essentialDepth = uint32_t(0); + destructibleParameters.debrisLifetimeMin = float(1); + destructibleParameters.debrisLifetimeMax = float(10); + destructibleParameters.debrisMaxSeparationMin = float(1); + destructibleParameters.debrisMaxSeparationMax = float(10); + destructibleParameters.debrisDestructionProbability = float(0); + destructibleParameters.validBounds = physx::PxBounds3(init(-1000, -1000, -1000, 1000, 1000, 1000)); + destructibleParameters.maxChunkSpeed = float(0); + destructibleParameters.flags.ACCUMULATE_DAMAGE = bool(true); + destructibleParameters.flags.DEBRIS_TIMEOUT = bool(false); + destructibleParameters.flags.DEBRIS_MAX_SEPARATION = bool(false); + destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS = bool(false); + destructibleParameters.flags.ACCURATE_RAYCASTS = bool(false); + destructibleParameters.flags.USE_VALID_BOUNDS = bool(false); + destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE = bool(false); + destructibleParameters.fractureImpulseScale = float(0); + destructibleParameters.damageDepthLimit = uint16_t(UINT16_MAX); + destructibleParameters.dynamicChunkDominanceGroup = uint16_t(UINT16_MAX); + destructibleParameters.dynamicChunksGroupsMask.useGroupsMask = bool(false); + destructibleParameters.dynamicChunksGroupsMask.bits0 = uint32_t(0); + destructibleParameters.dynamicChunksGroupsMask.bits1 = uint32_t(0); + destructibleParameters.dynamicChunksGroupsMask.bits2 = uint32_t(0); + destructibleParameters.dynamicChunksGroupsMask.bits3 = uint32_t(0); + destructibleParameters.runtimeFracture.RuntimeFractureType = (const char*)"VORONOI"; + destructibleParameters.runtimeFracture.sheetFracture = bool(true); + destructibleParameters.runtimeFracture.depthLimit = uint32_t(2); + destructibleParameters.runtimeFracture.destroyIfAtDepthLimit = bool(false); + destructibleParameters.runtimeFracture.minConvexSize = float(0.02); + destructibleParameters.runtimeFracture.impulseScale = float(1); + destructibleParameters.runtimeFracture.glass.numSectors = uint32_t(10); + destructibleParameters.runtimeFracture.glass.sectorRand = float(0.3); + destructibleParameters.runtimeFracture.glass.firstSegmentSize = float(0.06); + destructibleParameters.runtimeFracture.glass.segmentScale = float(1.4); + destructibleParameters.runtimeFracture.glass.segmentRand = float(0.3); + destructibleParameters.runtimeFracture.voronoi.dimensions = physx::PxVec3(physx::PxVec3(10.0f)); + destructibleParameters.runtimeFracture.voronoi.numCells = uint32_t(1); + destructibleParameters.runtimeFracture.voronoi.biasExp = float(10); + destructibleParameters.runtimeFracture.voronoi.maxDist = float(PX_MAX_F32); + destructibleParameters.runtimeFracture.attachment.posX = bool(false); + destructibleParameters.runtimeFracture.attachment.negX = bool(false); + destructibleParameters.runtimeFracture.attachment.posY = bool(false); + destructibleParameters.runtimeFracture.attachment.negY = bool(false); + destructibleParameters.runtimeFracture.attachment.posZ = bool(false); + destructibleParameters.runtimeFracture.attachment.negZ = bool(false); + destructibleParameters.supportStrength = float(-1); + destructibleParameters.legacyChunkBoundsTestSetting = int8_t(-1); + destructibleParameters.legacyDamageRadiusSpreadSetting = int8_t(-1); + destructibleParameters.alwaysDrawScatterMesh = bool(false); + userData = uint64_t(0); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void DestructibleActorState::initReferences(void) +{ + actorParameters = NULL; + + actorChunks = NULL; + +} + +void DestructibleActorState::freeDynamicArrays(void) +{ +} + +void DestructibleActorState::freeStrings(void) +{ +} + +void DestructibleActorState::freeReferences(void) +{ + if (actorParameters) + { + actorParameters->destroy(); + } + + if (actorChunks) + { + actorChunks->destroy(); + } + +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/DestructibleAssetCollisionDataSet.cpp b/APEX_1.4/module/destructible/src/autogen/DestructibleAssetCollisionDataSet.cpp new file mode 100644 index 00000000..666048ef --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/DestructibleAssetCollisionDataSet.cpp @@ -0,0 +1,525 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "DestructibleAssetCollisionDataSet.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace DestructibleAssetCollisionDataSetNS; + +const char* const DestructibleAssetCollisionDataSetFactory::vptr = + NvParameterized::getVptr<DestructibleAssetCollisionDataSet, DestructibleAssetCollisionDataSet::ClassAlignment>(); + +const uint32_t NumParamDefs = 8; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, 3, 4, 6, 5, 7, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 5 }, + { TYPE_STRING, false, (size_t)(&((ParametersStruct*)0)->assetName), NULL, 0 }, // assetName + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->cookingPlatform), NULL, 0 }, // cookingPlatform + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->cookingVersionNum), NULL, 0 }, // cookingVersionNum + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->scales), CHILDREN(5), 1 }, // scales + { TYPE_VEC3, false, 1 * sizeof(physx::PxVec3), NULL, 0 }, // scales[] + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->meshCookedCollisionStreamsAtScale), CHILDREN(6), 1 }, // meshCookedCollisionStreamsAtScale + { TYPE_REF, false, 1 * sizeof(NvParameterized::Interface*), NULL, 0 }, // meshCookedCollisionStreamsAtScale[] +}; + + +bool DestructibleAssetCollisionDataSet::mBuiltFlag = false; +NvParameterized::MutexType DestructibleAssetCollisionDataSet::mBuiltFlagMutex; + +DestructibleAssetCollisionDataSet::DestructibleAssetCollisionDataSet(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &DestructibleAssetCollisionDataSetFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +DestructibleAssetCollisionDataSet::~DestructibleAssetCollisionDataSet() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void DestructibleAssetCollisionDataSet::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~DestructibleAssetCollisionDataSet(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* DestructibleAssetCollisionDataSet::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* DestructibleAssetCollisionDataSet::getParameterDefinitionTree(void) const +{ + DestructibleAssetCollisionDataSet* tmpParam = const_cast<DestructibleAssetCollisionDataSet*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType DestructibleAssetCollisionDataSet::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType DestructibleAssetCollisionDataSet::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void DestructibleAssetCollisionDataSet::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<DestructibleAssetCollisionDataSet::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ +/* [0] - meshCookedCollisionStreamsAtScale (not an array of structs) */ + +void DestructibleAssetCollisionDataSet::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void DestructibleAssetCollisionDataSet::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="assetName" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("assetName", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The name of the asset for which convex hulls are cooked.\n A convex hull may be cooked for each chunk in the asset, for each scale in the\n scales array.", true); + HintTable[1].init("shortDescription", "The name of the asset for which convex hulls are cooked", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="cookingPlatform" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("cookingPlatform", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The cooking platform for convex cooking. Currently unused.", true); + HintTable[1].init("shortDescription", "Currently unused", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="cookingVersionNum" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("cookingVersionNum", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A version number for convex cooking. Currently unused.", true); + HintTable[1].init("shortDescription", "Currently unused", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="scales" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("scales", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "An array of scales at which chunks in the asset are cooked.\n The size of the outer array of meshCookedCollisionStreamsAtScale\n and scales must be equal.", true); + HintTable[1].init("shortDescription", "An array of scales at which chunks in the asset are cooked", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="scales[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("scales", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "An array of scales at which chunks in the asset are cooked.\n The size of the outer array of meshCookedCollisionStreamsAtScale\n and scales must be equal.", true); + HintTable[1].init("shortDescription", "An array of scales at which chunks in the asset are cooked", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=6, longName="meshCookedCollisionStreamsAtScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6]; + ParamDef->init("meshCookedCollisionStreamsAtScale", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "An array of arrays of collision hull byte streams.\n The outer array corresponds to different scales (given in the scales array).\n The inner array corresponds to different chunks within the asset.\n The size of the outer array of meshCookedCollisionStreamsAtScale\n and scales must be equal.", true); + HintTable[2].init("shortDescription", "An array of arrays of collision hull byte streams", true); + ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "MeshCookedCollisionStreamsAtScale" }; + ParamDefTable[6].setRefVariantVals((const char**)RefVariantVals, 1); + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=7, longName="meshCookedCollisionStreamsAtScale[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7]; + ParamDef->init("meshCookedCollisionStreamsAtScale", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "An array of arrays of collision hull byte streams.\n The outer array corresponds to different scales (given in the scales array).\n The inner array corresponds to different chunks within the asset.\n The size of the outer array of meshCookedCollisionStreamsAtScale\n and scales must be equal.", true); + HintTable[2].init("shortDescription", "An array of arrays of collision hull byte streams", true); + ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "MeshCookedCollisionStreamsAtScale" }; + ParamDefTable[7].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(2); + Children[2] = PDEF_PTR(3); + Children[3] = PDEF_PTR(4); + Children[4] = PDEF_PTR(6); + + ParamDefTable[0].setChildren(Children, 5); + } + + // SetChildren for: nodeIndex=4, longName="scales" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(5); + + ParamDefTable[4].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=6, longName="meshCookedCollisionStreamsAtScale" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(7); + + ParamDefTable[6].setChildren(Children, 1); + } + + mBuiltFlag = true; + +} +void DestructibleAssetCollisionDataSet::initStrings(void) +{ + assetName.isAllocated = true; + assetName.buf = NULL; +} + +void DestructibleAssetCollisionDataSet::initDynamicArrays(void) +{ + scales.buf = NULL; + scales.isAllocated = true; + scales.elementSize = sizeof(physx::PxVec3); + scales.arraySizes[0] = 0; + meshCookedCollisionStreamsAtScale.buf = NULL; + meshCookedCollisionStreamsAtScale.isAllocated = true; + meshCookedCollisionStreamsAtScale.elementSize = sizeof(NvParameterized::Interface*); + meshCookedCollisionStreamsAtScale.arraySizes[0] = 0; +} + +void DestructibleAssetCollisionDataSet::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + cookingPlatform = uint32_t(UINT32_MAX); + cookingVersionNum = uint32_t(0); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void DestructibleAssetCollisionDataSet::initReferences(void) +{ +} + +void DestructibleAssetCollisionDataSet::freeDynamicArrays(void) +{ + if (scales.isAllocated && scales.buf) + { + mParameterizedTraits->free(scales.buf); + } + if (meshCookedCollisionStreamsAtScale.isAllocated && meshCookedCollisionStreamsAtScale.buf) + { + mParameterizedTraits->free(meshCookedCollisionStreamsAtScale.buf); + } +} + +void DestructibleAssetCollisionDataSet::freeStrings(void) +{ + + if (assetName.isAllocated && assetName.buf) + { + mParameterizedTraits->strfree((char*)assetName.buf); + } +} + +void DestructibleAssetCollisionDataSet::freeReferences(void) +{ + + for (int i = 0; i < meshCookedCollisionStreamsAtScale.arraySizes[0]; ++i) + { + if (meshCookedCollisionStreamsAtScale.buf[i]) + { + meshCookedCollisionStreamsAtScale.buf[i]->destroy(); + } + } +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/DestructibleAssetParameters.cpp b/APEX_1.4/module/destructible/src/autogen/DestructibleAssetParameters.cpp new file mode 100644 index 00000000..b404970d --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/DestructibleAssetParameters.cpp @@ -0,0 +1,4829 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "DestructibleAssetParameters.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace DestructibleAssetParametersNS; + +const char* const DestructibleAssetParametersFactory::vptr = + NvParameterized::getVptr<DestructibleAssetParameters, DestructibleAssetParameters::ClassAlignment>(); + +const uint32_t NumParamDefs = 160; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, 3, 4, 5, 23, 42, 43, 55, 57, 59, 120, 131, 132, 133, 134, 135, 136, 141, 143, + 144, 146, 148, 149, 150, 151, 152, 154, 156, 158, 6, 7, 8, 9, 13, 17, 18, 19, 20, + 21, 22, 10, 11, 12, 14, 15, 16, 24, 25, 26, 27, 28, 32, 36, 37, 38, 39, 40, 41, 29, + 30, 31, 33, 34, 35, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 58, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 82, 83, 84, 85, 91, 116, 117, 118, + 119, 75, 76, 77, 78, 79, 80, 81, 86, 87, 88, 89, 90, 92, 93, 94, 95, 96, 97, 98, + 104, 109, 99, 100, 101, 102, 103, 105, 106, 107, 108, 110, 111, 112, 113, 114, 115, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 137, 138, 139, 140, 142, 145, 147, + 153, 155, 157, 159, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 30 }, + { TYPE_STRING, false, (size_t)(&((ParametersStruct*)0)->comments), NULL, 0 }, // comments + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->depthCount), NULL, 0 }, // depthCount + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->originalDepthCount), NULL, 0 }, // originalDepthCount + { TYPE_BOUNDS3, false, (size_t)(&((ParametersStruct*)0)->bounds), NULL, 0 }, // bounds + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->defaultBehaviorGroup), CHILDREN(30), 11 }, // defaultBehaviorGroup + { TYPE_STRING, false, (size_t)(&((BehaviorGroup_Type*)0)->name), NULL, 0 }, // defaultBehaviorGroup.name + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->damageThreshold), NULL, 0 }, // defaultBehaviorGroup.damageThreshold + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->damageToRadius), NULL, 0 }, // defaultBehaviorGroup.damageToRadius + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->damageSpread), CHILDREN(41), 3 }, // defaultBehaviorGroup.damageSpread + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->minimumRadius), NULL, 0 }, // defaultBehaviorGroup.damageSpread.minimumRadius + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->radiusMultiplier), NULL, 0 }, // defaultBehaviorGroup.damageSpread.radiusMultiplier + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->falloffExponent), NULL, 0 }, // defaultBehaviorGroup.damageSpread.falloffExponent + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->damageColorSpread), CHILDREN(44), 3 }, // defaultBehaviorGroup.damageColorSpread + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->minimumRadius), NULL, 0 }, // defaultBehaviorGroup.damageColorSpread.minimumRadius + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->radiusMultiplier), NULL, 0 }, // defaultBehaviorGroup.damageColorSpread.radiusMultiplier + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->falloffExponent), NULL, 0 }, // defaultBehaviorGroup.damageColorSpread.falloffExponent + { TYPE_VEC4, false, (size_t)(&((BehaviorGroup_Type*)0)->damageColorChange), NULL, 0 }, // defaultBehaviorGroup.damageColorChange + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->materialStrength), NULL, 0 }, // defaultBehaviorGroup.materialStrength + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->density), NULL, 0 }, // defaultBehaviorGroup.density + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->fadeOut), NULL, 0 }, // defaultBehaviorGroup.fadeOut + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->maxDepenetrationVelocity), NULL, 0 }, // defaultBehaviorGroup.maxDepenetrationVelocity + { TYPE_U64, false, (size_t)(&((BehaviorGroup_Type*)0)->userData), NULL, 0 }, // defaultBehaviorGroup.userData + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->behaviorGroups), CHILDREN(47), 1 }, // behaviorGroups + { TYPE_STRUCT, false, 1 * sizeof(BehaviorGroup_Type), CHILDREN(48), 11 }, // behaviorGroups[] + { TYPE_STRING, false, (size_t)(&((BehaviorGroup_Type*)0)->name), NULL, 0 }, // behaviorGroups[].name + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->damageThreshold), NULL, 0 }, // behaviorGroups[].damageThreshold + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->damageToRadius), NULL, 0 }, // behaviorGroups[].damageToRadius + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->damageSpread), CHILDREN(59), 3 }, // behaviorGroups[].damageSpread + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->minimumRadius), NULL, 0 }, // behaviorGroups[].damageSpread.minimumRadius + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->radiusMultiplier), NULL, 0 }, // behaviorGroups[].damageSpread.radiusMultiplier + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->falloffExponent), NULL, 0 }, // behaviorGroups[].damageSpread.falloffExponent + { TYPE_STRUCT, false, (size_t)(&((BehaviorGroup_Type*)0)->damageColorSpread), CHILDREN(62), 3 }, // behaviorGroups[].damageColorSpread + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->minimumRadius), NULL, 0 }, // behaviorGroups[].damageColorSpread.minimumRadius + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->radiusMultiplier), NULL, 0 }, // behaviorGroups[].damageColorSpread.radiusMultiplier + { TYPE_F32, false, (size_t)(&((DamageSpreadFunction_Type*)0)->falloffExponent), NULL, 0 }, // behaviorGroups[].damageColorSpread.falloffExponent + { TYPE_VEC4, false, (size_t)(&((BehaviorGroup_Type*)0)->damageColorChange), NULL, 0 }, // behaviorGroups[].damageColorChange + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->materialStrength), NULL, 0 }, // behaviorGroups[].materialStrength + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->density), NULL, 0 }, // behaviorGroups[].density + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->fadeOut), NULL, 0 }, // behaviorGroups[].fadeOut + { TYPE_F32, false, (size_t)(&((BehaviorGroup_Type*)0)->maxDepenetrationVelocity), NULL, 0 }, // behaviorGroups[].maxDepenetrationVelocity + { TYPE_U64, false, (size_t)(&((BehaviorGroup_Type*)0)->userData), NULL, 0 }, // behaviorGroups[].userData + { TYPE_I8, false, (size_t)(&((ParametersStruct*)0)->RTFractureBehaviorGroup), NULL, 0 }, // RTFractureBehaviorGroup + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->chunks), CHILDREN(65), 1 }, // chunks + { TYPE_STRUCT, false, 1 * sizeof(Chunk_Type), CHILDREN(66), 10 }, // chunks[] + { TYPE_U16, false, (size_t)(&((Chunk_Type*)0)->depth), NULL, 0 }, // chunks[].depth + { TYPE_U16, false, (size_t)(&((Chunk_Type*)0)->parentIndex), NULL, 0 }, // chunks[].parentIndex + { TYPE_U16, false, (size_t)(&((Chunk_Type*)0)->firstChildIndex), NULL, 0 }, // chunks[].firstChildIndex + { TYPE_U16, false, (size_t)(&((Chunk_Type*)0)->numChildren), NULL, 0 }, // chunks[].numChildren + { TYPE_U16, false, (size_t)(&((Chunk_Type*)0)->meshPartIndex), NULL, 0 }, // chunks[].meshPartIndex + { TYPE_U16, false, (size_t)(&((Chunk_Type*)0)->flags), NULL, 0 }, // chunks[].flags + { TYPE_VEC3, false, (size_t)(&((Chunk_Type*)0)->surfaceNormal), NULL, 0 }, // chunks[].surfaceNormal + { TYPE_I8, false, (size_t)(&((Chunk_Type*)0)->behaviorGroupIndex), NULL, 0 }, // chunks[].behaviorGroupIndex + { TYPE_U16, false, (size_t)(&((Chunk_Type*)0)->firstScatterMesh), NULL, 0 }, // chunks[].firstScatterMesh + { TYPE_U16, false, (size_t)(&((Chunk_Type*)0)->scatterMeshCount), NULL, 0 }, // chunks[].scatterMeshCount + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->chunkConvexHulls), CHILDREN(76), 1 }, // chunkConvexHulls + { TYPE_REF, false, 1 * sizeof(NvParameterized::Interface*), NULL, 0 }, // chunkConvexHulls[] + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->chunkConvexHullStartIndices), CHILDREN(77), 1 }, // chunkConvexHullStartIndices + { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // chunkConvexHullStartIndices[] + { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->destructibleParameters), CHILDREN(78), 24 }, // destructibleParameters + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->damageCap), NULL, 0 }, // destructibleParameters.damageCap + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->forceToDamage), NULL, 0 }, // destructibleParameters.forceToDamage + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->impactVelocityThreshold), NULL, 0 }, // destructibleParameters.impactVelocityThreshold + { TYPE_U32, false, (size_t)(&((DestructibleParameters_Type*)0)->minimumFractureDepth), NULL, 0 }, // destructibleParameters.minimumFractureDepth + { TYPE_I32, false, (size_t)(&((DestructibleParameters_Type*)0)->impactDamageDefaultDepth), NULL, 0 }, // destructibleParameters.impactDamageDefaultDepth + { TYPE_I32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisDepth), NULL, 0 }, // destructibleParameters.debrisDepth + { TYPE_U32, false, (size_t)(&((DestructibleParameters_Type*)0)->essentialDepth), NULL, 0 }, // destructibleParameters.essentialDepth + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisLifetimeMin), NULL, 0 }, // destructibleParameters.debrisLifetimeMin + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisLifetimeMax), NULL, 0 }, // destructibleParameters.debrisLifetimeMax + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisMaxSeparationMin), NULL, 0 }, // destructibleParameters.debrisMaxSeparationMin + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisMaxSeparationMax), NULL, 0 }, // destructibleParameters.debrisMaxSeparationMax + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->debrisDestructionProbability), NULL, 0 }, // destructibleParameters.debrisDestructionProbability + { TYPE_BOUNDS3, false, (size_t)(&((DestructibleParameters_Type*)0)->validBounds), NULL, 0 }, // destructibleParameters.validBounds + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->maxChunkSpeed), NULL, 0 }, // destructibleParameters.maxChunkSpeed + { TYPE_STRUCT, false, (size_t)(&((DestructibleParameters_Type*)0)->flags), CHILDREN(102), 7 }, // destructibleParameters.flags + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->ACCUMULATE_DAMAGE), NULL, 0 }, // destructibleParameters.flags.ACCUMULATE_DAMAGE + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->DEBRIS_TIMEOUT), NULL, 0 }, // destructibleParameters.flags.DEBRIS_TIMEOUT + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->DEBRIS_MAX_SEPARATION), NULL, 0 }, // destructibleParameters.flags.DEBRIS_MAX_SEPARATION + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->CRUMBLE_SMALLEST_CHUNKS), NULL, 0 }, // destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->ACCURATE_RAYCASTS), NULL, 0 }, // destructibleParameters.flags.ACCURATE_RAYCASTS + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->USE_VALID_BOUNDS), NULL, 0 }, // destructibleParameters.flags.USE_VALID_BOUNDS + { TYPE_BOOL, false, (size_t)(&((DestructibleParametersFlag_Type*)0)->CRUMBLE_VIA_RUNTIME_FRACTURE), NULL, 0 }, // destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->fractureImpulseScale), NULL, 0 }, // destructibleParameters.fractureImpulseScale + { TYPE_U16, false, (size_t)(&((DestructibleParameters_Type*)0)->damageDepthLimit), NULL, 0 }, // destructibleParameters.damageDepthLimit + { TYPE_U16, false, (size_t)(&((DestructibleParameters_Type*)0)->dynamicChunkDominanceGroup), NULL, 0 }, // destructibleParameters.dynamicChunkDominanceGroup + { TYPE_STRUCT, false, (size_t)(&((DestructibleParameters_Type*)0)->dynamicChunksGroupsMask), CHILDREN(109), 5 }, // destructibleParameters.dynamicChunksGroupsMask + { TYPE_BOOL, false, (size_t)(&((GroupsMask_Type*)0)->useGroupsMask), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.useGroupsMask + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits0), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits0 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits1), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits1 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits2), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits2 + { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits3), NULL, 0 }, // destructibleParameters.dynamicChunksGroupsMask.bits3 + { TYPE_STRUCT, false, (size_t)(&((DestructibleParameters_Type*)0)->runtimeFracture), CHILDREN(114), 9 }, // destructibleParameters.runtimeFracture + { TYPE_ENUM, false, (size_t)(&((RuntimeFracture_Type*)0)->RuntimeFractureType), NULL, 0 }, // destructibleParameters.runtimeFracture.RuntimeFractureType + { TYPE_BOOL, false, (size_t)(&((RuntimeFracture_Type*)0)->sheetFracture), NULL, 0 }, // destructibleParameters.runtimeFracture.sheetFracture + { TYPE_U32, false, (size_t)(&((RuntimeFracture_Type*)0)->depthLimit), NULL, 0 }, // destructibleParameters.runtimeFracture.depthLimit + { TYPE_BOOL, false, (size_t)(&((RuntimeFracture_Type*)0)->destroyIfAtDepthLimit), NULL, 0 }, // destructibleParameters.runtimeFracture.destroyIfAtDepthLimit + { TYPE_F32, false, (size_t)(&((RuntimeFracture_Type*)0)->minConvexSize), NULL, 0 }, // destructibleParameters.runtimeFracture.minConvexSize + { TYPE_F32, false, (size_t)(&((RuntimeFracture_Type*)0)->impulseScale), NULL, 0 }, // destructibleParameters.runtimeFracture.impulseScale + { TYPE_STRUCT, false, (size_t)(&((RuntimeFracture_Type*)0)->glass), CHILDREN(123), 5 }, // destructibleParameters.runtimeFracture.glass + { TYPE_U32, false, (size_t)(&((FractureGlass_Type*)0)->numSectors), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.numSectors + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->sectorRand), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.sectorRand + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->firstSegmentSize), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.firstSegmentSize + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->segmentScale), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.segmentScale + { TYPE_F32, false, (size_t)(&((FractureGlass_Type*)0)->segmentRand), NULL, 0 }, // destructibleParameters.runtimeFracture.glass.segmentRand + { TYPE_STRUCT, false, (size_t)(&((RuntimeFracture_Type*)0)->voronoi), CHILDREN(128), 4 }, // destructibleParameters.runtimeFracture.voronoi + { TYPE_VEC3, false, (size_t)(&((FractureVoronoi_Type*)0)->dimensions), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.dimensions + { TYPE_U32, false, (size_t)(&((FractureVoronoi_Type*)0)->numCells), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.numCells + { TYPE_F32, false, (size_t)(&((FractureVoronoi_Type*)0)->biasExp), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.biasExp + { TYPE_F32, false, (size_t)(&((FractureVoronoi_Type*)0)->maxDist), NULL, 0 }, // destructibleParameters.runtimeFracture.voronoi.maxDist + { TYPE_STRUCT, false, (size_t)(&((RuntimeFracture_Type*)0)->attachment), CHILDREN(132), 6 }, // destructibleParameters.runtimeFracture.attachment + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->posX), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.posX + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->negX), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.negX + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->posY), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.posY + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->negY), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.negY + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->posZ), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.posZ + { TYPE_BOOL, false, (size_t)(&((FractureAttachment_Type*)0)->negZ), NULL, 0 }, // destructibleParameters.runtimeFracture.attachment.negZ + { TYPE_F32, false, (size_t)(&((DestructibleParameters_Type*)0)->supportStrength), NULL, 0 }, // destructibleParameters.supportStrength + { TYPE_I8, false, (size_t)(&((DestructibleParameters_Type*)0)->legacyChunkBoundsTestSetting), NULL, 0 }, // destructibleParameters.legacyChunkBoundsTestSetting + { TYPE_I8, false, (size_t)(&((DestructibleParameters_Type*)0)->legacyDamageRadiusSpreadSetting), NULL, 0 }, // destructibleParameters.legacyDamageRadiusSpreadSetting + { TYPE_BOOL, false, (size_t)(&((DestructibleParameters_Type*)0)->alwaysDrawScatterMesh), NULL, 0 }, // destructibleParameters.alwaysDrawScatterMesh + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->depthParameters), CHILDREN(138), 1 }, // depthParameters + { TYPE_STRUCT, false, 1 * sizeof(DestructibleDepthParameters_Type), CHILDREN(139), 9 }, // depthParameters[] + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->OVERRIDE_IMPACT_DAMAGE), NULL, 0 }, // depthParameters[].OVERRIDE_IMPACT_DAMAGE + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->OVERRIDE_IMPACT_DAMAGE_VALUE), NULL, 0 }, // depthParameters[].OVERRIDE_IMPACT_DAMAGE_VALUE + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->IGNORE_POSE_UPDATES), NULL, 0 }, // depthParameters[].IGNORE_POSE_UPDATES + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->IGNORE_RAYCAST_CALLBACKS), NULL, 0 }, // depthParameters[].IGNORE_RAYCAST_CALLBACKS + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->IGNORE_CONTACT_CALLBACKS), NULL, 0 }, // depthParameters[].IGNORE_CONTACT_CALLBACKS + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->USER_FLAG_0), NULL, 0 }, // depthParameters[].USER_FLAG_0 + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->USER_FLAG_1), NULL, 0 }, // depthParameters[].USER_FLAG_1 + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->USER_FLAG_2), NULL, 0 }, // depthParameters[].USER_FLAG_2 + { TYPE_BOOL, false, (size_t)(&((DestructibleDepthParameters_Type*)0)->USER_FLAG_3), NULL, 0 }, // depthParameters[].USER_FLAG_3 + { TYPE_STRING, false, (size_t)(&((ParametersStruct*)0)->crumbleEmitterName), NULL, 0 }, // crumbleEmitterName + { TYPE_STRING, false, (size_t)(&((ParametersStruct*)0)->dustEmitterName), NULL, 0 }, // dustEmitterName + { TYPE_REF, false, (size_t)(&((ParametersStruct*)0)->collisionData), NULL, 0 }, // collisionData + { TYPE_REF, false, (size_t)(&((ParametersStruct*)0)->renderMeshAsset), NULL, 0 }, // renderMeshAsset + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->initialDestructibleActorAllowanceForInstancing), NULL, 0 }, // initialDestructibleActorAllowanceForInstancing + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->chunkInstanceInfo), CHILDREN(148), 1 }, // chunkInstanceInfo + { TYPE_STRUCT, false, 1 * sizeof(InstanceInfo_Type), CHILDREN(149), 3 }, // chunkInstanceInfo[] + { TYPE_U16, false, (size_t)(&((InstanceInfo_Type*)0)->partIndex), NULL, 0 }, // chunkInstanceInfo[].partIndex + { TYPE_VEC3, false, (size_t)(&((InstanceInfo_Type*)0)->chunkPositionOffset), NULL, 0 }, // chunkInstanceInfo[].chunkPositionOffset + { TYPE_VEC2, false, (size_t)(&((InstanceInfo_Type*)0)->chunkUVOffset), NULL, 0 }, // chunkInstanceInfo[].chunkUVOffset + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->staticMaterialNames), CHILDREN(152), 1 }, // staticMaterialNames + { TYPE_STRING, false, 1 * sizeof(NvParameterized::DummyStringStruct), NULL, 0 }, // staticMaterialNames[] + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->neighborPadding), NULL, 0 }, // neighborPadding + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->overlapsAtDepth), CHILDREN(153), 1 }, // overlapsAtDepth + { TYPE_REF, false, 1 * sizeof(NvParameterized::Interface*), NULL, 0 }, // overlapsAtDepth[] + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->firstChunkAtDepth), CHILDREN(154), 1 }, // firstChunkAtDepth + { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // firstChunkAtDepth[] + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->supportDepth), NULL, 0 }, // supportDepth + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->formExtendedStructures), NULL, 0 }, // formExtendedStructures + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->useAssetDefinedSupport), NULL, 0 }, // useAssetDefinedSupport + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->useWorldSupport), NULL, 0 }, // useWorldSupport + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->actorTransforms), CHILDREN(155), 1 }, // actorTransforms + { TYPE_MAT44, false, 1 * sizeof(physx::PxMat44), NULL, 0 }, // actorTransforms[] + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->scatterMeshAssets), CHILDREN(156), 1 }, // scatterMeshAssets + { TYPE_REF, false, 1 * sizeof(NvParameterized::Interface*), NULL, 0 }, // scatterMeshAssets[] + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->scatterMeshIndices), CHILDREN(157), 1 }, // scatterMeshIndices + { TYPE_U8, false, 1 * sizeof(uint8_t), NULL, 0 }, // scatterMeshIndices[] + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->scatterMeshTransforms), CHILDREN(158), 1 }, // scatterMeshTransforms + { TYPE_MAT44, false, 1 * sizeof(physx::PxMat44), NULL, 0 }, // scatterMeshTransforms[] +}; + + +bool DestructibleAssetParameters::mBuiltFlag = false; +NvParameterized::MutexType DestructibleAssetParameters::mBuiltFlagMutex; + +DestructibleAssetParameters::DestructibleAssetParameters(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &DestructibleAssetParametersFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +DestructibleAssetParameters::~DestructibleAssetParameters() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void DestructibleAssetParameters::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~DestructibleAssetParameters(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* DestructibleAssetParameters::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* DestructibleAssetParameters::getParameterDefinitionTree(void) const +{ + DestructibleAssetParameters* tmpParam = const_cast<DestructibleAssetParameters*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType DestructibleAssetParameters::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType DestructibleAssetParameters::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void DestructibleAssetParameters::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<DestructibleAssetParameters::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ +/* [1,0] - behaviorGroups.name */ +/* [0] - chunkConvexHulls (not an array of structs) */ +/* [0] - staticMaterialNames (not an array of structs) */ +/* [0] - overlapsAtDepth (not an array of structs) */ +/* [0] - scatterMeshAssets (not an array of structs) */ + +void DestructibleAssetParameters::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void DestructibleAssetParameters::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="comments" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("comments", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Human-readable string which describes which tool created this asset, its version, etc.", true); + HintTable[1].init("shortDescription", "Human-readable string which describes which tool created this asset, its version, etc.", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="depthCount" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("depthCount", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The number of chunk depth levels. This is 1 for an unfractured mesh.", true); + HintTable[1].init("shortDescription", "The number of chunk depth levels", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="originalDepthCount" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("originalDepthCount", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The depth count when authored - this way we can tell how far it's been reduced.", true); + HintTable[1].init("shortDescription", "The depth count when authored", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="bounds" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("bounds", TYPE_BOUNDS3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The axis-aligned bounding box of the destructible asset. This is the smallest AABB\n which contains all chunk AABBs.", true); + HintTable[1].init("shortDescription", "The AABB of the destructible asset", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="defaultBehaviorGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("defaultBehaviorGroup", TYPE_STRUCT, "BehaviorGroup", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The default behavior group referenced by chunks. Each chunk references a behavior group for chunk-specific reactions.", true); + HintTable[1].init("shortDescription", "The default behavior group referenced by chunks", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=6, longName="defaultBehaviorGroup.name" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6]; + ParamDef->init("name", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Name of behavior group, eg Concrete or Glass.", true); + HintTable[1].init("shortDescription", "Name of behavior group", true); + ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=7, longName="defaultBehaviorGroup.damageThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7]; + ParamDef->init("damageThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The damage amount which will cause a chunk to fracture (break free) from the destructible.\n This is obtained from the damage value passed into the DestructibleActor::applyDamage,\n or DestructibleActor::applyRadiusDamage, or via impact (see 'forceToDamage', below).", true); + HintTable[1].init("shortDescription", "The damage amount which will cause a chunk to fracture (break free) from the destructible.", true); + ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=8, longName="defaultBehaviorGroup.damageToRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8]; + ParamDef->init("damageToRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Controls the distance into the destructible to propagate damage. The damage applied to the chunk\n is multiplied by damageToRadius, to get the propagation distance. All chunks within the radius\n will have damage applied to them. The damage applied to each chunk varies with distance to the damage\n application position. Full damage is taken at zero distance, and zero damage at the damage radius.\n NOTE: This parameter is deprecated for point and radius damage. It will be used for those types of damage if legacy damage\n behavior is enabled with ModuleDestructible::setUseLegacyDamageRadiusSpread. Otherwise, the new parameters\n damageSpread.minimumRadius, damageSpread.radiusMultiplier, and damageSpread.falloffExponent are used. For impact damage, this parameter\n will continue to be used, however the radius will no longer scale with object size. The radius will continue\n to scale with the damage as a fraction of damageThreshold, however. If legacy damage behavior is used, this parameter\n will behave as before with respect to impact damage as well (scaling with object size).", true); + HintTable[1].init("shortDescription", "Controls the distance into the destructible to propagate damage.", true); + ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=9, longName="defaultBehaviorGroup.damageSpread" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9]; + ParamDef->init("damageSpread", TYPE_STRUCT, "DamageSpreadFunction", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes the radius and damage envelope function for damage applied to the destructible.", true); + HintTable[1].init("shortDescription", "Describes the radius and damage envelope function for damage applied to the destructible.", true); + ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=10, longName="defaultBehaviorGroup.damageSpread.minimumRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10]; + ParamDef->init("minimumRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum radius of damage spread when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "The minimum radius of damage spread when damage is applied.", true); + ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=11, longName="defaultBehaviorGroup.damageSpread.radiusMultiplier" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11]; + ParamDef->init("radiusMultiplier", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A scale to apply to the input damage radius when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "A scale to apply to the input damage radius when damage is applied.", true); + ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=12, longName="defaultBehaviorGroup.damageSpread.falloffExponent" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12]; + ParamDef->init("falloffExponent", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How damage varies between the minimum radius and the calculated damage radius. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.\n Within the minimumRadius, the full damage is applied to chunks. Past the minimumRadius, the formla for damage is:\n damage = (input damage) * ((radius - distance)/(radius - minimumRadius))^falloffExponent.\n Note: falloffExponent = 0.0 gives no falloff, so that damage = (input damage) over the entire range [0, radius).\n falloffExponent = 1.0 gives linear falloff.", true); + HintTable[1].init("shortDescription", "How damage varies between the minimum radius and the calculated damage radius.", true); + ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=13, longName="defaultBehaviorGroup.damageColorSpread" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13]; + ParamDef->init("damageColorSpread", TYPE_STRUCT, "DamageSpreadFunction", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes the radius and damage envelope function for color channel damage modification applied to the destructible.", true); + HintTable[1].init("shortDescription", "Describes the radius and damage envelope function for color channel damage modification applied to the destructible.", true); + ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=14, longName="defaultBehaviorGroup.damageColorSpread.minimumRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14]; + ParamDef->init("minimumRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum radius of damage spread when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "The minimum radius of damage spread when damage is applied.", true); + ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=15, longName="defaultBehaviorGroup.damageColorSpread.radiusMultiplier" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15]; + ParamDef->init("radiusMultiplier", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A scale to apply to the input damage radius when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "A scale to apply to the input damage radius when damage is applied.", true); + ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=16, longName="defaultBehaviorGroup.damageColorSpread.falloffExponent" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16]; + ParamDef->init("falloffExponent", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How damage varies between the minimum radius and the calculated damage radius. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.\n Within the minimumRadius, the full damage is applied to chunks. Past the minimumRadius, the formla for damage is:\n damage = (input damage) * ((radius - distance)/(radius - minimumRadius))^falloffExponent.\n Note: falloffExponent = 0.0 gives no falloff, so that damage = (input damage) over the entire range [0, radius).\n falloffExponent = 1.0 gives linear falloff.", true); + HintTable[1].init("shortDescription", "How damage varies between the minimum radius and the calculated damage radius.", true); + ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=17, longName="defaultBehaviorGroup.damageColorChange" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17]; + ParamDef->init("damageColorChange", TYPE_VEC4, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes how damage changes the color of vertices in the render mesh. If this vector is non-zero, then a dynamic\n (per-actor) color channel will be created and initialized to the asset's color channel, if it exists. Damage taken will go through\n the spread and envelope function described by damageColoring, and each color will be modified by the resulting damage, scaled\n by the values in damageColorChange. The change to color channel C is given by\n color[C] = clamp(color[C] + damageColorChange[C]*255*min(1.0, damage/damageThreshold), 0, 255).", true); + HintTable[1].init("shortDescription", "Describes how damage changes the color of vertices in the render mesh.", true); + ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=18, longName="defaultBehaviorGroup.materialStrength" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18]; + ParamDef->init("materialStrength", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "When a chunk takes impact damage due to physical contact (see see DestructibleDepthParameters), this parameter\n is the maximum impulse the contact can generate. Weak materials such as glass may have this set to a low value, so that\n heavier objects will pass through them during fracture.\n N.B.: Setting this parameter to 0 disables the impulse cap; that is, zero is interpreted as infinite.\n Default value = 0.0f.", true); + HintTable[1].init("shortDescription", "When a chunk takes impact, this is the maximum impulse the contact can generate.", true); + ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=19, longName="defaultBehaviorGroup.density" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19]; + ParamDef->init("density", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk density. (TODO: better description)", true); + HintTable[1].init("shortDescription", "Chunk density", true); + ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=20, longName="defaultBehaviorGroup.fadeOut" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20]; + ParamDef->init("fadeOut", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk fade out. (TODO: better description)", true); + HintTable[1].init("shortDescription", "Chunk fade out", true); + ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=21, longName="defaultBehaviorGroup.maxDepenetrationVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21]; + ParamDef->init("maxDepenetrationVelocity", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "In case some chunk is created inside static geometry it will be pushed out of it without limiting it's velocity. Sometimes it's not desirable, \n so this parameter can limit depenetration velocity. Keep in mind, that for low values you can see chunks 'floating' off the static meshes, which is also not always desirable.", true); + HintTable[1].init("shortDescription", "Chunk maximum depenetration velocity", true); + ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=22, longName="defaultBehaviorGroup.userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User data field. This 64-bit field can be set and retrieved by the user at runtime.", true); + HintTable[1].init("shortDescription", "User data field.", true); + ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=23, longName="behaviorGroups" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23]; + ParamDef->init("behaviorGroups", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The array of behavior groups referenced by chunks. Each chunk references a behavior group for chunk-specific reactions.", true); + HintTable[1].init("shortDescription", "The array of behavior groups referenced by chunks", true); + ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[2] = { 1, 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 2); + + } + + // Initialize DefinitionImpl node: nodeIndex=24, longName="behaviorGroups[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24]; + ParamDef->init("behaviorGroups", TYPE_STRUCT, "BehaviorGroup", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The array of behavior groups referenced by chunks. Each chunk references a behavior group for chunk-specific reactions.", true); + HintTable[1].init("shortDescription", "The array of behavior groups referenced by chunks", true); + ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=25, longName="behaviorGroups[].name" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25]; + ParamDef->init("name", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Name of behavior group, eg Concrete or Glass.", true); + HintTable[1].init("shortDescription", "Name of behavior group", true); + ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=26, longName="behaviorGroups[].damageThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26]; + ParamDef->init("damageThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The damage amount which will cause a chunk to fracture (break free) from the destructible.\n This is obtained from the damage value passed into the DestructibleActor::applyDamage,\n or DestructibleActor::applyRadiusDamage, or via impact (see 'forceToDamage', below).", true); + HintTable[1].init("shortDescription", "The damage amount which will cause a chunk to fracture (break free) from the destructible.", true); + ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=27, longName="behaviorGroups[].damageToRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27]; + ParamDef->init("damageToRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Controls the distance into the destructible to propagate damage. The damage applied to the chunk\n is multiplied by damageToRadius, to get the propagation distance. All chunks within the radius\n will have damage applied to them. The damage applied to each chunk varies with distance to the damage\n application position. Full damage is taken at zero distance, and zero damage at the damage radius.\n NOTE: This parameter is deprecated for point and radius damage. It will be used for those types of damage if legacy damage\n behavior is enabled with ModuleDestructible::setUseLegacyDamageRadiusSpread. Otherwise, the new parameters\n damageSpread.minimumRadius, damageSpread.radiusMultiplier, and damageSpread.falloffExponent are used. For impact damage, this parameter\n will continue to be used, however the radius will no longer scale with object size. The radius will continue\n to scale with the damage as a fraction of damageThreshold, however. If legacy damage behavior is used, this parameter\n will behave as before with respect to impact damage as well (scaling with object size).", true); + HintTable[1].init("shortDescription", "Controls the distance into the destructible to propagate damage.", true); + ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=28, longName="behaviorGroups[].damageSpread" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28]; + ParamDef->init("damageSpread", TYPE_STRUCT, "DamageSpreadFunction", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes the radius and damage envelope function for damage applied to the destructible.", true); + HintTable[1].init("shortDescription", "Describes the radius and damage envelope function for damage applied to the destructible.", true); + ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=29, longName="behaviorGroups[].damageSpread.minimumRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29]; + ParamDef->init("minimumRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum radius of damage spread when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "The minimum radius of damage spread when damage is applied.", true); + ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=30, longName="behaviorGroups[].damageSpread.radiusMultiplier" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30]; + ParamDef->init("radiusMultiplier", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A scale to apply to the input damage radius when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "A scale to apply to the input damage radius when damage is applied.", true); + ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=31, longName="behaviorGroups[].damageSpread.falloffExponent" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31]; + ParamDef->init("falloffExponent", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How damage varies between the minimum radius and the calculated damage radius. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.\n Within the minimumRadius, the full damage is applied to chunks. Past the minimumRadius, the formla for damage is:\n damage = (input damage) * ((radius - distance)/(radius - minimumRadius))^falloffExponent.\n Note: falloffExponent = 0.0 gives no falloff, so that damage = (input damage) over the entire range [0, radius).\n falloffExponent = 1.0 gives linear falloff.", true); + HintTable[1].init("shortDescription", "How damage varies between the minimum radius and the calculated damage radius.", true); + ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=32, longName="behaviorGroups[].damageColorSpread" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32]; + ParamDef->init("damageColorSpread", TYPE_STRUCT, "DamageSpreadFunction", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes the radius and damage envelope function for color channel damage modification applied to the destructible.", true); + HintTable[1].init("shortDescription", "Describes the radius and damage envelope function for color channel damage modification applied to the destructible.", true); + ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=33, longName="behaviorGroups[].damageColorSpread.minimumRadius" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33]; + ParamDef->init("minimumRadius", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum radius of damage spread when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "The minimum radius of damage spread when damage is applied.", true); + ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=34, longName="behaviorGroups[].damageColorSpread.radiusMultiplier" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34]; + ParamDef->init("radiusMultiplier", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A scale to apply to the input damage radius when damage is applied. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.", true); + HintTable[1].init("shortDescription", "A scale to apply to the input damage radius when damage is applied.", true); + ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=35, longName="behaviorGroups[].damageColorSpread.falloffExponent" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35]; + ParamDef->init("falloffExponent", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How damage varies between the minimum radius and the calculated damage radius. The formula for the damage radius is\n radius = minimumRadius + (input radius) * radiusMultiplier.\n Within the minimumRadius, the full damage is applied to chunks. Past the minimumRadius, the formla for damage is:\n damage = (input damage) * ((radius - distance)/(radius - minimumRadius))^falloffExponent.\n Note: falloffExponent = 0.0 gives no falloff, so that damage = (input damage) over the entire range [0, radius).\n falloffExponent = 1.0 gives linear falloff.", true); + HintTable[1].init("shortDescription", "How damage varies between the minimum radius and the calculated damage radius.", true); + ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=36, longName="behaviorGroups[].damageColorChange" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36]; + ParamDef->init("damageColorChange", TYPE_VEC4, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Describes how damage changes the color of vertices in the render mesh. If this vector is non-zero, then a dynamic\n (per-actor) color channel will be created and initialized to the asset's color channel, if it exists. Damage taken will go through\n the spread and envelope function described by damageColoring, and each color will be modified by the resulting damage, scaled\n by the values in damageColorChange. The change to color channel C is given by\n color[C] = clamp(color[C] + damageColorChange[C]*255*min(1.0, damage/damageThreshold), 0, 255).", true); + HintTable[1].init("shortDescription", "Describes how damage changes the color of vertices in the render mesh.", true); + ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=37, longName="behaviorGroups[].materialStrength" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37]; + ParamDef->init("materialStrength", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "When a chunk takes impact damage due to physical contact (see see DestructibleDepthParameters), this parameter\n is the maximum impulse the contact can generate. Weak materials such as glass may have this set to a low value, so that\n heavier objects will pass through them during fracture.\n N.B.: Setting this parameter to 0 disables the impulse cap; that is, zero is interpreted as infinite.\n Default value = 0.0f.", true); + HintTable[1].init("shortDescription", "When a chunk takes impact, this is the maximum impulse the contact can generate.", true); + ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=38, longName="behaviorGroups[].density" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38]; + ParamDef->init("density", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk density. (TODO: better description)", true); + HintTable[1].init("shortDescription", "Chunk density", true); + ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=39, longName="behaviorGroups[].fadeOut" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39]; + ParamDef->init("fadeOut", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk fade out. (TODO: better description)", true); + HintTable[1].init("shortDescription", "Chunk fade out", true); + ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=40, longName="behaviorGroups[].maxDepenetrationVelocity" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40]; + ParamDef->init("maxDepenetrationVelocity", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "In case some chunk is created inside static geometry it will be pushed out of it without limiting it's velocity. Sometimes it's not desirable, \n so this parameter can limit depenetration velocity. Keep in mind, that for low values you can see chunks 'floating' off the static meshes, which is also not always desirable.", true); + HintTable[1].init("shortDescription", "Chunk maximum depenetration velocity", true); + ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=41, longName="behaviorGroups[].userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[41]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User data field. This 64-bit field can be set and retrieved by the user at runtime.", true); + HintTable[1].init("shortDescription", "User data field.", true); + ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=42, longName="RTFractureBehaviorGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[42]; + ParamDef->init("RTFractureBehaviorGroup", TYPE_I8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The array of behavior groups referenced by chunks. Each chunk references a behavior group for chunk-specific reactions.", true); + HintTable[1].init("shortDescription", "The array of behavior groups referenced by chunks", true); + ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=43, longName="chunks" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[43]; + ParamDef->init("chunks", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The array of chunks. Chunks are stored breadth-first in their hierarchy.", true); + HintTable[1].init("shortDescription", "The array of chunks", true); + ParamDefTable[43].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=44, longName="chunks[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[44]; + ParamDef->init("chunks", TYPE_STRUCT, "Chunk", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The array of chunks. Chunks are stored breadth-first in their hierarchy.", true); + HintTable[1].init("shortDescription", "The array of chunks", true); + ParamDefTable[44].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=45, longName="chunks[].depth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[45]; + ParamDef->init("depth", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The depth of the chunk in the hierarchy.\n Level 0 chunks correspond to the unfractured (original) mesh. Level 1 chunks\n are their children, formed by splitting level 0 chunks, etc.", true); + HintTable[1].init("shortDescription", "The depth of the chunk in the hierarchy", true); + ParamDefTable[45].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=46, longName="chunks[].parentIndex" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[46]; + ParamDef->init("parentIndex", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The index of the chunk's parent in the hierarchy.\n If the chunk has no parent (its depth is 0), then the parentIndex is -1.", true); + HintTable[1].init("shortDescription", "The index of the chunk's parent in the hierarchy", true); + ParamDefTable[46].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=47, longName="chunks[].firstChildIndex" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[47]; + ParamDef->init("firstChildIndex", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The index of this chunk's first child in the hierarchy.\n All children have contiguous chunk indices, and lie in the range\n [firstChildIndex,firstChildIndex+numChildren-1]. If the chunk has no children,\n this value is undefined.", true); + HintTable[1].init("shortDescription", "The index of this chunk's first child in the hierarchy", true); + ParamDefTable[47].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=48, longName="chunks[].numChildren" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[48]; + ParamDef->init("numChildren", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "This chunk's number of children. If not 0, firstChildIndex\n is valid (see firstChildIndex).", true); + HintTable[1].init("shortDescription", "This chunk's number of children", true); + ParamDefTable[48].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=49, longName="chunks[].meshPartIndex" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[49]; + ParamDef->init("meshPartIndex", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If this chunk is not instanced, this is the corresponding mesh part for this chunk,\n in the ApexRenderMeshAsset included within this destructible asset. If this chunk is instanced,\n this refers to the InstanceInfo in the asset (see InstanceInfo).", true); + HintTable[1].init("shortDescription", "The corresponding mesh part for this chunk", true); + ParamDefTable[49].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=50, longName="chunks[].flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[50]; + ParamDef->init("flags", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[50].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("longDescription", "Flags which define individual chunk attributes, such as support,\n fractureability, etc.", true); + HintTable[2].init("shortDescription", "Flags which define individual chunk attributes", true); + ParamDefTable[50].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=51, longName="chunks[].surfaceNormal" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[51]; + ParamDef->init("surfaceNormal", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The average surface normal of this chunk. This is the normalized\n average of all triangle normals which are part of the original (unfractured) mesh.", true); + HintTable[1].init("shortDescription", "The average surface normal of this chunk", true); + ParamDefTable[51].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=52, longName="chunks[].behaviorGroupIndex" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[52]; + ParamDef->init("behaviorGroupIndex", TYPE_I8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Behavior group this chunk is associated with. This includes flags, damage threshold, density, impact\n resistance, and collision mask.", true); + HintTable[1].init("shortDescription", "Behavior group this chunk is associated with", true); + ParamDefTable[52].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=53, longName="chunks[].firstScatterMesh" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[53]; + ParamDef->init("firstScatterMesh", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Index of first scatter mesh (in scatterMeshIndices and scatterMeshTransforms).", true); + HintTable[1].init("shortDescription", "Index of first scatter mesh (in scatterMeshIndices and scatterMeshTransforms)", true); + ParamDefTable[53].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=54, longName="chunks[].scatterMeshCount" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[54]; + ParamDef->init("scatterMeshCount", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of scatter meshes (in scatterMeshIndices and scatterMeshTransforms).", true); + HintTable[1].init("shortDescription", "Number of scatter meshes (in scatterMeshIndices and scatterMeshTransforms)", true); + ParamDefTable[54].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=55, longName="chunkConvexHulls" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[55]; + ParamDef->init("chunkConvexHulls", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[55].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "Convex hull data for each chunk. This is not cooked convex hull data\n used for PhysX collision. These hulls are used to (a) create cooked PhysX convex hulls, and (b)\n for APEX scene queries.", true); + HintTable[2].init("shortDescription", "Convex hull data for each chunk", true); + ParamDefTable[55].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "ConvexHullParameters" }; + ParamDefTable[55].setRefVariantVals((const char**)RefVariantVals, 1); + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=56, longName="chunkConvexHulls[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[56]; + ParamDef->init("chunkConvexHulls", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[56].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "Convex hull data for each chunk. This is not cooked convex hull data\n used for PhysX collision. These hulls are used to (a) create cooked PhysX convex hulls, and (b)\n for APEX scene queries.", true); + HintTable[2].init("shortDescription", "Convex hull data for each chunk", true); + ParamDefTable[56].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "ConvexHullParameters" }; + ParamDefTable[56].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // Initialize DefinitionImpl node: nodeIndex=57, longName="chunkConvexHullStartIndices" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[57]; + ParamDef->init("chunkConvexHullStartIndices", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Map into array of convex hulls. The convex hulls for chunk i are in\n the chunkConvexHulls array, starting at chunkConvexHulls[i], and ending at chunkConvexHulls[i+1]-1.\n The array length is one greater than that of chunkConvexHulls.", true); + HintTable[1].init("shortDescription", "Map into array of convex hulls", true); + ParamDefTable[57].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=58, longName="chunkConvexHullStartIndices[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[58]; + ParamDef->init("chunkConvexHullStartIndices", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Map into array of convex hulls. The convex hulls for chunk i are in\n the chunkConvexHulls array, starting at chunkConvexHulls[i], and ending at chunkConvexHulls[i+1]-1.\n The array length is one greater than that of chunkConvexHulls.", true); + HintTable[1].init("shortDescription", "Map into array of convex hulls", true); + ParamDefTable[58].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=59, longName="destructibleParameters" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[59]; + ParamDef->init("destructibleParameters", TYPE_STRUCT, "DestructibleParameters", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The default destructible properties for this asset. These may be overridden\n for an instance (destructible actor), as a copy of the parameters is also stored in the actor.", true); + HintTable[1].init("shortDescription", "The default destructible properties for this asset", true); + ParamDefTable[59].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=60, longName="destructibleParameters.damageCap" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[60]; + ParamDef->init("damageCap", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Limits the amount of damage applied to a chunk. This is useful for preventing the entire destructible\nfrom getting pulverized by a very large application of damage. This can easily happen when impact damage is\nused, and the damage amount is proportional to the impact force (see forceToDamage).\n", true); + HintTable[1].init("shortDescription", "Limits the amount of damage applied to a chunk.", true); + ParamDefTable[60].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=61, longName="destructibleParameters.forceToDamage" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[61]; + ParamDef->init("forceToDamage", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If a chunk is at a depth which takes impact damage (see NxDestructibleDepthParameters),\nthen when a chunk has a collision in the NxScene, it will take damage equal to forceToDamage mulitplied by\nthe impact force.\nThe default value is zero, which effectively disables impact damage.\n", true); + HintTable[1].init("shortDescription", "Multiplier to calculate applied damage from an impact.", true); + ParamDefTable[61].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=62, longName="destructibleParameters.impactVelocityThreshold" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[62]; + ParamDef->init("impactVelocityThreshold", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Large impact force may be reported if rigid bodies are spawned inside one another. In this case the relative velocity of the two\nobjects will be low. This variable allows the user to set a minimum velocity threshold for impacts to ensure that the objects are\nmoving at a min velocity in order for the impact force to be considered.\n", true); + HintTable[1].init("shortDescription", "Large impact force may be reported if rigid bodies are spawned inside one another.", true); + ParamDefTable[62].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=63, longName="destructibleParameters.minimumFractureDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[63]; + ParamDef->init("minimumFractureDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks will not be broken free below this depth.\n", true); + HintTable[1].init("shortDescription", "The chunks will not be broken free below this depth.", true); + ParamDefTable[63].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=64, longName="destructibleParameters.impactDamageDefaultDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[64]; + ParamDef->init("impactDamageDefaultDepth", TYPE_I32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The default depth to which chunks will take impact damage. This default may be overridden in the depth settings.\n", true); + HintTable[1].init("shortDescription", "The default depth to which chunks will take impact damage.", true); + ParamDefTable[64].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=65, longName="destructibleParameters.debrisDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[65]; + ParamDef->init("debrisDepth", TYPE_I32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The chunk hierarchy depth at which chunks are considered to be 'debris.' Chunks at this depth or\nbelow will be considered for various debris settings, such as debrisLifetime.\nNegative values indicate that no chunk depth is considered debris.\nDefault value is -1.\n", true); + HintTable[1].init("shortDescription", "The chunk hierarchy depth at which chunks are considered to be 'debris.'", true); + ParamDefTable[65].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=66, longName="destructibleParameters.essentialDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[66]; + ParamDef->init("essentialDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The chunk hierarchy depth up to which chunks will always be processed. These chunks are considered\nto be essential either for gameplay or visually.\nThe minimum value is 0, meaning the level 0 chunk is always considered essential.\nDefault value is 0.\n", true); + HintTable[1].init("shortDescription", "The chunk hierarchy depth up to which chunks will always be processed", true); + ParamDefTable[66].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=67, longName="destructibleParameters.debrisLifetimeMin" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[67]; + ParamDef->init("debrisLifetimeMin", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed after a time (in seconds)\nseparated from non-debris chunks. The actual lifetime is interpolated between\ndebrisLifetimeMin and debrisLifetimeMax (see below), based upon the module\'s LOD setting.\nTo disable lifetime, clear the NxDestructibleDepthParametersFlag::DEBRIS_TIMEOUT\nflag in the flags field. If debrisLifetimeMax < debrisLifetimeMin, the mean of the two\nis used for both.\nDefault debrisLifetimeMin = 1.0, debrisLifetimeMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Minimum time to destroy debris", true); + ParamDefTable[67].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=68, longName="destructibleParameters.debrisLifetimeMax" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[68]; + ParamDef->init("debrisLifetimeMax", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed after a time (in seconds)\nseparated from non-debris chunks. The actual lifetime is interpolated between\ndebrisLifetimeMin (see above) and debrisLifetimeMax, based upon the module\'s LOD setting.\nTo disable lifetime, clear the NxDestructibleDepthParametersFlag::DEBRIS_TIMEOUT\nflag in the flags field. If debrisLifetimeMax < debrisLifetimeMin, the mean of the two\nis used for both.\nDefault debrisLifetimeMin = 1.0, debrisLifetimeMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Maximum time to destroy debris", true); + ParamDefTable[68].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=69, longName="destructibleParameters.debrisMaxSeparationMin" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[69]; + ParamDef->init("debrisMaxSeparationMin", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed if they are separated from\ntheir origin by a distance greater than maxSeparation. The actual maxSeparation is\ninterpolated between debrisMaxSeparationMin and debrisMaxSeparationMax (see below),\nbased upon the module\'s LOD setting. To disable maxSeparation, clear the\nNX_DESTRUCTIBLE_DEBRIS_MAX_SEPARATION flag in the flags field.\nIf debrisMaxSeparationMax < debrisMaxSeparationMin, the mean of the two is used for both.\nDefault debrisMaxSeparationMin = 1.0, debrisMaxSeparationMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Minimum separation distance", true); + ParamDefTable[69].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=70, longName="destructibleParameters.debrisMaxSeparationMax" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[70]; + ParamDef->init("debrisMaxSeparationMax", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "'Debris chunks' (see debrisDepth, above) will be destroyed if they are separated from\ntheir origin by a distance greater than maxSeparation. The actual maxSeparation is\ninterpolated between debrisMaxSeparationMin (see above) and debrisMaxSeparationMax,\nbased upon the module\'s LOD setting. To disable maxSeparation, clear the\nNX_DESTRUCTIBLE_DEBRIS_MAX_SEPARATION flag in the flags field.\nIf debrisMaxSeparationMax < debrisMaxSeparationMin, the mean of the two is used for both.\nDefault debrisMaxSeparationMin = 1.0, debrisMaxSeparationMax = 10.0f.\n", true); + HintTable[1].init("shortDescription", "Minimum separation distance", true); + ParamDefTable[70].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=71, longName="destructibleParameters.debrisDestructionProbability" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[71]; + ParamDef->init("debrisDestructionProbability", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The probablity that a debris chunk, when fractured, will simply be destroyed instead of becoming dynamic or breaking down\n further into child chunks. Valid range = [0.0,1.0]. Default value = 0.0.", true); + HintTable[1].init("shortDescription", "The probablity that a debris chunk, when fractured, will simply be destroyed", true); + ParamDefTable[71].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=72, longName="destructibleParameters.validBounds" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[72]; + ParamDef->init("validBounds", TYPE_BOUNDS3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A bounding box around each NxDestructibleActor created, defining a range of validity\nfor chunks that break free. These bounds are scaled and translated with the\nNxDestructibleActor\'s scale and position, but they are not rotated with the\nNxDestructibleActor.\n", true); + HintTable[1].init("shortDescription", "valid bounding region for debris", true); + ParamDefTable[72].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=73, longName="destructibleParameters.maxChunkSpeed" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[73]; + ParamDef->init("maxChunkSpeed", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If greater than 0, the chunks' speeds will not be allowed to exceed this value. Use 0\nto disable this feature (this is the default).\n", true); + HintTable[1].init("shortDescription", "Maximum speed of a chunk", true); + ParamDefTable[73].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=74, longName="destructibleParameters.flags" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[74]; + ParamDef->init("flags", TYPE_STRUCT, "DestructibleParametersFlag", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A collection of flags defined in NxDestructibleParametersFlag.\n", true); + HintTable[1].init("shortDescription", "A collection of flags defined in DestructibleParametersFlag.", true); + ParamDefTable[74].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=75, longName="destructibleParameters.flags.ACCUMULATE_DAMAGE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[75]; + ParamDef->init("ACCUMULATE_DAMAGE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, chunks will 'remember' damage applied to them, so that many applications of a damage amount\nbelow damageThreshold will eventually fracture the chunk. If not set, a single application of\ndamage must exceed damageThreshold in order to fracture the chunk.\n", true); + HintTable[1].init("shortDescription", "Determines if chunks accumulate damage", true); + ParamDefTable[75].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=76, longName="destructibleParameters.flags.DEBRIS_TIMEOUT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[76]; + ParamDef->init("DEBRIS_TIMEOUT", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not chunks at or deeper than the 'debris' depth (see NxDestructibleParameters::debrisDepth)\nwill time out. The lifetime is a value between NxDestructibleParameters::debrisLifetimeMin and\nNxDestructibleParameters::debrisLifetimeMax, based upon the destructible module\'s LOD setting.\n", true); + HintTable[1].init("shortDescription", "Whether or not chunks at or deeper than the 'debris' depth will timeout", true); + ParamDefTable[76].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=77, longName="destructibleParameters.flags.DEBRIS_MAX_SEPARATION" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[77]; + ParamDef->init("DEBRIS_MAX_SEPARATION", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not chunks at or deeper than the 'debris' depth (see NxDestructibleParameters::debrisDepth)\nwill be removed if they separate too far from their origins. The maxSeparation is a value between\nNxDestructibleParameters::debrisMaxSeparationMin and NxDestructibleParameters::debrisMaxSeparationMax,\nbased upon the destructible module\'s LOD setting.\n", true); + HintTable[1].init("shortDescription", "Whether or not chunks at or deeper than the 'debris' depth will be removed if separated too far", true); + ParamDefTable[77].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=78, longName="destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[78]; + ParamDef->init("CRUMBLE_SMALLEST_CHUNKS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, the smallest chunks may be further broken down, either by fluid crumbles (if a crumble particle\nsystem is specified in the NxDestructibleActorDesc), or by simply removing the chunk if no crumble\nparticle system is specified. Note: the 'smallest chunks' are normally defined to be the deepest level\nof the fracture hierarchy. However, they may be taken from higher levels of the hierarchy if\nNxModuleDestructible::setMaxChunkDepthOffset is called with a non-zero value.\n", true); + HintTable[1].init("shortDescription", "If set, the smallest chunks may be further broken down", true); + ParamDefTable[78].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=79, longName="destructibleParameters.flags.ACCURATE_RAYCASTS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[79]; + ParamDef->init("ACCURATE_RAYCASTS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, the NxDestructibleActor::rayCast function will search within the nearest visible chunk hit\nfor collisions with child chunks. This is used to get a better raycast position and normal, in\ncase the parent collision volume does not tightly fit the graphics mesh. The returned chunk index\nwill always be that of the visible parent that is intersected, however.\n", true); + HintTable[1].init("shortDescription", "If set, the NxDestructibleActor::rayCast function will search within the nearest visible chunk hit", true); + ParamDefTable[79].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=80, longName="destructibleParameters.flags.USE_VALID_BOUNDS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[80]; + ParamDef->init("USE_VALID_BOUNDS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, the validBounds field of NxDestructibleParameters will be used. These bounds are translated\n(but not scaled or rotated) to the origin of the destructible actor. If a chunk or chunk island moves\noutside of those bounds, it is destroyed.\n", true); + HintTable[1].init("shortDescription", "If set, the validBounds field of NxDestructibleParameters will be used.", true); + ParamDefTable[80].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=81, longName="destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[81]; + ParamDef->init("CRUMBLE_VIA_RUNTIME_FRACTURE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, crumbled chunks will use the runtime fracture pipeline. The chunk will be procedurally broken\ndestroyed using either the default or a specified fracture pattern.\n", true); + HintTable[1].init("shortDescription", "If set, crumbled chunks will use the runtime fracture pipeline.", true); + ParamDefTable[81].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=82, longName="destructibleParameters.fractureImpulseScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[82]; + ParamDef->init("fractureImpulseScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scale factor used to apply an impulse force along the normal of chunk when fractured. This is used\nin order to 'push' the pieces out as they fracture.\n", true); + HintTable[1].init("shortDescription", "Scale factor used to apply an impulse force along the normal of chunk when fractured.", true); + ParamDefTable[82].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=83, longName="destructibleParameters.damageDepthLimit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[83]; + ParamDef->init("damageDepthLimit", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How deep in the hierarchy damage will be propagated, relative to the chunk hit.", true); + HintTable[1].init("shortDescription", "How deep in the hierarchy damage will be propagated, relative to the chunk hit.", true); + ParamDefTable[83].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=84, longName="destructibleParameters.dynamicChunkDominanceGroup" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[84]; + ParamDef->init("dynamicChunkDominanceGroup", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Optional dominance group for dynamic chunks created when fractured. (ignored if > 31)\n", true); + HintTable[1].init("shortDescription", "Optional dominance group for dynamic chunks created when fractured.", true); + ParamDefTable[84].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=85, longName="destructibleParameters.dynamicChunksGroupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[85]; + ParamDef->init("dynamicChunksGroupsMask", TYPE_STRUCT, "GroupsMask", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Optional groups mask for dynamic chunks created when fractured.\n", true); + HintTable[1].init("shortDescription", "Optional groups mask for dynamic chunks created when fractured.", true); + ParamDefTable[85].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=86, longName="destructibleParameters.dynamicChunksGroupsMask.useGroupsMask" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[86]; + ParamDef->init("useGroupsMask", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not the groupsMask should be used. If so, then this will be applied to all NxShapes\n created to represent this destructible's chunks.", true); + HintTable[1].init("shortDescription", "Whether or not the groupsMask should be used", true); + ParamDefTable[86].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=87, longName="destructibleParameters.dynamicChunksGroupsMask.bits0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[87]; + ParamDef->init("bits0", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits0 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits0 of the groups mask", true); + ParamDefTable[87].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=88, longName="destructibleParameters.dynamicChunksGroupsMask.bits1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[88]; + ParamDef->init("bits1", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits1 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits1 of the groups mask", true); + ParamDefTable[88].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=89, longName="destructibleParameters.dynamicChunksGroupsMask.bits2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[89]; + ParamDef->init("bits2", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits2 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits2 of the groups mask", true); + ParamDefTable[89].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=90, longName="destructibleParameters.dynamicChunksGroupsMask.bits3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[90]; + ParamDef->init("bits3", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If useGroupsMask is true, this is bits3 of the groups mask. See the PhysX documentation for more on groups masks.", true); + HintTable[1].init("shortDescription", "bits3 of the groups mask", true); + ParamDefTable[90].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=91, longName="destructibleParameters.runtimeFracture" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[91]; + ParamDef->init("runtimeFracture", TYPE_STRUCT, "RuntimeFracture", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Runtime Fracture Settings. 'CRUMBLE_VIA_RUNTIME_FRACTURE' must be set for this to do anything.\n", true); + HintTable[1].init("shortDescription", "Runtime Fracture Settings", true); + ParamDefTable[91].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=92, longName="destructibleParameters.runtimeFracture.RuntimeFractureType" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[92]; + ParamDef->init("RuntimeFractureType", TYPE_ENUM, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Which type of fracture pattern to choose", true); + ParamDefTable[92].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + static const char* const EnumVals[] = { "VORONOI", "GLASS" }; + ParamDefTable[92].setEnumVals((const char**)EnumVals, 2); + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=93, longName="destructibleParameters.runtimeFracture.sheetFracture" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[93]; + ParamDef->init("sheetFracture", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, align fracture pattern to largest face. \nIf false, the fracture pattern will be aligned to the hit normal with each fracture.\n", true); + HintTable[1].init("shortDescription", "If true, align fracture pattern to largest face", true); + ParamDefTable[93].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=94, longName="destructibleParameters.runtimeFracture.depthLimit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[94]; + ParamDef->init("depthLimit", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of times deep a chunk can be fractured. Can help limit the number of chunks produced by\nruntime fracture.\n", true); + HintTable[1].init("shortDescription", "Number of times deep a chunk can be fractured.", true); + ParamDefTable[94].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=95, longName="destructibleParameters.runtimeFracture.destroyIfAtDepthLimit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[95]; + ParamDef->init("destroyIfAtDepthLimit", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, destroy chunks when they hit their depth limit. \nIf false, then chunks at their depth limit will not fracture but will have a force applied.\n", true); + HintTable[1].init("shortDescription", "Destroy chunk if at depth limit", true); + ParamDefTable[95].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=96, longName="destructibleParameters.runtimeFracture.minConvexSize" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[96]; + ParamDef->init("minConvexSize", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Minimum Convex Size. Minimum size of convex produced by a fracture.\n", true); + HintTable[1].init("shortDescription", "Minimum Convex Size.", true); + ParamDefTable[96].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=97, longName="destructibleParameters.runtimeFracture.impulseScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[97]; + ParamDef->init("impulseScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scales impulse applied by a fracture.\n", true); + HintTable[1].init("shortDescription", "Scales impulse applied by a fracture.", true); + ParamDefTable[97].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=98, longName="destructibleParameters.runtimeFracture.glass" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[98]; + ParamDef->init("glass", TYPE_STRUCT, "FractureGlass", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Glass Fracture Pattern Settings.\n", true); + HintTable[1].init("shortDescription", "Glass Fracture Pattern Settings.", true); + ParamDefTable[98].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=99, longName="destructibleParameters.runtimeFracture.glass.numSectors" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[99]; + ParamDef->init("numSectors", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of angular slices in the glass fracture pattern. \n", true); + HintTable[1].init("shortDescription", "Number of angular slices.", true); + ParamDefTable[99].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=100, longName="destructibleParameters.runtimeFracture.glass.sectorRand" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[100]; + ParamDef->init("sectorRand", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Creates variance in the angle of slices. A value of zero results in all angular slices having the same angle.\n", true); + HintTable[1].init("shortDescription", "Creates variance in the angle of slices.", true); + ParamDefTable[100].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=101, longName="destructibleParameters.runtimeFracture.glass.firstSegmentSize" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[101]; + ParamDef->init("firstSegmentSize", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The minimum shard size. Shards below this size will not be created and thus not visible.\n", true); + HintTable[1].init("shortDescription", "The minimum shard size.", true); + ParamDefTable[101].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=102, longName="destructibleParameters.runtimeFracture.glass.segmentScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[102]; + ParamDef->init("segmentScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scales the radial spacing in the glass fracture pattern. A larger value results in radially longer shards.\n", true); + HintTable[1].init("shortDescription", "Scales the radial spacing.", true); + ParamDefTable[102].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=103, longName="destructibleParameters.runtimeFracture.glass.segmentRand" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[103]; + ParamDef->init("segmentRand", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Creates variance in the radial size of shards. A value of zero results in a low noise circular pattern.\n", true); + HintTable[1].init("shortDescription", "Creates variance in the radial size of shards.", true); + ParamDefTable[103].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=104, longName="destructibleParameters.runtimeFracture.voronoi" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[104]; + ParamDef->init("voronoi", TYPE_STRUCT, "FractureVoronoi", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Voronoi Fracture Pattern Settings.\n", true); + HintTable[1].init("shortDescription", "Voronoi Fracture Pattern Settings.", true); + ParamDefTable[104].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=105, longName="destructibleParameters.runtimeFracture.voronoi.dimensions" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[105]; + ParamDef->init("dimensions", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The size of the entire block. \n", true); + HintTable[1].init("shortDescription", "The size of the entire block", true); + ParamDefTable[105].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=106, longName="destructibleParameters.runtimeFracture.voronoi.numCells" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[106]; + ParamDef->init("numCells", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Number of Cells corresponds to the number of chunks to create during the fracture, default value is only one chunk.\n", true); + HintTable[1].init("shortDescription", "Max Number of Cells to create.", true); + ParamDefTable[106].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=107, longName="destructibleParameters.runtimeFracture.voronoi.biasExp" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[107]; + ParamDef->init("biasExp", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Bias Exponential value is used in distributing voronoi points which is used to fracture the original chunk.\n", true); + HintTable[1].init("shortDescription", "Bias Exponential value.", true); + ParamDefTable[107].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=108, longName="destructibleParameters.runtimeFracture.voronoi.maxDist" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[108]; + ParamDef->init("maxDist", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "This is to prevent a illegal voronoi point that's used to generate voronoi chunks.\n", true); + HintTable[1].init("shortDescription", "The max distance a Voronoi point away from origin.", true); + ParamDefTable[108].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=109, longName="destructibleParameters.runtimeFracture.attachment" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[109]; + ParamDef->init("attachment", TYPE_STRUCT, "FractureAttachment", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Attachment Settings. Allows the sides of a runtime fracture chunk to be kinematic rather than dynamic.\n", true); + HintTable[1].init("shortDescription", "Attachment Settings", true); + ParamDefTable[109].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=110, longName="destructibleParameters.runtimeFracture.attachment.posX" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[110]; + ParamDef->init("posX", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the positive x side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to positive x side of sheet.", true); + ParamDefTable[110].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=111, longName="destructibleParameters.runtimeFracture.attachment.negX" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[111]; + ParamDef->init("negX", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the negative x side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to negative x side of sheet.", true); + ParamDefTable[111].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=112, longName="destructibleParameters.runtimeFracture.attachment.posY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[112]; + ParamDef->init("posY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the positive y side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to positive y side of sheet.", true); + ParamDefTable[112].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=113, longName="destructibleParameters.runtimeFracture.attachment.negY" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[113]; + ParamDef->init("negY", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the negative y side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to negative y side of sheet.", true); + ParamDefTable[113].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=114, longName="destructibleParameters.runtimeFracture.attachment.posZ" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[114]; + ParamDef->init("posZ", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the positive z side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to positive z side of sheet.", true); + ParamDefTable[114].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=115, longName="destructibleParameters.runtimeFracture.attachment.negZ" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[115]; + ParamDef->init("negZ", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, make the negative z side of the sheet an attachment point.\n", true); + HintTable[1].init("shortDescription", "Attach to negative z side of sheet.", true); + ParamDefTable[115].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=116, longName="destructibleParameters.supportStrength" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[116]; + ParamDef->init("supportStrength", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The larger the supportStrength is, the harder it will break under stressSolver. SupportStrength should be larger\nthan 0.0 so that it is not extremely fragile.\nDefault supportStrength = -1.0 which means strength is turned off initially.\n", true); + HintTable[1].init("shortDescription", "The support strength threshold for breaking chunks in stressSolver", true); + ParamDefTable[116].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=117, longName="destructibleParameters.legacyChunkBoundsTestSetting" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[117]; + ParamDef->init("legacyChunkBoundsTestSetting", TYPE_I8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Whether or not to use the old chunk bounds testing for damage, or use the module setting. A value of 0 forces the new method to be used.\nA positive value forces the old method to be used. Negative values cause the global (NxModuleDestructible) setting to be used.\n", true); + HintTable[1].init("shortDescription", "Whether or not to use the old chunk bounds testing for damage, or use the module setting.", true); + ParamDefTable[117].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=118, longName="destructibleParameters.legacyDamageRadiusSpreadSetting" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[118]; + ParamDef->init("legacyDamageRadiusSpreadSetting", TYPE_I8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("END", "", true); + ParamDefTable[118].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("END", "", true); + HintTable[1].init("longDescription", "Whether or not to use the old damage spread method, or use the module setting. A value of 0 forces the new method to be used.\nA positive value forces the old method to be used. Negative values cause the global (NxModuleDestructible) setting to be used.\n", true); + HintTable[2].init("shortDescription", "Whether or not to use the old damage spread method, or use the module setting.", true); + ParamDefTable[118].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=119, longName="destructibleParameters.alwaysDrawScatterMesh" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[119]; + ParamDef->init("alwaysDrawScatterMesh", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Scatter mesh visibility is controlled by LOD. If asset has more than one depth level, scatter mesh is not drawn.\n This flag forces drawing of scatter mesh on chunks with depth > 1.", true); + HintTable[1].init("shortDescription", "Always draw scatter mesh on the chunks with depth > 1", true); + ParamDefTable[119].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=120, longName="depthParameters" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[120]; + ParamDef->init("depthParameters", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The default destructible depth parameters for this asset. These\n are properties that apply to all chunks at a particular level of the hierarchy. These may be overridden\n for an instance (destructible actor), as a copy of the parameters is also stored in the actor.", true); + HintTable[1].init("shortDescription", "The default destructible depth parameters for this asset", true); + ParamDefTable[120].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=121, longName="depthParameters[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[121]; + ParamDef->init("depthParameters", TYPE_STRUCT, "DestructibleDepthParameters", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The default destructible depth parameters for this asset. These\n are properties that apply to all chunks at a particular level of the hierarchy. These may be overridden\n for an instance (destructible actor), as a copy of the parameters is also stored in the actor.", true); + HintTable[1].init("shortDescription", "The default destructible depth parameters for this asset", true); + ParamDefTable[121].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=122, longName="depthParameters[].OVERRIDE_IMPACT_DAMAGE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[122]; + ParamDef->init("OVERRIDE_IMPACT_DAMAGE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks at this hierarchy depth level will take impact damage iff OVERRIDE_IMPACT_DAMAGE_VALUE = TRUE, no matter the setting of impactDamageDefaultDepth.\n", true); + HintTable[1].init("shortDescription", "If true, chunks at this hierarchy depth level will take impact damage iff OVERRIDE_IMPACT_DAMAGE_VALUE = TRUE, no matter the setting of impactDamageDefaultDepth.", true); + ParamDefTable[122].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=123, longName="depthParameters[].OVERRIDE_IMPACT_DAMAGE_VALUE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[123]; + ParamDef->init("OVERRIDE_IMPACT_DAMAGE_VALUE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If OVERRIDE_IMPACT_DAMAGE = TRUE, chunks at this hierarchy depth level will take impact damage iff OVERRIDE_IMPACT_DAMAGE_VALUE = TRUE.\n", true); + HintTable[1].init("shortDescription", "If OVERRIDE_IMPACT_DAMAGE = TRUE, chunks at this hierarchy depth level will take impact damage iff OVERRIDE_IMPACT_DAMAGE_VALUE = TRUE.", true); + ParamDefTable[123].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=124, longName="depthParameters[].IGNORE_POSE_UPDATES" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[124]; + ParamDef->init("IGNORE_POSE_UPDATES", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks at this depth should have pose updates ignored.\n", true); + HintTable[1].init("shortDescription", "Chunks at this depth should have pose updates ignored.", true); + ParamDefTable[124].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=125, longName="depthParameters[].IGNORE_RAYCAST_CALLBACKS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[125]; + ParamDef->init("IGNORE_RAYCAST_CALLBACKS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks at this depth should be ignored in raycast callbacks.\n", true); + HintTable[1].init("shortDescription", "Chunks at this depth should be ignored in raycast callbacks.", true); + ParamDefTable[125].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=126, longName="depthParameters[].IGNORE_CONTACT_CALLBACKS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[126]; + ParamDef->init("IGNORE_CONTACT_CALLBACKS", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunks at this depth should be ignored in contact callbacks.\n", true); + HintTable[1].init("shortDescription", "Chunks at this depth should be ignored in contact callbacks.", true); + ParamDefTable[126].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=127, longName="depthParameters[].USER_FLAG_0" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[127]; + ParamDef->init("USER_FLAG_0", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User defined flag.\n", true); + HintTable[1].init("shortDescription", "User defined flag.", true); + ParamDefTable[127].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=128, longName="depthParameters[].USER_FLAG_1" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[128]; + ParamDef->init("USER_FLAG_1", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User defined flag.\n", true); + HintTable[1].init("shortDescription", "User defined flag.", true); + ParamDefTable[128].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=129, longName="depthParameters[].USER_FLAG_2" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[129]; + ParamDef->init("USER_FLAG_2", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User defined flag.\n", true); + HintTable[1].init("shortDescription", "User defined flag.", true); + ParamDefTable[129].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=130, longName="depthParameters[].USER_FLAG_3" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[130]; + ParamDef->init("USER_FLAG_3", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "User defined flag.\n", true); + HintTable[1].init("shortDescription", "User defined flag.", true); + ParamDefTable[130].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=131, longName="crumbleEmitterName" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[131]; + ParamDef->init("crumbleEmitterName", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The name of the crumble emitter to use when crumbling\n the smallest chunks.", true); + HintTable[1].init("shortDescription", "The name of the crumble emitter to use", true); + ParamDefTable[131].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=132, longName="dustEmitterName" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[132]; + ParamDef->init("dustEmitterName", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The name of the dust emitter to use. If defined, dust particles\n will be spawned above the chunk surface traces when a chunk is fractured.", true); + HintTable[1].init("shortDescription", "The name of the dust emitter to use", true); + ParamDefTable[132].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=133, longName="collisionData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[133]; + ParamDef->init("collisionData", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[133].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The cooked convex data for PhysX collision. All cooked convex hulls for a set of\n scales may be included", true); + HintTable[2].init("shortDescription", "The cooked convex data for PhysX collision", true); + ParamDefTable[133].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "DestructibleAssetCollisionDataSet" }; + ParamDefTable[133].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // Initialize DefinitionImpl node: nodeIndex=134, longName="renderMeshAsset" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[134]; + ParamDef->init("renderMeshAsset", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[134].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The included render mesh asset.", true); + HintTable[2].init("shortDescription", "The included render mesh asset", true); + ParamDefTable[134].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "RenderMeshAssetParameters" }; + ParamDefTable[134].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // Initialize DefinitionImpl node: nodeIndex=135, longName="initialDestructibleActorAllowanceForInstancing" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[135]; + ParamDef->init("initialDestructibleActorAllowanceForInstancing", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Initial actor estimate for instance buffer allocation.\n Used for setting instance buffer sizes.", true); + HintTable[1].init("shortDescription", "Initial actor estimate for instance buffer allocation", true); + ParamDefTable[135].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=136, longName="chunkInstanceInfo" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[136]; + ParamDef->init("chunkInstanceInfo", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-instance data for each instanced chunk.", true); + HintTable[1].init("shortDescription", "Per-instance data for each instanced chunk", true); + ParamDefTable[136].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=137, longName="chunkInstanceInfo[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[137]; + ParamDef->init("chunkInstanceInfo", TYPE_STRUCT, "InstanceInfo", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-instance data for each instanced chunk.", true); + HintTable[1].init("shortDescription", "Per-instance data for each instanced chunk", true); + ParamDefTable[137].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=138, longName="chunkInstanceInfo[].partIndex" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[138]; + ParamDef->init("partIndex", TYPE_U16, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The part instanced for this chunk.", true); + HintTable[1].init("shortDescription", "The part instanced for this chunk", true); + ParamDefTable[138].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=139, longName="chunkInstanceInfo[].chunkPositionOffset" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[139]; + ParamDef->init("chunkPositionOffset", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Translation for this chunk mesh within the asset.\n Normally a chunk needs no translation, but if a chunk is instanced within\n the asset, then this translation is needed.", true); + HintTable[1].init("shortDescription", "Translation for this chunk mesh within the asset", true); + ParamDefTable[139].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=140, longName="chunkInstanceInfo[].chunkUVOffset" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[140]; + ParamDef->init("chunkUVOffset", TYPE_VEC2, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "UV translation for this chunk mesh's vertices.", true); + HintTable[1].init("shortDescription", "UV translation for this chunk mesh's vertices", true); + ParamDefTable[140].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=141, longName="staticMaterialNames" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[141]; + ParamDef->init("staticMaterialNames", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Alternative material names for the static render mesh, if it's created.", true); + HintTable[1].init("shortDescription", "Alternative material names for the static render mesh, if it's created", true); + ParamDefTable[141].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=142, longName="staticMaterialNames[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[142]; + ParamDef->init("staticMaterialNames", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Alternative material names for the static render mesh, if it's created.", true); + HintTable[1].init("shortDescription", "Alternative material names for the static render mesh, if it's created", true); + ParamDefTable[142].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=143, longName="neighborPadding" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[143]; + ParamDef->init("neighborPadding", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Padding used for chunk neighbor tests. This padding is relative to the largest diagonal\n of the asset's local bounding box.\n This value must be non-negative.\n Default value = 0.001f.", true); + HintTable[1].init("shortDescription", "Padding used for chunk neighbor tests.", true); + ParamDefTable[143].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=144, longName="overlapsAtDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[144]; + ParamDef->init("overlapsAtDepth", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[144].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The chunk overlaps (adjacencies) at each depth of the hierarchy.", true); + HintTable[2].init("shortDescription", "The chunk overlaps at each depth of the hierarchy", true); + ParamDefTable[144].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "CachedOverlaps" }; + ParamDefTable[144].setRefVariantVals((const char**)RefVariantVals, 1); + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=145, longName="overlapsAtDepth[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[145]; + ParamDef->init("overlapsAtDepth", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[145].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The chunk overlaps (adjacencies) at each depth of the hierarchy.", true); + HintTable[2].init("shortDescription", "The chunk overlaps at each depth of the hierarchy", true); + ParamDefTable[145].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "CachedOverlaps" }; + ParamDefTable[145].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // Initialize DefinitionImpl node: nodeIndex=146, longName="firstChunkAtDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[146]; + ParamDef->init("firstChunkAtDepth", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The first index of chunks at each depth in the hierarchy. All chunks\n at a given depth are stored contiguously.", true); + HintTable[1].init("shortDescription", "The first index of chunks at each depth", true); + ParamDefTable[146].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=147, longName="firstChunkAtDepth[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[147]; + ParamDef->init("firstChunkAtDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The first index of chunks at each depth in the hierarchy. All chunks\n at a given depth are stored contiguously.", true); + HintTable[1].init("shortDescription", "The first index of chunks at each depth", true); + ParamDefTable[147].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=148, longName="supportDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[148]; + ParamDef->init("supportDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The chunk hierarchy depth at which to create a support graph. Higher depth levels give more detailed support,\nbut will give a higher computational load. Chunks below the support depth will never be supported.\n", true); + HintTable[1].init("shortDescription", "The chunk hierarchy depth at which to create a support graph.", true); + ParamDefTable[148].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=149, longName="formExtendedStructures" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[149]; + ParamDef->init("formExtendedStructures", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If initially static, the destructible will become part of an extended support structure if it is\nin contact with another static destructible that also has this flag set.\n", true); + HintTable[1].init("shortDescription", "If initially static, the destructible will become part of an extended support structure if it is in contact with another static destructible that also has this flag set.", true); + ParamDefTable[149].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=150, longName="useAssetDefinedSupport" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[150]; + ParamDef->init("useAssetDefinedSupport", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, then chunks which are tagged as 'support' chunks (via DestructibleChunkDesc::isSupportChunk)\nwill have environmental support in static destructibles.\nNote: if both ASSET_DEFINED_SUPPORT and WORLD_SUPPORT are set, then chunks must be tagged as\n'support' chunks AND overlap the PxScene's static geometry in order to be environmentally supported.\n", true); + HintTable[1].init("shortDescription", "If set, then chunks which are tagged as 'support' chunks", true); + ParamDefTable[150].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=151, longName="useWorldSupport" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[151]; + ParamDef->init("useWorldSupport", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If set, then chunks which overlap the PxScene\'s static geometry will have environmental support in\nstatic destructibles.\nNote: if both ASSET_DEFINED_SUPPORT and WORLD_SUPPORT are set, then chunks must be tagged as\n'support' chunks AND overlap the PxScene's static geometry in order to be environmentally supported.\n", true); + HintTable[1].init("shortDescription", "If set, then chunks which overlap the PxScene's static geometry will have environmental support", true); + ParamDefTable[151].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=152, longName="actorTransforms" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[152]; + ParamDef->init("actorTransforms", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "List of actor poses (that may contain scaling) which may be saved in the asset for convenience.", true); + HintTable[1].init("shortDescription", "List of actor poses (that may contain scaling) which may be saved in the asset for convenience", true); + ParamDefTable[152].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=153, longName="actorTransforms[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[153]; + ParamDef->init("actorTransforms", TYPE_MAT44, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "List of actor poses (that may contain scaling) which may be saved in the asset for convenience.", true); + HintTable[1].init("shortDescription", "List of actor poses (that may contain scaling) which may be saved in the asset for convenience", true); + ParamDefTable[153].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=154, longName="scatterMeshAssets" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[154]; + ParamDef->init("scatterMeshAssets", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[154].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The included scatter mesh asset.", true); + HintTable[2].init("shortDescription", "The included scatter mesh assets", true); + ParamDefTable[154].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "RenderMeshAssetParameters" }; + ParamDefTable[154].setRefVariantVals((const char**)RefVariantVals, 1); + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=155, longName="scatterMeshAssets[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[155]; + ParamDef->init("scatterMeshAssets", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[155].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "The included scatter mesh asset.", true); + HintTable[2].init("shortDescription", "The included scatter mesh assets", true); + ParamDefTable[155].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "RenderMeshAssetParameters" }; + ParamDefTable[155].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // Initialize DefinitionImpl node: nodeIndex=156, longName="scatterMeshIndices" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[156]; + ParamDef->init("scatterMeshIndices", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Array of indices for scatter meshes defined in the asset. Valid indices must be in the range [0,N), where N is the size of the scatterMeshAssets array.", true); + HintTable[1].init("shortDescription", "Array of indices for scatter meshes defined in the asset", true); + ParamDefTable[156].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=157, longName="scatterMeshIndices[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[157]; + ParamDef->init("scatterMeshIndices", TYPE_U8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Array of indices for scatter meshes defined in the asset. Valid indices must be in the range [0,N), where N is the size of the scatterMeshAssets array.", true); + HintTable[1].init("shortDescription", "Array of indices for scatter meshes defined in the asset", true); + ParamDefTable[157].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=158, longName="scatterMeshTransforms" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[158]; + ParamDef->init("scatterMeshTransforms", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Array of chunk-relative transforms for scatter meshes defined in the asset. Must be the same size as scatterMeshIndices.", true); + HintTable[1].init("shortDescription", "Array of chunk-relative transforms for scatter meshes defined in the asset", true); + ParamDefTable[158].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=159, longName="scatterMeshTransforms[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[159]; + ParamDef->init("scatterMeshTransforms", TYPE_MAT44, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Array of chunk-relative transforms for scatter meshes defined in the asset. Must be the same size as scatterMeshIndices.", true); + HintTable[1].init("shortDescription", "Array of chunk-relative transforms for scatter meshes defined in the asset", true); + ParamDefTable[159].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[30]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(2); + Children[2] = PDEF_PTR(3); + Children[3] = PDEF_PTR(4); + Children[4] = PDEF_PTR(5); + Children[5] = PDEF_PTR(23); + Children[6] = PDEF_PTR(42); + Children[7] = PDEF_PTR(43); + Children[8] = PDEF_PTR(55); + Children[9] = PDEF_PTR(57); + Children[10] = PDEF_PTR(59); + Children[11] = PDEF_PTR(120); + Children[12] = PDEF_PTR(131); + Children[13] = PDEF_PTR(132); + Children[14] = PDEF_PTR(133); + Children[15] = PDEF_PTR(134); + Children[16] = PDEF_PTR(135); + Children[17] = PDEF_PTR(136); + Children[18] = PDEF_PTR(141); + Children[19] = PDEF_PTR(143); + Children[20] = PDEF_PTR(144); + Children[21] = PDEF_PTR(146); + Children[22] = PDEF_PTR(148); + Children[23] = PDEF_PTR(149); + Children[24] = PDEF_PTR(150); + Children[25] = PDEF_PTR(151); + Children[26] = PDEF_PTR(152); + Children[27] = PDEF_PTR(154); + Children[28] = PDEF_PTR(156); + Children[29] = PDEF_PTR(158); + + ParamDefTable[0].setChildren(Children, 30); + } + + // SetChildren for: nodeIndex=5, longName="defaultBehaviorGroup" + { + static Definition* Children[11]; + Children[0] = PDEF_PTR(6); + Children[1] = PDEF_PTR(7); + Children[2] = PDEF_PTR(8); + Children[3] = PDEF_PTR(9); + Children[4] = PDEF_PTR(13); + Children[5] = PDEF_PTR(17); + Children[6] = PDEF_PTR(18); + Children[7] = PDEF_PTR(19); + Children[8] = PDEF_PTR(20); + Children[9] = PDEF_PTR(21); + Children[10] = PDEF_PTR(22); + + ParamDefTable[5].setChildren(Children, 11); + } + + // SetChildren for: nodeIndex=9, longName="defaultBehaviorGroup.damageSpread" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(10); + Children[1] = PDEF_PTR(11); + Children[2] = PDEF_PTR(12); + + ParamDefTable[9].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=13, longName="defaultBehaviorGroup.damageColorSpread" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(14); + Children[1] = PDEF_PTR(15); + Children[2] = PDEF_PTR(16); + + ParamDefTable[13].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=23, longName="behaviorGroups" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(24); + + ParamDefTable[23].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=24, longName="behaviorGroups[]" + { + static Definition* Children[11]; + Children[0] = PDEF_PTR(25); + Children[1] = PDEF_PTR(26); + Children[2] = PDEF_PTR(27); + Children[3] = PDEF_PTR(28); + Children[4] = PDEF_PTR(32); + Children[5] = PDEF_PTR(36); + Children[6] = PDEF_PTR(37); + Children[7] = PDEF_PTR(38); + Children[8] = PDEF_PTR(39); + Children[9] = PDEF_PTR(40); + Children[10] = PDEF_PTR(41); + + ParamDefTable[24].setChildren(Children, 11); + } + + // SetChildren for: nodeIndex=28, longName="behaviorGroups[].damageSpread" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(29); + Children[1] = PDEF_PTR(30); + Children[2] = PDEF_PTR(31); + + ParamDefTable[28].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=32, longName="behaviorGroups[].damageColorSpread" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(33); + Children[1] = PDEF_PTR(34); + Children[2] = PDEF_PTR(35); + + ParamDefTable[32].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=43, longName="chunks" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(44); + + ParamDefTable[43].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=44, longName="chunks[]" + { + static Definition* Children[10]; + Children[0] = PDEF_PTR(45); + Children[1] = PDEF_PTR(46); + Children[2] = PDEF_PTR(47); + Children[3] = PDEF_PTR(48); + Children[4] = PDEF_PTR(49); + Children[5] = PDEF_PTR(50); + Children[6] = PDEF_PTR(51); + Children[7] = PDEF_PTR(52); + Children[8] = PDEF_PTR(53); + Children[9] = PDEF_PTR(54); + + ParamDefTable[44].setChildren(Children, 10); + } + + // SetChildren for: nodeIndex=55, longName="chunkConvexHulls" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(56); + + ParamDefTable[55].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=57, longName="chunkConvexHullStartIndices" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(58); + + ParamDefTable[57].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=59, longName="destructibleParameters" + { + static Definition* Children[24]; + Children[0] = PDEF_PTR(60); + Children[1] = PDEF_PTR(61); + Children[2] = PDEF_PTR(62); + Children[3] = PDEF_PTR(63); + Children[4] = PDEF_PTR(64); + Children[5] = PDEF_PTR(65); + Children[6] = PDEF_PTR(66); + Children[7] = PDEF_PTR(67); + Children[8] = PDEF_PTR(68); + Children[9] = PDEF_PTR(69); + Children[10] = PDEF_PTR(70); + Children[11] = PDEF_PTR(71); + Children[12] = PDEF_PTR(72); + Children[13] = PDEF_PTR(73); + Children[14] = PDEF_PTR(74); + Children[15] = PDEF_PTR(82); + Children[16] = PDEF_PTR(83); + Children[17] = PDEF_PTR(84); + Children[18] = PDEF_PTR(85); + Children[19] = PDEF_PTR(91); + Children[20] = PDEF_PTR(116); + Children[21] = PDEF_PTR(117); + Children[22] = PDEF_PTR(118); + Children[23] = PDEF_PTR(119); + + ParamDefTable[59].setChildren(Children, 24); + } + + // SetChildren for: nodeIndex=74, longName="destructibleParameters.flags" + { + static Definition* Children[7]; + Children[0] = PDEF_PTR(75); + Children[1] = PDEF_PTR(76); + Children[2] = PDEF_PTR(77); + Children[3] = PDEF_PTR(78); + Children[4] = PDEF_PTR(79); + Children[5] = PDEF_PTR(80); + Children[6] = PDEF_PTR(81); + + ParamDefTable[74].setChildren(Children, 7); + } + + // SetChildren for: nodeIndex=85, longName="destructibleParameters.dynamicChunksGroupsMask" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(86); + Children[1] = PDEF_PTR(87); + Children[2] = PDEF_PTR(88); + Children[3] = PDEF_PTR(89); + Children[4] = PDEF_PTR(90); + + ParamDefTable[85].setChildren(Children, 5); + } + + // SetChildren for: nodeIndex=91, longName="destructibleParameters.runtimeFracture" + { + static Definition* Children[9]; + Children[0] = PDEF_PTR(92); + Children[1] = PDEF_PTR(93); + Children[2] = PDEF_PTR(94); + Children[3] = PDEF_PTR(95); + Children[4] = PDEF_PTR(96); + Children[5] = PDEF_PTR(97); + Children[6] = PDEF_PTR(98); + Children[7] = PDEF_PTR(104); + Children[8] = PDEF_PTR(109); + + ParamDefTable[91].setChildren(Children, 9); + } + + // SetChildren for: nodeIndex=98, longName="destructibleParameters.runtimeFracture.glass" + { + static Definition* Children[5]; + Children[0] = PDEF_PTR(99); + Children[1] = PDEF_PTR(100); + Children[2] = PDEF_PTR(101); + Children[3] = PDEF_PTR(102); + Children[4] = PDEF_PTR(103); + + ParamDefTable[98].setChildren(Children, 5); + } + + // SetChildren for: nodeIndex=104, longName="destructibleParameters.runtimeFracture.voronoi" + { + static Definition* Children[4]; + Children[0] = PDEF_PTR(105); + Children[1] = PDEF_PTR(106); + Children[2] = PDEF_PTR(107); + Children[3] = PDEF_PTR(108); + + ParamDefTable[104].setChildren(Children, 4); + } + + // SetChildren for: nodeIndex=109, longName="destructibleParameters.runtimeFracture.attachment" + { + static Definition* Children[6]; + Children[0] = PDEF_PTR(110); + Children[1] = PDEF_PTR(111); + Children[2] = PDEF_PTR(112); + Children[3] = PDEF_PTR(113); + Children[4] = PDEF_PTR(114); + Children[5] = PDEF_PTR(115); + + ParamDefTable[109].setChildren(Children, 6); + } + + // SetChildren for: nodeIndex=120, longName="depthParameters" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(121); + + ParamDefTable[120].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=121, longName="depthParameters[]" + { + static Definition* Children[9]; + Children[0] = PDEF_PTR(122); + Children[1] = PDEF_PTR(123); + Children[2] = PDEF_PTR(124); + Children[3] = PDEF_PTR(125); + Children[4] = PDEF_PTR(126); + Children[5] = PDEF_PTR(127); + Children[6] = PDEF_PTR(128); + Children[7] = PDEF_PTR(129); + Children[8] = PDEF_PTR(130); + + ParamDefTable[121].setChildren(Children, 9); + } + + // SetChildren for: nodeIndex=136, longName="chunkInstanceInfo" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(137); + + ParamDefTable[136].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=137, longName="chunkInstanceInfo[]" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(138); + Children[1] = PDEF_PTR(139); + Children[2] = PDEF_PTR(140); + + ParamDefTable[137].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=141, longName="staticMaterialNames" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(142); + + ParamDefTable[141].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=144, longName="overlapsAtDepth" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(145); + + ParamDefTable[144].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=146, longName="firstChunkAtDepth" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(147); + + ParamDefTable[146].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=152, longName="actorTransforms" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(153); + + ParamDefTable[152].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=154, longName="scatterMeshAssets" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(155); + + ParamDefTable[154].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=156, longName="scatterMeshIndices" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(157); + + ParamDefTable[156].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=158, longName="scatterMeshTransforms" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(159); + + ParamDefTable[158].setChildren(Children, 1); + } + + mBuiltFlag = true; + +} +void DestructibleAssetParameters::initStrings(void) +{ + comments.isAllocated = true; + comments.buf = NULL; + defaultBehaviorGroup.name.isAllocated = true; + defaultBehaviorGroup.name.buf = NULL; + crumbleEmitterName.isAllocated = true; + crumbleEmitterName.buf = NULL; + dustEmitterName.isAllocated = true; + dustEmitterName.buf = NULL; +} + +void DestructibleAssetParameters::initDynamicArrays(void) +{ + behaviorGroups.buf = NULL; + behaviorGroups.isAllocated = true; + behaviorGroups.elementSize = sizeof(BehaviorGroup_Type); + behaviorGroups.arraySizes[0] = 0; + chunks.buf = NULL; + chunks.isAllocated = true; + chunks.elementSize = sizeof(Chunk_Type); + chunks.arraySizes[0] = 0; + chunkConvexHulls.buf = NULL; + chunkConvexHulls.isAllocated = true; + chunkConvexHulls.elementSize = sizeof(NvParameterized::Interface*); + chunkConvexHulls.arraySizes[0] = 0; + chunkConvexHullStartIndices.buf = NULL; + chunkConvexHullStartIndices.isAllocated = true; + chunkConvexHullStartIndices.elementSize = sizeof(uint32_t); + chunkConvexHullStartIndices.arraySizes[0] = 0; + depthParameters.buf = NULL; + depthParameters.isAllocated = true; + depthParameters.elementSize = sizeof(DestructibleDepthParameters_Type); + depthParameters.arraySizes[0] = 0; + chunkInstanceInfo.buf = NULL; + chunkInstanceInfo.isAllocated = true; + chunkInstanceInfo.elementSize = sizeof(InstanceInfo_Type); + chunkInstanceInfo.arraySizes[0] = 0; + staticMaterialNames.buf = NULL; + staticMaterialNames.isAllocated = true; + staticMaterialNames.elementSize = sizeof(NvParameterized::DummyStringStruct); + staticMaterialNames.arraySizes[0] = 0; + overlapsAtDepth.buf = NULL; + overlapsAtDepth.isAllocated = true; + overlapsAtDepth.elementSize = sizeof(NvParameterized::Interface*); + overlapsAtDepth.arraySizes[0] = 0; + firstChunkAtDepth.buf = NULL; + firstChunkAtDepth.isAllocated = true; + firstChunkAtDepth.elementSize = sizeof(uint32_t); + firstChunkAtDepth.arraySizes[0] = 0; + actorTransforms.buf = NULL; + actorTransforms.isAllocated = true; + actorTransforms.elementSize = sizeof(physx::PxMat44); + actorTransforms.arraySizes[0] = 0; + scatterMeshAssets.buf = NULL; + scatterMeshAssets.isAllocated = true; + scatterMeshAssets.elementSize = sizeof(NvParameterized::Interface*); + scatterMeshAssets.arraySizes[0] = 0; + scatterMeshIndices.buf = NULL; + scatterMeshIndices.isAllocated = true; + scatterMeshIndices.elementSize = sizeof(uint8_t); + scatterMeshIndices.arraySizes[0] = 0; + scatterMeshTransforms.buf = NULL; + scatterMeshTransforms.isAllocated = true; + scatterMeshTransforms.elementSize = sizeof(physx::PxMat44); + scatterMeshTransforms.arraySizes[0] = 0; +} + +void DestructibleAssetParameters::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + depthCount = uint32_t(0); + originalDepthCount = uint32_t(0); + defaultBehaviorGroup.damageThreshold = float(1); + defaultBehaviorGroup.damageToRadius = float(0.1); + defaultBehaviorGroup.damageSpread.minimumRadius = float(0); + defaultBehaviorGroup.damageSpread.radiusMultiplier = float(1); + defaultBehaviorGroup.damageSpread.falloffExponent = float(1); + defaultBehaviorGroup.damageColorSpread.minimumRadius = float(0); + defaultBehaviorGroup.damageColorSpread.radiusMultiplier = float(1); + defaultBehaviorGroup.damageColorSpread.falloffExponent = float(1); + defaultBehaviorGroup.damageColorChange = physx::PxVec4(initVec4(0, 0, 0, 0)); + defaultBehaviorGroup.materialStrength = float(0); + defaultBehaviorGroup.density = float(0); + defaultBehaviorGroup.fadeOut = float(1); + defaultBehaviorGroup.maxDepenetrationVelocity = float(PX_MAX_F32); + defaultBehaviorGroup.userData = uint64_t(0); + RTFractureBehaviorGroup = int8_t(-1); + destructibleParameters.damageCap = float(0); + destructibleParameters.forceToDamage = float(0); + destructibleParameters.impactVelocityThreshold = float(0); + destructibleParameters.minimumFractureDepth = uint32_t(0); + destructibleParameters.impactDamageDefaultDepth = int32_t(-1); + destructibleParameters.debrisDepth = int32_t(-1); + destructibleParameters.essentialDepth = uint32_t(0); + destructibleParameters.debrisLifetimeMin = float(1); + destructibleParameters.debrisLifetimeMax = float(10); + destructibleParameters.debrisMaxSeparationMin = float(1); + destructibleParameters.debrisMaxSeparationMax = float(10); + destructibleParameters.debrisDestructionProbability = float(0); + destructibleParameters.validBounds = physx::PxBounds3(init(-1000, -1000, -1000, 1000, 1000, 1000)); + destructibleParameters.maxChunkSpeed = float(0); + destructibleParameters.flags.ACCUMULATE_DAMAGE = bool(true); + destructibleParameters.flags.DEBRIS_TIMEOUT = bool(false); + destructibleParameters.flags.DEBRIS_MAX_SEPARATION = bool(false); + destructibleParameters.flags.CRUMBLE_SMALLEST_CHUNKS = bool(false); + destructibleParameters.flags.ACCURATE_RAYCASTS = bool(false); + destructibleParameters.flags.USE_VALID_BOUNDS = bool(false); + destructibleParameters.flags.CRUMBLE_VIA_RUNTIME_FRACTURE = bool(false); + destructibleParameters.fractureImpulseScale = float(0); + destructibleParameters.damageDepthLimit = uint16_t(UINT16_MAX); + destructibleParameters.dynamicChunkDominanceGroup = uint16_t(UINT16_MAX); + destructibleParameters.dynamicChunksGroupsMask.useGroupsMask = bool(false); + destructibleParameters.dynamicChunksGroupsMask.bits0 = uint32_t(0); + destructibleParameters.dynamicChunksGroupsMask.bits1 = uint32_t(0); + destructibleParameters.dynamicChunksGroupsMask.bits2 = uint32_t(0); + destructibleParameters.dynamicChunksGroupsMask.bits3 = uint32_t(0); + destructibleParameters.runtimeFracture.RuntimeFractureType = (const char*)"VORONOI"; + destructibleParameters.runtimeFracture.sheetFracture = bool(true); + destructibleParameters.runtimeFracture.depthLimit = uint32_t(2); + destructibleParameters.runtimeFracture.destroyIfAtDepthLimit = bool(false); + destructibleParameters.runtimeFracture.minConvexSize = float(0.02); + destructibleParameters.runtimeFracture.impulseScale = float(1); + destructibleParameters.runtimeFracture.glass.numSectors = uint32_t(10); + destructibleParameters.runtimeFracture.glass.sectorRand = float(0.3); + destructibleParameters.runtimeFracture.glass.firstSegmentSize = float(0.06); + destructibleParameters.runtimeFracture.glass.segmentScale = float(1.4); + destructibleParameters.runtimeFracture.glass.segmentRand = float(0.3); + destructibleParameters.runtimeFracture.voronoi.dimensions = physx::PxVec3(physx::PxVec3(10.0f)); + destructibleParameters.runtimeFracture.voronoi.numCells = uint32_t(1); + destructibleParameters.runtimeFracture.voronoi.biasExp = float(10); + destructibleParameters.runtimeFracture.voronoi.maxDist = float(PX_MAX_F32); + destructibleParameters.runtimeFracture.attachment.posX = bool(false); + destructibleParameters.runtimeFracture.attachment.negX = bool(false); + destructibleParameters.runtimeFracture.attachment.posY = bool(false); + destructibleParameters.runtimeFracture.attachment.negY = bool(false); + destructibleParameters.runtimeFracture.attachment.posZ = bool(false); + destructibleParameters.runtimeFracture.attachment.negZ = bool(false); + destructibleParameters.supportStrength = float(-1); + destructibleParameters.legacyChunkBoundsTestSetting = int8_t(-1); + destructibleParameters.legacyDamageRadiusSpreadSetting = int8_t(-1); + destructibleParameters.alwaysDrawScatterMesh = bool(false); + initialDestructibleActorAllowanceForInstancing = uint32_t(0); + neighborPadding = float(0.001); + supportDepth = uint32_t(0); + formExtendedStructures = bool(false); + useAssetDefinedSupport = bool(false); + useWorldSupport = bool(false); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void DestructibleAssetParameters::initReferences(void) +{ + collisionData = NULL; + + renderMeshAsset = NULL; + +} + +void DestructibleAssetParameters::freeDynamicArrays(void) +{ + if (behaviorGroups.isAllocated && behaviorGroups.buf) + { + mParameterizedTraits->free(behaviorGroups.buf); + } + if (chunks.isAllocated && chunks.buf) + { + mParameterizedTraits->free(chunks.buf); + } + if (chunkConvexHulls.isAllocated && chunkConvexHulls.buf) + { + mParameterizedTraits->free(chunkConvexHulls.buf); + } + if (chunkConvexHullStartIndices.isAllocated && chunkConvexHullStartIndices.buf) + { + mParameterizedTraits->free(chunkConvexHullStartIndices.buf); + } + if (depthParameters.isAllocated && depthParameters.buf) + { + mParameterizedTraits->free(depthParameters.buf); + } + if (chunkInstanceInfo.isAllocated && chunkInstanceInfo.buf) + { + mParameterizedTraits->free(chunkInstanceInfo.buf); + } + if (staticMaterialNames.isAllocated && staticMaterialNames.buf) + { + mParameterizedTraits->free(staticMaterialNames.buf); + } + if (overlapsAtDepth.isAllocated && overlapsAtDepth.buf) + { + mParameterizedTraits->free(overlapsAtDepth.buf); + } + if (firstChunkAtDepth.isAllocated && firstChunkAtDepth.buf) + { + mParameterizedTraits->free(firstChunkAtDepth.buf); + } + if (actorTransforms.isAllocated && actorTransforms.buf) + { + mParameterizedTraits->free(actorTransforms.buf); + } + if (scatterMeshAssets.isAllocated && scatterMeshAssets.buf) + { + mParameterizedTraits->free(scatterMeshAssets.buf); + } + if (scatterMeshIndices.isAllocated && scatterMeshIndices.buf) + { + mParameterizedTraits->free(scatterMeshIndices.buf); + } + if (scatterMeshTransforms.isAllocated && scatterMeshTransforms.buf) + { + mParameterizedTraits->free(scatterMeshTransforms.buf); + } +} + +void DestructibleAssetParameters::freeStrings(void) +{ + + if (comments.isAllocated && comments.buf) + { + mParameterizedTraits->strfree((char*)comments.buf); + } + + if (defaultBehaviorGroup.name.isAllocated && defaultBehaviorGroup.name.buf) + { + mParameterizedTraits->strfree((char*)defaultBehaviorGroup.name.buf); + } + + for (int i = 0; i < behaviorGroups.arraySizes[0]; ++i) + { + if (behaviorGroups.buf[i].name.isAllocated && behaviorGroups.buf[i].name.buf) + { + mParameterizedTraits->strfree((char*)behaviorGroups.buf[i].name.buf); + } + } + + if (crumbleEmitterName.isAllocated && crumbleEmitterName.buf) + { + mParameterizedTraits->strfree((char*)crumbleEmitterName.buf); + } + + if (dustEmitterName.isAllocated && dustEmitterName.buf) + { + mParameterizedTraits->strfree((char*)dustEmitterName.buf); + } + + for (int i = 0; i < staticMaterialNames.arraySizes[0]; ++i) + { + if (staticMaterialNames.buf[i].isAllocated && staticMaterialNames.buf[i].buf) + { + mParameterizedTraits->strfree((char*)staticMaterialNames.buf[i].buf); + } + } +} + +void DestructibleAssetParameters::freeReferences(void) +{ + + for (int i = 0; i < chunkConvexHulls.arraySizes[0]; ++i) + { + if (chunkConvexHulls.buf[i]) + { + chunkConvexHulls.buf[i]->destroy(); + } + } + if (collisionData) + { + collisionData->destroy(); + } + + if (renderMeshAsset) + { + renderMeshAsset->destroy(); + } + + + for (int i = 0; i < overlapsAtDepth.arraySizes[0]; ++i) + { + if (overlapsAtDepth.buf[i]) + { + overlapsAtDepth.buf[i]->destroy(); + } + } + + for (int i = 0; i < scatterMeshAssets.arraySizes[0]; ++i) + { + if (scatterMeshAssets.buf[i]) + { + scatterMeshAssets.buf[i]->destroy(); + } + } +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/DestructibleDebugRenderParams.cpp b/APEX_1.4/module/destructible/src/autogen/DestructibleDebugRenderParams.cpp new file mode 100644 index 00000000..f11fc194 --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/DestructibleDebugRenderParams.cpp @@ -0,0 +1,508 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "DestructibleDebugRenderParams.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace DestructibleDebugRenderParamsNS; + +const char* const DestructibleDebugRenderParamsFactory::vptr = + NvParameterized::getVptr<DestructibleDebugRenderParams, DestructibleDebugRenderParams::ClassAlignment>(); + +const uint32_t NumParamDefs = 10; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 9 }, + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->VISUALIZE_DESTRUCTIBLE_ACTOR), NULL, 0 }, // VISUALIZE_DESTRUCTIBLE_ACTOR + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->VISUALIZE_DESTRUCTIBLE_BOUNDS), NULL, 0 }, // VISUALIZE_DESTRUCTIBLE_BOUNDS + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->VISUALIZE_DESTRUCTIBLE_SUPPORT), NULL, 0 }, // VISUALIZE_DESTRUCTIBLE_SUPPORT + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->VISUALIZE_DESTRUCTIBLE_ACTOR_POSE), NULL, 0 }, // VISUALIZE_DESTRUCTIBLE_ACTOR_POSE + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_POSE), NULL, 0 }, // THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_POSE + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->VISUALIZE_DESTRUCTIBLE_ACTOR_NAME), NULL, 0 }, // VISUALIZE_DESTRUCTIBLE_ACTOR_NAME + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_NAME), NULL, 0 }, // THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_NAME + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->VISUALIZE_DESTRUCTIBLE_FRAGMENT_POSE), NULL, 0 }, // VISUALIZE_DESTRUCTIBLE_FRAGMENT_POSE + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->THRESHOLD_DISTANCE_DESTRUCTIBLE_FRAGMENT_POSE), NULL, 0 }, // THRESHOLD_DISTANCE_DESTRUCTIBLE_FRAGMENT_POSE +}; + + +bool DestructibleDebugRenderParams::mBuiltFlag = false; +NvParameterized::MutexType DestructibleDebugRenderParams::mBuiltFlagMutex; + +DestructibleDebugRenderParams::DestructibleDebugRenderParams(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &DestructibleDebugRenderParamsFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +DestructibleDebugRenderParams::~DestructibleDebugRenderParams() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void DestructibleDebugRenderParams::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~DestructibleDebugRenderParams(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* DestructibleDebugRenderParams::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* DestructibleDebugRenderParams::getParameterDefinitionTree(void) const +{ + DestructibleDebugRenderParams* tmpParam = const_cast<DestructibleDebugRenderParams*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType DestructibleDebugRenderParams::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType DestructibleDebugRenderParams::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void DestructibleDebugRenderParams::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<DestructibleDebugRenderParams::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ + +void DestructibleDebugRenderParams::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void DestructibleDebugRenderParams::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="VISUALIZE_DESTRUCTIBLE_ACTOR" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("VISUALIZE_DESTRUCTIBLE_ACTOR", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Module switch - whether or not to visualize destruction.", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="VISUALIZE_DESTRUCTIBLE_BOUNDS" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("VISUALIZE_DESTRUCTIBLE_BOUNDS", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Shows the axis-aligned bounding box which contains all chunks for each destructible actor.", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="VISUALIZE_DESTRUCTIBLE_SUPPORT" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("VISUALIZE_DESTRUCTIBLE_SUPPORT", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Shows the support graph as lines and support chunks' bounding boxes.", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="VISUALIZE_DESTRUCTIBLE_ACTOR_POSE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("VISUALIZE_DESTRUCTIBLE_ACTOR_POSE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Shows the coordinate frame representing the local origin for unfractured destructibles.", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_POSE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_POSE", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "If VISUALIZE_DESTRUCTIBLE_ACTOR_POSE is true, the maximum object-to-eye distance to draw the chunk poses.", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=6, longName="VISUALIZE_DESTRUCTIBLE_ACTOR_NAME" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6]; + ParamDef->init("VISUALIZE_DESTRUCTIBLE_ACTOR_NAME", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Shows the name of each destructible.", true); + ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=7, longName="THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_NAME" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7]; + ParamDef->init("THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_NAME", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "If VISUALIZE_DESTRUCTIBLE_ACTOR_NAME is true, the maximum object-to-eye distance to draw the actor names.", true); + ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=8, longName="VISUALIZE_DESTRUCTIBLE_FRAGMENT_POSE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8]; + ParamDef->init("VISUALIZE_DESTRUCTIBLE_FRAGMENT_POSE", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Shows the coordinate frame representing the local origin for each chunk island.", true); + ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=9, longName="THRESHOLD_DISTANCE_DESTRUCTIBLE_FRAGMENT_POSE" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9]; + ParamDef->init("THRESHOLD_DISTANCE_DESTRUCTIBLE_FRAGMENT_POSE", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "If VISUALIZE_DESTRUCTIBLE_FRAGMENT_POSE is true, the maximum object-to-eye distance to draw the fragment poses", true); + ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[9]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(2); + Children[2] = PDEF_PTR(3); + Children[3] = PDEF_PTR(4); + Children[4] = PDEF_PTR(5); + Children[5] = PDEF_PTR(6); + Children[6] = PDEF_PTR(7); + Children[7] = PDEF_PTR(8); + Children[8] = PDEF_PTR(9); + + ParamDefTable[0].setChildren(Children, 9); + } + + mBuiltFlag = true; + +} +void DestructibleDebugRenderParams::initStrings(void) +{ +} + +void DestructibleDebugRenderParams::initDynamicArrays(void) +{ +} + +void DestructibleDebugRenderParams::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + VISUALIZE_DESTRUCTIBLE_ACTOR = bool(true); + VISUALIZE_DESTRUCTIBLE_BOUNDS = float(0); + VISUALIZE_DESTRUCTIBLE_SUPPORT = float(0); + VISUALIZE_DESTRUCTIBLE_ACTOR_POSE = bool(true); + THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_POSE = float(3.402823466e+038); + VISUALIZE_DESTRUCTIBLE_ACTOR_NAME = bool(true); + THRESHOLD_DISTANCE_DESTRUCTIBLE_ACTOR_NAME = float(3.402823466e+038); + VISUALIZE_DESTRUCTIBLE_FRAGMENT_POSE = bool(true); + THRESHOLD_DISTANCE_DESTRUCTIBLE_FRAGMENT_POSE = float(3.402823466e+038); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void DestructibleDebugRenderParams::initReferences(void) +{ +} + +void DestructibleDebugRenderParams::freeDynamicArrays(void) +{ +} + +void DestructibleDebugRenderParams::freeStrings(void) +{ +} + +void DestructibleDebugRenderParams::freeReferences(void) +{ +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/DestructibleModuleParameters.cpp b/APEX_1.4/module/destructible/src/autogen/DestructibleModuleParameters.cpp new file mode 100644 index 00000000..ca5d7abc --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/DestructibleModuleParameters.cpp @@ -0,0 +1,505 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "DestructibleModuleParameters.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace DestructibleModuleParametersNS; + +const char* const DestructibleModuleParametersFactory::vptr = + NvParameterized::getVptr<DestructibleModuleParameters, DestructibleModuleParameters::ClassAlignment>(); + +const uint32_t NumParamDefs = 9; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 8 }, + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->maxDynamicChunkIslandCount), NULL, 0 }, // maxDynamicChunkIslandCount + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->sortFIFOByBenefit), NULL, 0 }, // sortFIFOByBenefit + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->validBoundsPadding), NULL, 0 }, // validBoundsPadding + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->maxChunkSeparationLOD), NULL, 0 }, // maxChunkSeparationLOD + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->maxActorCreatesPerFrame), NULL, 0 }, // maxActorCreatesPerFrame + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->maxChunkDepthOffset), NULL, 0 }, // maxChunkDepthOffset + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->massScale), NULL, 0 }, // massScale + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->scaledMassExponent), NULL, 0 }, // scaledMassExponent +}; + + +bool DestructibleModuleParameters::mBuiltFlag = false; +NvParameterized::MutexType DestructibleModuleParameters::mBuiltFlagMutex; + +DestructibleModuleParameters::DestructibleModuleParameters(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &DestructibleModuleParametersFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +DestructibleModuleParameters::~DestructibleModuleParameters() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void DestructibleModuleParameters::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~DestructibleModuleParameters(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* DestructibleModuleParameters::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* DestructibleModuleParameters::getParameterDefinitionTree(void) const +{ + DestructibleModuleParameters* tmpParam = const_cast<DestructibleModuleParameters*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType DestructibleModuleParameters::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType DestructibleModuleParameters::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void DestructibleModuleParameters::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<DestructibleModuleParameters::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ + +void DestructibleModuleParameters::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void DestructibleModuleParameters::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "This class is used for initializing the ModuleDestructible.", true); + ParamDefTable[0].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="maxDynamicChunkIslandCount" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("maxDynamicChunkIslandCount", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "The maximum number of dynamic PxActors that will be allowed to be active per ApexScene. A value of 0 (the default) is interpreted as no limit.", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="sortFIFOByBenefit" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("sortFIFOByBenefit", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Instead of keeping the maxCount youngest, use maxCount largest benefit if this is true.", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="validBoundsPadding" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("validBoundsPadding", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "The padding applied to the combined scene valid bounds and Destructible actor bounds. The final combined and passed bounds is used to cull PxActors", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="maxChunkSeparationLOD" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("maxChunkSeparationLOD", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("max", uint64_t(1), true); + HintTable[1].init("min", uint64_t(0), true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#else + + static HintImpl HintTable[4]; + static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], }; + HintTable[0].init("longDescription", "Chunk islands are destroyed after this time or separation from their origins. This parameter sets the lifetimes and max separations within their min-max ranges. The valid range is [0,1]. Default is 0.5.", true); + HintTable[1].init("max", uint64_t(1), true); + HintTable[2].init("min", uint64_t(0), true); + HintTable[3].init("shortDescription", "Every destructible asset defines a min and max lifetime, and maximum separation distance for its chunks.", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 4); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="maxActorCreatesPerFrame" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("maxActorCreatesPerFrame", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("shortDescription", "Lets the user throttle the number of SDK actor creates per frame (per scene) due to destruction, as this can be quite costly. The default is 0xffffffff (unlimited).", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=6, longName="maxChunkDepthOffset" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6]; + ParamDef->init("maxChunkDepthOffset", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If maxChunkDepthOffset = 0, all chunks can be fractured. If maxChunkDepthOffset = 1, the highest level (smallest) chunks are eliminated, etc. This prevents too many chunks from being formed. In other words, the higher maxChunkDepthOffset, the lower the LOD.", true); + HintTable[1].init("shortDescription", "Effectively eliminates the higher level (smaller) chunks from DestructibleAssets (see DestructibleAsset).", true); + ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=7, longName="massScale" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7]; + ParamDef->init("massScale", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Used with scaledMassExponent for scaling dynamic chunk masses.\nThe 'real' mass m of a chunk is calculated by the destructible actor's density multiplied by\nthe total volume of the chunk's (scaled) collision shapes. The mass used in\nthe simulation is massScale*pow(m/massScale,scaledMassExponent). Values less than 1 have the\neffect of reducing the ratio of different masses. The closer scaledMassExponent is to zero, the\nmore the ratio will be 'flattened.' This helps PhysX converge when there is a very large number\nof interacting rigid bodies (such as a pile of destructible chunks).\nValid range: (0,infinity). Default = 1.0.\n", true); + HintTable[1].init("shortDescription", "Used with scaledMassExponent for scaling dynamic chunk masses.", true); + ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=8, longName="scaledMassExponent" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8]; + ParamDef->init("scaledMassExponent", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Used with massScale for scaling dynamic chunk masses.\nThe 'real' mass m of a chunk is calculated by the destructible actor's density multiplied by\nthe total volume of the chunk's (scaled) collision shapes. The mass used in\nthe simulation is massScale*pow(m/massScale,scaledMassExponent). Values less than 1 have the\neffect of reducing the ratio of different masses. The closer scaledMassExponent is to zero, the\nmore the ratio will be 'flattened.' This helps PhysX converge when there is a very large number\nof interacting rigid bodies (such as a pile of destructible chunks).\nValid range: (0,1]. Default = 0.5.\n", true); + HintTable[1].init("shortDescription", "Used with massScale for scaling dynamic chunk masses.", true); + ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[8]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(2); + Children[2] = PDEF_PTR(3); + Children[3] = PDEF_PTR(4); + Children[4] = PDEF_PTR(5); + Children[5] = PDEF_PTR(6); + Children[6] = PDEF_PTR(7); + Children[7] = PDEF_PTR(8); + + ParamDefTable[0].setChildren(Children, 8); + } + + mBuiltFlag = true; + +} +void DestructibleModuleParameters::initStrings(void) +{ +} + +void DestructibleModuleParameters::initDynamicArrays(void) +{ +} + +void DestructibleModuleParameters::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + maxDynamicChunkIslandCount = uint32_t(0); + sortFIFOByBenefit = bool(false); + validBoundsPadding = float(0); + maxChunkSeparationLOD = float(0.5); + maxActorCreatesPerFrame = uint32_t(UINT32_MAX); + maxChunkDepthOffset = uint32_t(0); + massScale = float(1); + scaledMassExponent = float(0.5); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void DestructibleModuleParameters::initReferences(void) +{ +} + +void DestructibleModuleParameters::freeDynamicArrays(void) +{ +} + +void DestructibleModuleParameters::freeStrings(void) +{ +} + +void DestructibleModuleParameters::freeReferences(void) +{ +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/DestructiblePreviewParam.cpp b/APEX_1.4/module/destructible/src/autogen/DestructiblePreviewParam.cpp new file mode 100644 index 00000000..53055f9f --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/DestructiblePreviewParam.cpp @@ -0,0 +1,572 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "DestructiblePreviewParam.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace DestructiblePreviewParamNS; + +const char* const DestructiblePreviewParamFactory::vptr = + NvParameterized::getVptr<DestructiblePreviewParam, DestructiblePreviewParam::ClassAlignment>(); + +const uint32_t NumParamDefs = 10; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, 3, 4, 5, 7, 9, 6, 8, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 7 }, + { TYPE_MAT44, false, (size_t)(&((ParametersStruct*)0)->globalPose), NULL, 0 }, // globalPose + { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->chunkDepth), NULL, 0 }, // chunkDepth + { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->explodeAmount), NULL, 0 }, // explodeAmount + { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->renderUnexplodedChunksStatically), NULL, 0 }, // renderUnexplodedChunksStatically + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->overrideSkinnedMaterialNames), CHILDREN(7), 1 }, // overrideSkinnedMaterialNames + { TYPE_STRING, false, 1 * sizeof(NvParameterized::DummyStringStruct), NULL, 0 }, // overrideSkinnedMaterialNames[] + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->overrideStaticMaterialNames), CHILDREN(8), 1 }, // overrideStaticMaterialNames + { TYPE_STRING, false, 1 * sizeof(NvParameterized::DummyStringStruct), NULL, 0 }, // overrideStaticMaterialNames[] + { TYPE_U64, false, (size_t)(&((ParametersStruct*)0)->userData), NULL, 0 }, // userData +}; + + +bool DestructiblePreviewParam::mBuiltFlag = false; +NvParameterized::MutexType DestructiblePreviewParam::mBuiltFlagMutex; + +DestructiblePreviewParam::DestructiblePreviewParam(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &DestructiblePreviewParamFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +DestructiblePreviewParam::~DestructiblePreviewParam() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void DestructiblePreviewParam::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~DestructiblePreviewParam(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* DestructiblePreviewParam::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* DestructiblePreviewParam::getParameterDefinitionTree(void) const +{ + DestructiblePreviewParam* tmpParam = const_cast<DestructiblePreviewParam*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType DestructiblePreviewParam::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType DestructiblePreviewParam::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void DestructiblePreviewParam::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<DestructiblePreviewParam::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ +/* [0] - overrideSkinnedMaterialNames (not an array of structs) */ +/* [0] - overrideStaticMaterialNames (not an array of structs) */ + +void DestructiblePreviewParam::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void DestructiblePreviewParam::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="globalPose" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("globalPose", TYPE_MAT44, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The pose for the destructible preview, including scaling.\n", true); + HintTable[1].init("shortDescription", "The pose for the destructible preview", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="chunkDepth" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("chunkDepth", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Which chunk depth to render.\n", true); + HintTable[1].init("shortDescription", "Which chunk depth to render.", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="explodeAmount" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("explodeAmount", TYPE_F32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "How far apart to 'explode' the chunks rendered. The value is relative to the chunk's initial offset from the origin.\n", true); + HintTable[1].init("shortDescription", "How far apart to 'explode' the chunks rendered.", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="renderUnexplodedChunksStatically" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("renderUnexplodedChunksStatically", TYPE_BOOL, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "If true, unexploded chunks (see explodeAmount) will be renderered statically (without skinning).\nDefault value = false.\n", true); + HintTable[1].init("shortDescription", "Whether or not to render unexploded chunks statically (without skinning)", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="overrideSkinnedMaterialNames" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("overrideSkinnedMaterialNames", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-actor material names, to override those in the asset, for skinned rendering.", true); + HintTable[1].init("shortDescription", "Per-actor material names, to override those in the asset, for skinned rendering", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=6, longName="overrideSkinnedMaterialNames[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6]; + ParamDef->init("overrideSkinnedMaterialNames", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-actor material names, to override those in the asset, for skinned rendering.", true); + HintTable[1].init("shortDescription", "Per-actor material names, to override those in the asset, for skinned rendering", true); + ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=7, longName="overrideStaticMaterialNames" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7]; + ParamDef->init("overrideStaticMaterialNames", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-actor material names, to override those in the asset, for static rendering.", true); + HintTable[1].init("shortDescription", "Per-actor material names, to override those in the asset, for static rendering", true); + ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=8, longName="overrideStaticMaterialNames[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8]; + ParamDef->init("overrideStaticMaterialNames", TYPE_STRING, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Per-actor material names, to override those in the asset, for static rendering.", true); + HintTable[1].init("shortDescription", "Per-actor material names, to override those in the asset, for static rendering", true); + ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=9, longName="userData" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9]; + ParamDef->init("userData", TYPE_U64, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("editorDisplay", "false", true); + ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("editorDisplay", "false", true); + HintTable[1].init("shortDescription", "Optional user data pointer associated with the destructible preview", true); + ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[7]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(2); + Children[2] = PDEF_PTR(3); + Children[3] = PDEF_PTR(4); + Children[4] = PDEF_PTR(5); + Children[5] = PDEF_PTR(7); + Children[6] = PDEF_PTR(9); + + ParamDefTable[0].setChildren(Children, 7); + } + + // SetChildren for: nodeIndex=5, longName="overrideSkinnedMaterialNames" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(6); + + ParamDefTable[5].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=7, longName="overrideStaticMaterialNames" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(8); + + ParamDefTable[7].setChildren(Children, 1); + } + + mBuiltFlag = true; + +} +void DestructiblePreviewParam::initStrings(void) +{ +} + +void DestructiblePreviewParam::initDynamicArrays(void) +{ + overrideSkinnedMaterialNames.buf = NULL; + overrideSkinnedMaterialNames.isAllocated = true; + overrideSkinnedMaterialNames.elementSize = sizeof(NvParameterized::DummyStringStruct); + overrideSkinnedMaterialNames.arraySizes[0] = 0; + overrideStaticMaterialNames.buf = NULL; + overrideStaticMaterialNames.isAllocated = true; + overrideStaticMaterialNames.elementSize = sizeof(NvParameterized::DummyStringStruct); + overrideStaticMaterialNames.arraySizes[0] = 0; +} + +void DestructiblePreviewParam::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + globalPose = physx::PxMat44(init(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)); + chunkDepth = uint32_t(0); + explodeAmount = float(0); + renderUnexplodedChunksStatically = bool(false); + userData = uint64_t(0); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void DestructiblePreviewParam::initReferences(void) +{ +} + +void DestructiblePreviewParam::freeDynamicArrays(void) +{ + if (overrideSkinnedMaterialNames.isAllocated && overrideSkinnedMaterialNames.buf) + { + mParameterizedTraits->free(overrideSkinnedMaterialNames.buf); + } + if (overrideStaticMaterialNames.isAllocated && overrideStaticMaterialNames.buf) + { + mParameterizedTraits->free(overrideStaticMaterialNames.buf); + } +} + +void DestructiblePreviewParam::freeStrings(void) +{ + + for (int i = 0; i < overrideSkinnedMaterialNames.arraySizes[0]; ++i) + { + if (overrideSkinnedMaterialNames.buf[i].isAllocated && overrideSkinnedMaterialNames.buf[i].buf) + { + mParameterizedTraits->strfree((char*)overrideSkinnedMaterialNames.buf[i].buf); + } + } + + for (int i = 0; i < overrideStaticMaterialNames.arraySizes[0]; ++i) + { + if (overrideStaticMaterialNames.buf[i].isAllocated && overrideStaticMaterialNames.buf[i].buf) + { + mParameterizedTraits->strfree((char*)overrideStaticMaterialNames.buf[i].buf); + } + } +} + +void DestructiblePreviewParam::freeReferences(void) +{ +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/MeshCookedCollisionStream.cpp b/APEX_1.4/module/destructible/src/autogen/MeshCookedCollisionStream.cpp new file mode 100644 index 00000000..074c9531 --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/MeshCookedCollisionStream.cpp @@ -0,0 +1,348 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "MeshCookedCollisionStream.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace MeshCookedCollisionStreamNS; + +const char* const MeshCookedCollisionStreamFactory::vptr = + NvParameterized::getVptr<MeshCookedCollisionStream, MeshCookedCollisionStream::ClassAlignment>(); + +const uint32_t NumParamDefs = 3; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 1 }, + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->bytes), CHILDREN(1), 1 }, // bytes + { TYPE_U8, false, 1 * sizeof(uint8_t), NULL, 0 }, // bytes[] +}; + + +bool MeshCookedCollisionStream::mBuiltFlag = false; +NvParameterized::MutexType MeshCookedCollisionStream::mBuiltFlagMutex; + +MeshCookedCollisionStream::MeshCookedCollisionStream(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &MeshCookedCollisionStreamFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +MeshCookedCollisionStream::~MeshCookedCollisionStream() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void MeshCookedCollisionStream::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~MeshCookedCollisionStream(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* MeshCookedCollisionStream::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* MeshCookedCollisionStream::getParameterDefinitionTree(void) const +{ + MeshCookedCollisionStream* tmpParam = const_cast<MeshCookedCollisionStream*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType MeshCookedCollisionStream::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType MeshCookedCollisionStream::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void MeshCookedCollisionStream::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<MeshCookedCollisionStream::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ + +void MeshCookedCollisionStream::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void MeshCookedCollisionStream::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="bytes" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("bytes", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A byte stream used to store cooked convex collision data. One\n is needed for every chunk at every scale which will be instanced.", true); + HintTable[1].init("shortDescription", "A byte stream used to store cooked convex collision data", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="bytes[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("bytes", TYPE_U8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "A byte stream used to store cooked convex collision data. One\n is needed for every chunk at every scale which will be instanced.", true); + HintTable[1].init("shortDescription", "A byte stream used to store cooked convex collision data", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(1); + + ParamDefTable[0].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=1, longName="bytes" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(2); + + ParamDefTable[1].setChildren(Children, 1); + } + + mBuiltFlag = true; + +} +void MeshCookedCollisionStream::initStrings(void) +{ +} + +void MeshCookedCollisionStream::initDynamicArrays(void) +{ + bytes.buf = NULL; + bytes.isAllocated = true; + bytes.elementSize = sizeof(uint8_t); + bytes.arraySizes[0] = 0; +} + +void MeshCookedCollisionStream::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void MeshCookedCollisionStream::initReferences(void) +{ +} + +void MeshCookedCollisionStream::freeDynamicArrays(void) +{ + if (bytes.isAllocated && bytes.buf) + { + mParameterizedTraits->free(bytes.buf); + } +} + +void MeshCookedCollisionStream::freeStrings(void) +{ +} + +void MeshCookedCollisionStream::freeReferences(void) +{ +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/MeshCookedCollisionStreamsAtScale.cpp b/APEX_1.4/module/destructible/src/autogen/MeshCookedCollisionStreamsAtScale.cpp new file mode 100644 index 00000000..c8693a9e --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/MeshCookedCollisionStreamsAtScale.cpp @@ -0,0 +1,376 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "MeshCookedCollisionStreamsAtScale.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace MeshCookedCollisionStreamsAtScaleNS; + +const char* const MeshCookedCollisionStreamsAtScaleFactory::vptr = + NvParameterized::getVptr<MeshCookedCollisionStreamsAtScale, MeshCookedCollisionStreamsAtScale::ClassAlignment>(); + +const uint32_t NumParamDefs = 3; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 2, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 1 }, + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->meshCookedCollisionStreams), CHILDREN(1), 1 }, // meshCookedCollisionStreams + { TYPE_REF, false, 1 * sizeof(NvParameterized::Interface*), NULL, 0 }, // meshCookedCollisionStreams[] +}; + + +bool MeshCookedCollisionStreamsAtScale::mBuiltFlag = false; +NvParameterized::MutexType MeshCookedCollisionStreamsAtScale::mBuiltFlagMutex; + +MeshCookedCollisionStreamsAtScale::MeshCookedCollisionStreamsAtScale(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &MeshCookedCollisionStreamsAtScaleFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +MeshCookedCollisionStreamsAtScale::~MeshCookedCollisionStreamsAtScale() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void MeshCookedCollisionStreamsAtScale::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~MeshCookedCollisionStreamsAtScale(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* MeshCookedCollisionStreamsAtScale::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* MeshCookedCollisionStreamsAtScale::getParameterDefinitionTree(void) const +{ + MeshCookedCollisionStreamsAtScale* tmpParam = const_cast<MeshCookedCollisionStreamsAtScale*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType MeshCookedCollisionStreamsAtScale::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType MeshCookedCollisionStreamsAtScale::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void MeshCookedCollisionStreamsAtScale::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<MeshCookedCollisionStreamsAtScale::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ +/* [0] - meshCookedCollisionStreams (not an array of structs) */ + +void MeshCookedCollisionStreamsAtScale::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void MeshCookedCollisionStreamsAtScale::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="meshCookedCollisionStreams" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("meshCookedCollisionStreams", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "An array of collision hull byte streams. These will be the convex\n hulls for all chunks at a particular scale.", true); + HintTable[2].init("shortDescription", "An array of collision hull byte streams", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "MeshCookedCollisionStream" }; + ParamDefTable[1].setRefVariantVals((const char**)RefVariantVals, 1); + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="meshCookedCollisionStreams[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("meshCookedCollisionStreams", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "An array of collision hull byte streams. These will be the convex\n hulls for all chunks at a particular scale.", true); + HintTable[2].init("shortDescription", "An array of collision hull byte streams", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "MeshCookedCollisionStream" }; + ParamDefTable[2].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(1); + + ParamDefTable[0].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=1, longName="meshCookedCollisionStreams" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(2); + + ParamDefTable[1].setChildren(Children, 1); + } + + mBuiltFlag = true; + +} +void MeshCookedCollisionStreamsAtScale::initStrings(void) +{ +} + +void MeshCookedCollisionStreamsAtScale::initDynamicArrays(void) +{ + meshCookedCollisionStreams.buf = NULL; + meshCookedCollisionStreams.isAllocated = true; + meshCookedCollisionStreams.elementSize = sizeof(NvParameterized::Interface*); + meshCookedCollisionStreams.arraySizes[0] = 0; +} + +void MeshCookedCollisionStreamsAtScale::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void MeshCookedCollisionStreamsAtScale::initReferences(void) +{ +} + +void MeshCookedCollisionStreamsAtScale::freeDynamicArrays(void) +{ + if (meshCookedCollisionStreams.isAllocated && meshCookedCollisionStreams.buf) + { + mParameterizedTraits->free(meshCookedCollisionStreams.buf); + } +} + +void MeshCookedCollisionStreamsAtScale::freeStrings(void) +{ +} + +void MeshCookedCollisionStreamsAtScale::freeReferences(void) +{ + + for (int i = 0; i < meshCookedCollisionStreams.arraySizes[0]; ++i) + { + if (meshCookedCollisionStreams.buf[i]) + { + meshCookedCollisionStreams.buf[i]->destroy(); + } + } +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/SurfaceTraceParameters.cpp b/APEX_1.4/module/destructible/src/autogen/SurfaceTraceParameters.cpp new file mode 100644 index 00000000..7a4cfbef --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/SurfaceTraceParameters.cpp @@ -0,0 +1,438 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "SurfaceTraceParameters.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace SurfaceTraceParametersNS; + +const char* const SurfaceTraceParametersFactory::vptr = + NvParameterized::getVptr<SurfaceTraceParameters, SurfaceTraceParameters::ClassAlignment>(); + +const uint32_t NumParamDefs = 6; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 3, 5, 2, 4, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 3 }, + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->submeshIndices), CHILDREN(3), 1 }, // submeshIndices + { TYPE_U8, false, 1 * sizeof(uint8_t), NULL, 0 }, // submeshIndices[] + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->vertexIndices), CHILDREN(4), 1 }, // vertexIndices + { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // vertexIndices[] + { TYPE_VEC3, false, (size_t)(&((ParametersStruct*)0)->defaultNormal), NULL, 0 }, // defaultNormal +}; + + +bool SurfaceTraceParameters::mBuiltFlag = false; +NvParameterized::MutexType SurfaceTraceParameters::mBuiltFlagMutex; + +SurfaceTraceParameters::SurfaceTraceParameters(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &SurfaceTraceParametersFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +SurfaceTraceParameters::~SurfaceTraceParameters() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void SurfaceTraceParameters::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~SurfaceTraceParameters(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* SurfaceTraceParameters::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* SurfaceTraceParameters::getParameterDefinitionTree(void) const +{ + SurfaceTraceParameters* tmpParam = const_cast<SurfaceTraceParameters*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType SurfaceTraceParameters::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType SurfaceTraceParameters::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void SurfaceTraceParameters::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<SurfaceTraceParameters::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ + +void SurfaceTraceParameters::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void SurfaceTraceParameters::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="submeshIndices" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("submeshIndices", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The submeshes to which the corresponding vertices (in vertexIndices) belong.\n The surface traces are defined as a set of vertex indices, but these indices are relative to\n a submesh. The size of submeshIndices must be equal to the size of vertexIndices.", true); + HintTable[1].init("shortDescription", "The submeshes to which the corresponding vertices (in vertexIndices) belong", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="submeshIndices[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("submeshIndices", TYPE_U8, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The submeshes to which the corresponding vertices (in vertexIndices) belong.\n The surface traces are defined as a set of vertex indices, but these indices are relative to\n a submesh. The size of submeshIndices must be equal to the size of vertexIndices.", true); + HintTable[1].init("shortDescription", "The submeshes to which the corresponding vertices (in vertexIndices) belong", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="vertexIndices" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("vertexIndices", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The vertex indices defining the surface trace. The surface traces are defined\n as a set of vertex indices, but these indices are relative to a submesh. The size of submeshIndices\n must be equal to the size of vertexIndices.", true); + HintTable[1].init("shortDescription", "The vertex indices defining the surface trace.", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + ParamDef->setArraySize(-1); + } + + // Initialize DefinitionImpl node: nodeIndex=4, longName="vertexIndices[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4]; + ParamDef->init("vertexIndices", TYPE_U32, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The vertex indices defining the surface trace. The surface traces are defined\n as a set of vertex indices, but these indices are relative to a submesh. The size of submeshIndices\n must be equal to the size of vertexIndices.", true); + HintTable[1].init("shortDescription", "The vertex indices defining the surface trace.", true); + ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=5, longName="defaultNormal" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5]; + ParamDef->init("defaultNormal", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "The average surface normal for this trace. A surface trace is a single closed loop\n on the surface of the mesh, along triangle boundaries. This normal is the normalized average of the\n surface triangles enclosed by the loop.", true); + HintTable[1].init("shortDescription", "The average surface normal for this trace", true); + ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[3]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(3); + Children[2] = PDEF_PTR(5); + + ParamDefTable[0].setChildren(Children, 3); + } + + // SetChildren for: nodeIndex=1, longName="submeshIndices" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(2); + + ParamDefTable[1].setChildren(Children, 1); + } + + // SetChildren for: nodeIndex=3, longName="vertexIndices" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(4); + + ParamDefTable[3].setChildren(Children, 1); + } + + mBuiltFlag = true; + +} +void SurfaceTraceParameters::initStrings(void) +{ +} + +void SurfaceTraceParameters::initDynamicArrays(void) +{ + submeshIndices.buf = NULL; + submeshIndices.isAllocated = true; + submeshIndices.elementSize = sizeof(uint8_t); + submeshIndices.arraySizes[0] = 0; + vertexIndices.buf = NULL; + vertexIndices.isAllocated = true; + vertexIndices.elementSize = sizeof(uint32_t); + vertexIndices.arraySizes[0] = 0; +} + +void SurfaceTraceParameters::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void SurfaceTraceParameters::initReferences(void) +{ +} + +void SurfaceTraceParameters::freeDynamicArrays(void) +{ + if (submeshIndices.isAllocated && submeshIndices.buf) + { + mParameterizedTraits->free(submeshIndices.buf); + } + if (vertexIndices.isAllocated && vertexIndices.buf) + { + mParameterizedTraits->free(vertexIndices.buf); + } +} + +void SurfaceTraceParameters::freeStrings(void) +{ +} + +void SurfaceTraceParameters::freeReferences(void) +{ +} + +} // namespace destructible +} // namespace nvidia diff --git a/APEX_1.4/module/destructible/src/autogen/SurfaceTraceSetParameters.cpp b/APEX_1.4/module/destructible/src/autogen/SurfaceTraceSetParameters.cpp new file mode 100644 index 00000000..d5b35283 --- /dev/null +++ b/APEX_1.4/module/destructible/src/autogen/SurfaceTraceSetParameters.cpp @@ -0,0 +1,402 @@ +// 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) 2008-2015 NVIDIA Corporation. All rights reserved. + +// This file was generated by NvParameterized/scripts/GenParameterized.pl + + +#include "SurfaceTraceSetParameters.h" +#include <string.h> +#include <stdlib.h> + +using namespace NvParameterized; + +namespace nvidia +{ +namespace destructible +{ + +using namespace SurfaceTraceSetParametersNS; + +const char* const SurfaceTraceSetParametersFactory::vptr = + NvParameterized::getVptr<SurfaceTraceSetParameters, SurfaceTraceSetParameters::ClassAlignment>(); + +const uint32_t NumParamDefs = 4; +static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs]; + + +static const size_t ParamLookupChildrenTable[] = +{ + 1, 3, 2, +}; + +#define TENUM(type) nvidia::##type +#define CHILDREN(index) &ParamLookupChildrenTable[index] +static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] = +{ + { TYPE_STRUCT, false, 0, CHILDREN(0), 2 }, + { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->traces), CHILDREN(2), 1 }, // traces + { TYPE_REF, false, 1 * sizeof(NvParameterized::Interface*), NULL, 0 }, // traces[] + { TYPE_VEC3, false, (size_t)(&((ParametersStruct*)0)->positionOffset), NULL, 0 }, // positionOffset +}; + + +bool SurfaceTraceSetParameters::mBuiltFlag = false; +NvParameterized::MutexType SurfaceTraceSetParameters::mBuiltFlagMutex; + +SurfaceTraceSetParameters::SurfaceTraceSetParameters(NvParameterized::Traits* traits, void* buf, int32_t* refCount) : + NvParameters(traits, buf, refCount) +{ + //mParameterizedTraits->registerFactory(className(), &SurfaceTraceSetParametersFactoryInst); + + if (!buf) //Do not init data if it is inplace-deserialized + { + initDynamicArrays(); + initStrings(); + initReferences(); + initDefaults(); + } +} + +SurfaceTraceSetParameters::~SurfaceTraceSetParameters() +{ + freeStrings(); + freeReferences(); + freeDynamicArrays(); +} + +void SurfaceTraceSetParameters::destroy() +{ + // We cache these fields here to avoid overwrite in destructor + bool doDeallocateSelf = mDoDeallocateSelf; + NvParameterized::Traits* traits = mParameterizedTraits; + int32_t* refCount = mRefCount; + void* buf = mBuffer; + + this->~SurfaceTraceSetParameters(); + + NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf); +} + +const NvParameterized::DefinitionImpl* SurfaceTraceSetParameters::getParameterDefinitionTree(void) +{ + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +const NvParameterized::DefinitionImpl* SurfaceTraceSetParameters::getParameterDefinitionTree(void) const +{ + SurfaceTraceSetParameters* tmpParam = const_cast<SurfaceTraceSetParameters*>(this); + + if (!mBuiltFlag) // Double-checked lock + { + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + if (!mBuiltFlag) + { + tmpParam->buildTree(); + } + } + + return(&ParamDefTable[0]); +} + +NvParameterized::ErrorType SurfaceTraceSetParameters::getParameterHandle(const char* long_name, Handle& handle) const +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +NvParameterized::ErrorType SurfaceTraceSetParameters::getParameterHandle(const char* long_name, Handle& handle) +{ + ErrorType Ret = NvParameters::getParameterHandle(long_name, handle); + if (Ret != ERROR_NONE) + { + return(Ret); + } + + size_t offset; + void* ptr; + + getVarPtr(handle, ptr, offset); + + if (ptr == NULL) + { + return(ERROR_INDEX_OUT_OF_RANGE); + } + + return(ERROR_NONE); +} + +void SurfaceTraceSetParameters::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const +{ + ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<SurfaceTraceSetParameters::ParametersStruct*>(¶meters()), handle, offset); +} + + +/* Dynamic Handle Indices */ +/* [0] - traces (not an array of structs) */ + +void SurfaceTraceSetParameters::freeParameterDefinitionTable(NvParameterized::Traits* traits) +{ + if (!traits) + { + return; + } + + if (!mBuiltFlag) // Double-checked lock + { + return; + } + + NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex); + + if (!mBuiltFlag) + { + return; + } + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + ParamDefTable[i].~DefinitionImpl(); + } + + traits->free(ParamDefTable); + + mBuiltFlag = false; +} + +#define PDEF_PTR(index) (&ParamDefTable[index]) + +void SurfaceTraceSetParameters::buildTree(void) +{ + + uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs; + ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize)); + memset(ParamDefTable, 0, allocSize); + + for (uint32_t i = 0; i < NumParamDefs; ++i) + { + NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits); + } + + // Initialize DefinitionImpl node: nodeIndex=0, longName="" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0]; + ParamDef->init("", TYPE_STRUCT, "STRUCT", true); + + + + + + + } + + // Initialize DefinitionImpl node: nodeIndex=1, longName="traces" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1]; + ParamDef->init("traces", TYPE_ARRAY, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "A set of surface traces belonging to a single chunk. Since chunks\n may have a complex shape, the triangles which are on the destructible's surface may not\n form a contiguous set. Therefore there may be more than one surface trace per chunk.", true); + HintTable[2].init("shortDescription", "A set of surface traces belonging to a single chunk", true); + ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "SurfaceTraceParameters" }; + ParamDefTable[1].setRefVariantVals((const char**)RefVariantVals, 1); + + + ParamDef->setArraySize(-1); + static const uint8_t dynHandleIndices[1] = { 0, }; + ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1); + + } + + // Initialize DefinitionImpl node: nodeIndex=2, longName="traces[]" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2]; + ParamDef->init("traces", TYPE_REF, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + + static HintImpl HintTable[1]; + static Hint* HintPtrTable[1] = { &HintTable[0], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1); + +#else + + static HintImpl HintTable[3]; + static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], }; + HintTable[0].init("INCLUDED", uint64_t(1), true); + HintTable[1].init("longDescription", "A set of surface traces belonging to a single chunk. Since chunks\n may have a complex shape, the triangles which are on the destructible's surface may not\n form a contiguous set. Therefore there may be more than one surface trace per chunk.", true); + HintTable[2].init("shortDescription", "A set of surface traces belonging to a single chunk", true); + ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 3); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + static const char* const RefVariantVals[] = { "SurfaceTraceParameters" }; + ParamDefTable[2].setRefVariantVals((const char**)RefVariantVals, 1); + + + + } + + // Initialize DefinitionImpl node: nodeIndex=3, longName="positionOffset" + { + NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3]; + ParamDef->init("positionOffset", TYPE_VEC3, NULL, true); + +#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS + +#else + + static HintImpl HintTable[2]; + static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], }; + HintTable[0].init("longDescription", "Chunk-local offset for this trace, needed for instanced chunks.", true); + HintTable[1].init("shortDescription", "Chunk-local offset for this trace, needed for instanced chunks", true); + ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2); + +#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */ + + + + + + } + + // SetChildren for: nodeIndex=0, longName="" + { + static Definition* Children[2]; + Children[0] = PDEF_PTR(1); + Children[1] = PDEF_PTR(3); + + ParamDefTable[0].setChildren(Children, 2); + } + + // SetChildren for: nodeIndex=1, longName="traces" + { + static Definition* Children[1]; + Children[0] = PDEF_PTR(2); + + ParamDefTable[1].setChildren(Children, 1); + } + + mBuiltFlag = true; + +} +void SurfaceTraceSetParameters::initStrings(void) +{ +} + +void SurfaceTraceSetParameters::initDynamicArrays(void) +{ + traces.buf = NULL; + traces.isAllocated = true; + traces.elementSize = sizeof(NvParameterized::Interface*); + traces.arraySizes[0] = 0; +} + +void SurfaceTraceSetParameters::initDefaults(void) +{ + + freeStrings(); + freeReferences(); + freeDynamicArrays(); + positionOffset = physx::PxVec3(physx::PxVec3(0.0f)); + + initDynamicArrays(); + initStrings(); + initReferences(); +} + +void SurfaceTraceSetParameters::initReferences(void) +{ +} + +void SurfaceTraceSetParameters::freeDynamicArrays(void) +{ + if (traces.isAllocated && traces.buf) + { + mParameterizedTraits->free(traces.buf); + } +} + +void SurfaceTraceSetParameters::freeStrings(void) +{ +} + +void SurfaceTraceSetParameters::freeReferences(void) +{ + + for (int i = 0; i < traces.arraySizes[0]; ++i) + { + if (traces.buf[i]) + { + traces.buf[i]->destroy(); + } + } +} + +} // namespace destructible +} // namespace nvidia |