aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/module/destructible/include/DestructibleStructureStressSolver.h
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/module/destructible/include/DestructibleStructureStressSolver.h
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'APEX_1.4/module/destructible/include/DestructibleStructureStressSolver.h')
-rw-r--r--APEX_1.4/module/destructible/include/DestructibleStructureStressSolver.h413
1 files changed, 413 insertions, 0 deletions
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