Revision control
++ // Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
++ // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
++ // SPDX-FileCopyrightText: Copyright (c) 2008-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
++ // SPDX-License-Identifier: Apache-2.0
++
++ #ifndef PX_PBD_PARTICLE_SYSTEM_H
++ #define PX_PBD_PARTICLE_SYSTEM_H
++
++ #include "foundation/PxSimpleTypes.h"
++ #include "foundation/PxVec3.h"
++ #include "foundation/PxArray.h"
++ #include "cudamanager/PxCudaTypes.h"
++ #include "PxParticleSystemFlag.h"
++ #include "PxFiltering.h"
++ #include "PxActor.h"
++ #include "PxParticleSystem.h"
++
++ #if !PX_DOXYGEN
++ namespace physx
++ {
++ #endif
++
++ #if PX_VC
++ #pragma warning(push)
++ #pragma warning(disable : 4435)
++ #endif
++
++ class PxCudaContextManager;
++ class PxGpuParticleSystem;
++
++ class PxParticleAndDiffuseBuffer;
++ class PxParticleBuffer;
++
++ /**
++ \brief Container to hold a pair of corresponding device and host pointers. These pointers should point to GPU / CPU mirrors of the same data, but
++ this is not enforced.
++ */
++ template <typename Type>
++ struct PxGpuMirroredPointer
++ {
++ Type* mDevicePtr;
++ Type* mHostPtr;
++
++ PxGpuMirroredPointer(Type* devicePtr, Type* hostPtr) : mDevicePtr(devicePtr), mHostPtr(hostPtr) { }
++ };
++
++ /**
++ \brief Particle system callback base class to schedule work that should be done before, while or after the particle system updates.
++ A call to fetchResultsParticleSystem() on the PxScene will synchronize the work such that the caller knows that all tasks of this callback completed.
++ */
++ class PxParticleSystemCallback
++ {
++ public:
++ /**
++ \brief Method gets called when dirty data from the particle system is uploated to the gpu
++
++ \param[in] gpuParticleSystem Pointers to the particle systems gpu data available as host accessible pointer and as gpu accessible pointer
++ \param[in] stream The stream on which all cuda kernel calls get scheduled for execution. A call to fetchResultsParticleSystem() on the
++ PxScene will synchronize the work such that the caller knows that the task completed.
++ */
++ virtual void onBegin(const PxGpuMirroredPointer<PxGpuParticleSystem>& gpuParticleSystem, CUstream stream) = 0;
++
++ /**
++ \brief Method gets called when the simulation step of the particle system is performed
++
++ \param[in] gpuParticleSystem Pointers to the particle systems gpu data available as host accessible pointer and as gpu accessible pointer
++ \param[in] stream The stream on which all cuda kernel calls get scheduled for execution. A call to fetchResultsParticleSystem() on the
++ PxScene will synchronize the work such that the caller knows that the task completed.
++ */
++ virtual void onAdvance(const PxGpuMirroredPointer<PxGpuParticleSystem>& gpuParticleSystem, CUstream stream) = 0;
++
++ /**
++ \brief Method gets called after the particle system simulation step completed
++
++ \param[in] gpuParticleSystem Pointers to the particle systems gpu data available as host accessible pointer and as gpu accessible pointer
++ \param[in] stream The stream on which all cuda kernel calls get scheduled for execution. A call to fetchResultsParticleSystem() on the
++ PxScene will synchronize the work such that the caller knows that the task completed.
++ */
++ virtual void onPostSolve(const PxGpuMirroredPointer<PxGpuParticleSystem>& gpuParticleSystem, CUstream stream) = 0;
++
++ /**
++ \brief Destructor
++ */
++ virtual ~PxParticleSystemCallback() {}
++ };
++
++ /**
++ \brief Special callback that forwards calls to arbitrarily many sub-callbacks
++ */
++ class PxMultiCallback : public PxParticleSystemCallback
++ {
++ private:
++ PxArray<PxParticleSystemCallback*> mCallbacks;
++
++ public:
++ PxMultiCallback() : mCallbacks(0) {}
++
++ virtual void onPostSolve(const PxGpuMirroredPointer<PxGpuParticleSystem>& gpuParticleSystem, CUstream stream) PX_OVERRIDE
++ {
++ for (PxU32 i = 0; i < mCallbacks.size(); ++i)
++ mCallbacks[i]->onPostSolve(gpuParticleSystem, stream);
++ }
++
++ virtual void onBegin(const PxGpuMirroredPointer<PxGpuParticleSystem>& gpuParticleSystem, CUstream stream) PX_OVERRIDE
++ {
++ for (PxU32 i = 0; i < mCallbacks.size(); ++i)
++ mCallbacks[i]->onBegin(gpuParticleSystem, stream);
++ }
++
++ virtual void onAdvance(const PxGpuMirroredPointer<PxGpuParticleSystem>& gpuParticleSystem, CUstream stream) PX_OVERRIDE
++ {
++ for (PxU32 i = 0; i < mCallbacks.size(); ++i)
++ mCallbacks[i]->onAdvance(gpuParticleSystem, stream);
++ }
++
++ /**
++ \brief Adds a callback
++
++ \param[in] callback The callback to add
++ \return True if the callback was added
++ */
++ bool addCallback(PxParticleSystemCallback* callback)
++ {
++ if (mCallbacks.find(callback) != mCallbacks.end())
++ return false;
++ mCallbacks.pushBack(callback);
++ return true;
++ }
++
++ /**
++ \brief Removes a callback
++
++ \param[in] callback The callback to remove
++ \return True if the callback was removed
++ */
++ bool removeCallback(const PxParticleSystemCallback* callback)
++ {
++ for (PxU32 i = 0; i < mCallbacks.size(); ++i)
++ {
++ if (mCallbacks[i] == callback)
++ {
++ mCallbacks.remove(i);
++ return true;
++ }
++ }
++ return false;
++ }
++ };
++
++ /**
++ \brief Flags which control the behaviour of a particle system.
++
++ See #PxPBDParticleSystem::setParticleFlag(), #PxPBDParticleSystem::setParticleFlags(), #PxPBDParticleSystem::getParticleFlags()
++ */
++ struct PxParticleFlag
++ {
++ enum Enum
++ {
++ eDISABLE_SELF_COLLISION = 1 << 0, //!< Disables particle self-collision
++ eDISABLE_RIGID_COLLISION = 1 << 1, //!< Disables particle-rigid body collision
++ eFULL_DIFFUSE_ADVECTION = 1 << 2, //!< Enables full advection of diffuse particles. By default, diffuse particles are advected only by particles in the cell they are contained. This flag enables full neighbourhood generation (more expensive).
++ eENABLE_SPECULATIVE_CCD = 1 << 3 //!< Enables speculative CCD for particle-rigid body collision. \see PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD.
++ };
++ };
++
++ typedef PxFlags<PxParticleFlag::Enum, PxU32> PxParticleFlags;
++
++ /**
++ \brief Collection of flags providing a mechanism to lock motion along a specific axis.
++
++ \see PxParticleSystem.setParticleLockFlag(), PxParticleSystem.getParticleLockFlags()
++ */
++ struct PxParticleLockFlag
++ {
++ enum Enum
++ {
++ eLOCK_X = (1 << 0),
++ eLOCK_Y = (1 << 1),
++ eLOCK_Z = (1 << 2)
++ };
++ };
++
++ typedef PxFlags<PxParticleLockFlag::Enum, PxU8> PxParticleLockFlags;
++ PX_FLAGS_OPERATORS(PxParticleLockFlag::Enum, PxU8)
++
++ /**
++ \brief A particle system that uses the position based dynamics(PBD) solver.
++
++ The position based dynamics solver for particle systems supports behaviors like
++ fluid, cloth, inflatables etc.
++
++ */
++ class PxPBDParticleSystem : public PxActor
++ {
++ public:
++
++ virtual ~PxPBDParticleSystem() {}
++
++ /**
++ \brief Sets the solver iteration counts for the body.
++
++ The position iteration count determines how accurately contacts and internal particle-particle
++ interactions (fluid density, self-collision) are resolved. With too few, particles can
++ become unstable or a fluid can appear too compressible; a higher position iteration count may help.
++
++ Velocity iterations run after the position solve and correct velocities only. Increasing the
++ velocity iteration count may reduce the velocity lag inherent in position-based dynamics at
++ contacts, as well as violent depenetration. Internal particle-particle interactions are not
++ solved for, biasing the velocity result toward contacts.
++
++ <b>Default:</b> 4 position iterations, 1 velocity iteration
++
++ \param[in] minPositionIters Number of position iterations the solver should perform for this particle system. <b>Range:</b> [1,255]
++ \param[in] minVelocityIters Number of velocity iterations the solver should perform for this particle system. <b>Range:</b> [0,255]
++
++ See #getSolverIterationCounts()
++ */
++ virtual void setSolverIterationCounts(PxU32 minPositionIters, PxU32 minVelocityIters = 1) = 0;
++
++ /**
++ \brief Retrieves the solver iteration counts.
++
++ See #setSolverIterationCounts()
++ */
++ virtual void getSolverIterationCounts(PxU32& minPositionIters, PxU32& minVelocityIters) const = 0;
++
++ /**
++ \brief Retrieves the collision filter settings.
++
++ \return The filter data
++ */
++ virtual PxFilterData getSimulationFilterData() const = 0;
++
++ /**
++ \brief Set collision filter settings
++
++ Allows to control with which objects the particle system collides
++
++ \param[in] data The filter data
++ */
++ virtual void setSimulationFilterData(const PxFilterData& data) = 0;
++
++ /**
++ \brief Set particle flag
++
++ Allows to control self collision etc.
++
++ \param[in] flag The flag to set
++ \param[in] val The new value of the flag
++ */
++ virtual void setParticleFlag(PxParticleFlag::Enum flag, bool val) = 0;
++
++ /**
++ \brief Set particle flags
++
++ Allows to control self collision etc.
++
++ \param[in] flags The flags to set
++ */
++ virtual void setParticleFlags(PxParticleFlags flags) = 0;
++
++ /**
++ \brief Retrieves the particle flags.
++
++ \return The particle flags
++ */
++ virtual PxParticleFlags getParticleFlags() const = 0;
++
++ /**
++ \brief Set the maximal depenetration velocity particles can reach
++
++ Allows to limit the particles' maximal depenetration velocity to avoid that collision responses lead to very high particle velocities
++
++ <b>Default:</b> 1.0e32
++
++ \param[in] maxDepenetrationVelocity The maximal depenetration velocity
++ */
++ virtual void setMaxDepenetrationVelocity(PxReal maxDepenetrationVelocity) = 0;
++
++ /**
++ \brief Retrieves maximal depenetration velocity a particle can have.
++
++ \return The maximal depenetration velocity
++ */
++ virtual PxReal getMaxDepenetrationVelocity() const = 0;
++
++ /**
++ \brief Set the maximal linear velocity particles can reach.
++
++ Allows to limit the particles' maximal velocity to control the maximal distance a particle can move per frame.
++
++ <b>Default:</b> PX_MAX_F32
++
++ \param[in] maxLinearVelocity The maximal linear velocity
++ */
++ virtual void setMaxLinearVelocity(PxReal maxLinearVelocity) = 0;
++
++ /**
++ \brief Retrieves maximal linear velocity a particle can have.
++
++ \return The maximal linear velocity
++ */
++ virtual PxReal getMaxLinearVelocity() const = 0;
++
++ /**
++ \deprecated Use setMaxLinearVelocity() instead.
++ */
++ PX_DEPRECATED PX_FORCE_INLINE void setMaxVelocity(PxReal maxVelocity) { setMaxLinearVelocity(maxVelocity); }
++
++ /**
++ \deprecated Use getMaxLinearVelocity() instead.
++ */
++ PX_DEPRECATED PX_FORCE_INLINE PxReal getMaxVelocity() const { return getMaxLinearVelocity(); }
++
++
++ /**
++ \brief Return the cuda context manager
++
++ \return The cuda context manager
++ */
++ virtual PxCudaContextManager* getCudaContextManager() const = 0;
++
++ /**
++ \brief Set the rest offset for the collision between particles and rigids or deformable bodies.
++
++ A particle and a rigid or deformable body will come to rest at a distance equal to the sum of their restOffset values.
++
++ \param[in] restOffset <b>Range:</b> (0, contactOffset)
++ */
++ virtual void setRestOffset(PxReal restOffset) = 0;
++
++ /**
++ \brief Return the rest offset
++ \return the rest offset
++
++ See #setRestOffset()
++ */
++ virtual PxReal getRestOffset() const = 0;
++
++ /**
++ \brief Set the contact offset for the collision between particles and rigids or soft bodies
++
++ The contact offset needs to be larger than the rest offset.
++ Contact constraints are generated for a particle and a rigid or deformable below the distance equal to the sum of their contacOffset values.
++
++ \param[in] contactOffset <b>Range:</b> (restOffset, PX_MAX_F32)
++ */
++ virtual void setContactOffset(PxReal contactOffset) = 0;
++
++ /**
++ \brief Return the contact offset
++ \return the contact offset
++
++ See #setContactOffset()
++ */
++ virtual PxReal getContactOffset() const = 0;
++
++ /**
++ \brief Set the contact offset for the interactions between particles
++
++ The particle contact offset needs to be larger than the fluid rest offset and larger than the solid rest offset.
++ Interactions for two particles are computed if their distance is below twice the particleContactOffset value.
++
++ \param[in] particleContactOffset <b>Range:</b> (Max(solidRestOffset, fluidRestOffset), PX_MAX_F32)
++ */
++ virtual void setParticleContactOffset(PxReal particleContactOffset) = 0;
++
++ /**
++ \brief Return the particle contact offset
++ \return the particle contact offset
++
++ See #setParticleContactOffset()
++ */
++ virtual PxReal getParticleContactOffset() const = 0;
++
++ /**
++ \brief Set the solid rest offset
++
++ Two solid particles (or a solid and a fluid particle) will come to rest at a distance equal to twice the solidRestOffset value.
++
++ \param[in] solidRestOffset <b>Range:</b> (0, particleContactOffset)
++ */
++ virtual void setSolidRestOffset(PxReal solidRestOffset) = 0;
++
++ /**
++ \brief Return the solid rest offset
++ \return the solid rest offset
++
++ See #setSolidRestOffset()
++ */
++ virtual PxReal getSolidRestOffset() const = 0;
++
++
++ /**
++ \brief Reads the particle lock flags.
++
++ See the list of flags #PxParticleLockFlag
++
++ \return The values of the particle lock flags.
++
++ \see PxParticleLockFlag setParticleLockFlag()
++ */
++ virtual PxParticleLockFlags getParticleLockFlags() const = 0;
++
++ /**
++ \brief Raises or clears a particular particle lock flag.
++
++ See the list of flags #PxParticleLockFlag
++
++ <b>Default:</b> no flags are set
++
++
++ \param[in] flag The PxParticleLockFlag to raise(set) or clear.
++ \param[in] value The new boolean value for the flag.
++
++ \see PxParticleLockFlag getParticleLockFlags()
++ */
++ virtual void setParticleLockFlag(PxParticleLockFlag::Enum flag, bool value) = 0;
++
++ /**
++ \brief Set all particle lock flags.
++ \see setParticleLockFlag()
++ */
++ virtual void setParticleLockFlags(PxParticleLockFlags flags) = 0;
++
++
++ /**
++ \brief Creates combined particle flag with particle material and particle phase flags.
++
++ \param[in] material A material instance to associate with the new particle group.
++ \param[in] flags The particle phase flags.
++ \return The combined particle group index and phase flags.
++
++ See #PxParticlePhaseFlag
++ */
++ virtual PxU32 createPhase(PxPBDMaterial* material, PxParticlePhaseFlags flags) = 0;
++
++
++ /**
++ \brief Returns number of particle materials referenced by particle phases
++ \return The number of particle materials
++ */
++ virtual PxU32 getNbParticleMaterials() const = 0;
++
++ /**
++ \brief Returns particle materials referenced by particle phases
++ \return The particle materials
++ */
++ virtual PxU32 getParticleMaterials(PxPBDMaterial** userBuffer, PxU32 bufferSize, PxU32 startIndex = 0) const = 0;
++
++ /**
++ \brief Sets a user notify object which receives special simulation events when they occur.
++
++ \note Do not set the callback while the simulation is running. Calls to this method while the simulation is running will be ignored.
++ \note A call to fetchResultsParticleSystem() on the PxScene will synchronize the work such that the caller knows that all worke done in the callback completed.
++
++ \param[in] callback User notification callback. See PxSimulationEventCallback.
++
++ See #PxParticleSystemCallback, #getParticleSystemCallback()
++ */
++ virtual void setParticleSystemCallback(PxParticleSystemCallback* callback) = 0;
++
++ /**
++ \brief Retrieves the simulationEventCallback pointer set with setSimulationEventCallback().
++ \return The current user notify pointer. See PxSimulationEventCallback.
++
++ See #PxParticleSystemCallback, #setParticleSystemCallback()
++ */
++ virtual PxParticleSystemCallback* getParticleSystemCallback() const = 0;
++
++ /**
++ \brief Add an existing particle buffer to the particle system.
++ \param[in] particleBuffer a PxParticleBuffer*.
++
++ See #PxParticleBuffer.
++ */
++ virtual void addParticleBuffer(PxParticleBuffer* particleBuffer) = 0;
++
++ /**
++ \brief Remove particle buffer from the particle system.
++ \param[in] particleBuffer a PxParticleBuffer*.
++
++ See #PxParticleBuffer.
++ */
++ virtual void removeParticleBuffer(PxParticleBuffer* particleBuffer) = 0;
++
++ /**
++ \brief Returns the GPU particle system index.
++ \return The GPU index, if the particle system is in a scene and PxSceneFlag::eENABLE_DIRECT_GPU_API is set, or 0xFFFFFFFF otherwise.
++ */
++ virtual PxU32 getGpuParticleSystemIndex() = 0;
++
++ /**
++ \brief Set wind direction and intensity
++
++ \param[in] wind The wind direction and intensity
++ */
++ virtual void setWind(const PxVec3& wind) = 0;
++
++ /**
++ \brief Retrieves the wind direction and intensity.
++
++ \return The wind direction and intensity
++ */
++ virtual PxVec3 getWind() const = 0;
++
++ /**
++ \brief Set the fluid boundary density scale
++
++ Defines how strong of a contribution the boundary (typically a rigid surface) should have on a fluid particle's density.
++
++ \param[in] fluidBoundaryDensityScale <b>Range:</b> (0.0, 1.0)
++ */
++ virtual void setFluidBoundaryDensityScale(PxReal fluidBoundaryDensityScale) = 0;
++
++ /**
++ \brief Return the fluid boundary density scale
++ \return the fluid boundary density scale
++
++ See #setFluidBoundaryDensityScale()
++ */
++ virtual PxReal getFluidBoundaryDensityScale() const = 0;
++
++ /**
++ \brief Set the fluid rest offset
++
++ Two fluid particles will come to rest at a distance equal to twice the fluidRestOffset value.
++
++ \param[in] fluidRestOffset <b>Range:</b> (0, particleContactOffset)
++ */
++ virtual void setFluidRestOffset(PxReal fluidRestOffset) = 0;
++
++ /**
++ \brief Return the fluid rest offset
++ \return the fluid rest offset
++
++ See #setFluidRestOffset()
++ */
++ virtual PxReal getFluidRestOffset() const = 0;
++
++ /**
++ \brief Set the particle system grid size x dimension
++
++ \param[in] gridSizeX x dimension in the particle grid
++ */
++ virtual void setGridSizeX(PxU32 gridSizeX) = 0;
++
++ /**
++ \brief Get the particle system grid size x dimension
++ \return[in] the x dimension in the particle grid
++
++ See #setGridSizeX()
++ */
++ virtual PxU32 getGridSizeX() const = 0;
++
++ /**
++ \brief Set the particle system grid size y dimension
++
++ \param[in] gridSizeY y dimension in the particle grid
++ */
++ virtual void setGridSizeY(PxU32 gridSizeY) = 0;
++
++ /**
++ \brief Get the particle system grid size y dimension
++ \return[in] the y dimension in the particle grid
++
++ See #setGridSizeY()
++ */
++ virtual PxU32 getGridSizeY() const = 0;
++
++ /**
++ \brief Set the particle system grid size z dimension
++
++ \param[in] gridSizeZ z dimension in the particle grid
++ */
++ virtual void setGridSizeZ(PxU32 gridSizeZ) = 0;
++
++ /**
++ \brief Get the particle system grid size z dimension
++ \return[in] the z dimension in the particle grid
++
++ See #setGridSizeZ()
++ */
++ virtual PxU32 getGridSizeZ() const = 0;
++
++
++ virtual const char* getConcreteTypeName() const PX_OVERRIDE PX_FINAL { return "PxPBDParticleSystem"; }
++
++ protected:
++ PX_INLINE PxPBDParticleSystem(PxType concreteType, PxBaseFlags baseFlags) : PxActor(concreteType, baseFlags) {}
++ PX_INLINE PxPBDParticleSystem(PxBaseFlags baseFlags) : PxActor(baseFlags) {}
++ virtual bool isKindOf(const char* name) const PX_OVERRIDE { PX_IS_KIND_OF(name, "PxPBDParticleSystem", PxActor); }
++ };
++
++ #if PX_VC
++ #pragma warning(pop)
++ #endif
++
++
++ #if !PX_DOXYGEN
++ } // namespace physx
++ #endif
++
++ #endif