include/PxSceneDesc.h

File members: include/PxSceneDesc.h

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//  * Neither the name of NVIDIA CORPORATION nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2024 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.

#ifndef PX_SCENE_DESC_H
#define PX_SCENE_DESC_H

#include "PxSceneQueryDesc.h"
#include "PxPhysXConfig.h"
#include "foundation/PxFlags.h"
#include "foundation/PxBounds3.h"
#include "foundation/PxBitUtils.h"
#include "PxFiltering.h"
#include "PxBroadPhase.h"
#include "common/PxTolerancesScale.h"
#include "task/PxTask.h"

#if !PX_DOXYGEN
namespace physx
{
#endif

    class PxBroadPhaseCallback;
    class PxCudaContextManager;

struct PxFrictionType
{
    enum Enum
    {
        ePATCH,
        eONE_DIRECTIONAL PX_DEPRECATED,
        eTWO_DIRECTIONAL PX_DEPRECATED,
        eFRICTION_COUNT
    };
};

struct PxSolverType
{
    enum Enum
    {
        ePGS,
        eTGS
    };
};

struct PxSceneFlag
{
    enum Enum
    {
        eENABLE_ACTIVE_ACTORS   = (1<<0),

        eENABLE_CCD = (1<<1),

        eDISABLE_CCD_RESWEEP    = (1<<2),

        eENABLE_PCM = (1 << 6),

        eDISABLE_CONTACT_REPORT_BUFFER_RESIZE   = (1 << 7),

        eDISABLE_CONTACT_CACHE  = (1 << 8),

        eREQUIRE_RW_LOCK = (1 << 9),

        eENABLE_STABILIZATION = (1 << 10),

        eENABLE_AVERAGE_POINT = (1 << 11),

        eEXCLUDE_KINEMATICS_FROM_ACTIVE_ACTORS = (1 << 12),

        /*\brief Enables the GPU dynamics pipeline

        When set to true, a CUDA ARCH 3.0 or above-enabled NVIDIA GPU is present and the CUDA context manager has been configured, this will run the GPU dynamics pipelin instead of the CPU dynamics pipeline.

        Note that this flag is not mutable and must be set in PxSceneDesc at scene creation.
        */
        eENABLE_GPU_DYNAMICS = (1 << 13),

        eENABLE_ENHANCED_DETERMINISM = (1<<14),

        eENABLE_FRICTION_EVERY_ITERATION = (1 << 15),

        eENABLE_EXTERNAL_FORCES_EVERY_ITERATION_TGS = (1 << 16),

        /*
        \brief Enables the direct-GPU API. Raising this flag is only allowed if eENABLE_GPU_DYNAMICS is raised and
        PxBroadphaseType::eGPU is used.

        This is useful if your application only needs to communicate to the GPU via GPU buffers. Can be significantly
        faster.

        \note Enabling the direct-GPU API will disable the readback of simulation state from GPU to CPU. Simulation outputs
        can only be accessed using the direct-GPU API functions in PxScene (PxScene::copyBodyData(), PxScene::copyArticulationData(),
        PxScene::copySoftbodyData(), PxScene::copyContactData()), and reading state directly from the actor is not allowed.

        \note This flag is not mutable and must be set in PxSceneDesc at scene creation.
        \see PxScene::getDirectGPUAPI() PxDirectGPUAPI

        <b>Default</b> false
        */
        eENABLE_DIRECT_GPU_API = (1 << 17),

        eENABLE_BODY_ACCELERATIONS = (1 << 18),

        /*
        \brief Enables the solver residual reporting.

        \note Enabling this flag can have a negative impact on the performance but the impact should be small.
        */
        eENABLE_SOLVER_RESIDUAL_REPORTING = (1 << 19),

        eMUTABLE_FLAGS = eENABLE_ACTIVE_ACTORS|eEXCLUDE_KINEMATICS_FROM_ACTIVE_ACTORS
    };
};

typedef PxFlags<PxSceneFlag::Enum,PxU32> PxSceneFlags;
PX_FLAGS_OPERATORS(PxSceneFlag::Enum,PxU32)

class PxSimulationEventCallback;
class PxContactModifyCallback;
class PxCCDContactModifyCallback;
class PxSimulationFilterCallback;

class PxSceneLimits
{
public:
    PxU32       maxNbActors;
    PxU32       maxNbBodies;
    PxU32       maxNbStaticShapes;
    PxU32       maxNbDynamicShapes;
    PxU32       maxNbAggregates;
    PxU32       maxNbConstraints;
    PxU32       maxNbRegions;
    PxU32       maxNbBroadPhaseOverlaps;

    PX_INLINE PxSceneLimits();

    PX_INLINE void setToDefault();

    PX_INLINE bool isValid() const;
};

PX_INLINE PxSceneLimits::PxSceneLimits() :  //constructor sets to default
    maxNbActors             (0),
    maxNbBodies             (0),
    maxNbStaticShapes       (0),
    maxNbDynamicShapes      (0),
    maxNbAggregates         (0),
    maxNbConstraints        (0),
    maxNbRegions            (0),
    maxNbBroadPhaseOverlaps (0)
{
}

PX_INLINE void PxSceneLimits::setToDefault()
{
    *this = PxSceneLimits();
}

PX_INLINE bool PxSceneLimits::isValid() const
{
    if(maxNbRegions>256)    // max number of regions is currently limited
        return false;

    return true;
}

//#if PX_SUPPORT_GPU_PHYSX
struct PxGpuDynamicsMemoryConfig
{
    PxU64 tempBufferCapacity;
    PxU32 maxRigidContactCount;
    PxU32 maxRigidPatchCount;
    PxU32 heapCapacity;
    PxU32 foundLostPairsCapacity;
    PxU32 foundLostAggregatePairsCapacity;
    PxU32 totalAggregatePairsCapacity;
    PxU32 maxSoftBodyContacts;
    PxU32 maxFemClothContacts;
    PxU32 maxParticleContacts;
    PxU32 collisionStackSize;
    PxU32 maxHairContacts;

    PxGpuDynamicsMemoryConfig() :
        tempBufferCapacity(16 * 1024 * 1024),
        maxRigidContactCount(1024 * 512),
        maxRigidPatchCount(1024 * 80),
        heapCapacity(64 * 1024 * 1024),
        foundLostPairsCapacity(256 * 1024),
        foundLostAggregatePairsCapacity(1024),
        totalAggregatePairsCapacity(1024),
        maxSoftBodyContacts(1 * 1024 * 1024),
        maxFemClothContacts(1 * 1024 * 1024),
        maxParticleContacts(1*1024*1024),
        collisionStackSize(64*1024*1024),
        maxHairContacts(1 * 1024 * 1024)
    {
    }

    PX_PHYSX_CORE_API bool isValid() const;
};

PX_INLINE bool PxGpuDynamicsMemoryConfig::isValid() const
{
    const bool isPowerOfTwo = PxIsPowerOfTwo(heapCapacity);
    return isPowerOfTwo;
}

//#endif

class PxSceneDesc : public PxSceneQueryDesc
{
public:

    PxVec3  gravity;

    PxSimulationEventCallback*  simulationEventCallback;

    PxContactModifyCallback*    contactModifyCallback;

    PxCCDContactModifyCallback* ccdContactModifyCallback;

    const void* filterShaderData;

    PxU32   filterShaderDataSize;

    PxSimulationFilterShader    filterShader;

    PxSimulationFilterCallback* filterCallback;

    PxPairFilteringMode::Enum   kineKineFilteringMode;

    PxPairFilteringMode::Enum   staticKineFilteringMode;

    PxBroadPhaseType::Enum  broadPhaseType;

    PxBroadPhaseCallback*   broadPhaseCallback;

    PxSceneLimits   limits;

    PxFrictionType::Enum frictionType;

    PxSolverType::Enum  solverType;

    PxReal bounceThresholdVelocity;

    PxReal frictionOffsetThreshold;

    PxReal frictionCorrelationDistance;

    PxSceneFlags    flags;

    PxCpuDispatcher*    cpuDispatcher;

    PxCudaContextManager*   cudaContextManager;

    void*   userData;

    PxU32   solverBatchSize;

    PxU32   solverArticulationBatchSize;

    PxU32   nbContactDataBlocks;

    PxU32   maxNbContactDataBlocks;

    PxReal  maxBiasCoefficient;

    PxU32   contactReportStreamBufferSize;

    PxU32   ccdMaxPasses;

    PxReal  ccdThreshold;

    PxReal  ccdMaxSeparation;

    PxReal  wakeCounterResetValue;

    PxBounds3   sanityBounds;

    PxGpuDynamicsMemoryConfig gpuDynamicsConfig;

    PxU32   gpuMaxNumPartitions;

    PxU32   gpuMaxNumStaticPartitions;

    PxU32   gpuComputeVersion;

    PxU32   contactPairSlabSize;

    PxSceneQuerySystem* sceneQuerySystem;

private:
    // For internal use only
    PxTolerancesScale   tolerancesScale;
public:
    PX_INLINE PxSceneDesc(const PxTolerancesScale& scale);

    PX_INLINE void setToDefault(const PxTolerancesScale& scale);

    PX_INLINE bool isValid() const;

    // For internal use only
    PX_INLINE const PxTolerancesScale& getTolerancesScale() const { return tolerancesScale; }
};

PX_INLINE PxSceneDesc::PxSceneDesc(const PxTolerancesScale& scale):
    gravity                         (PxVec3(0.0f)),
    simulationEventCallback         (NULL),
    contactModifyCallback           (NULL),
    ccdContactModifyCallback        (NULL),

    filterShaderData                (NULL),
    filterShaderDataSize            (0),
    filterShader                    (NULL),
    filterCallback                  (NULL),

    kineKineFilteringMode           (PxPairFilteringMode::eDEFAULT),
    staticKineFilteringMode         (PxPairFilteringMode::eDEFAULT),

    broadPhaseType                  (PxBroadPhaseType::ePABP),
    broadPhaseCallback              (NULL),

    frictionType                    (PxFrictionType::ePATCH),
    solverType                      (PxSolverType::ePGS),
    bounceThresholdVelocity         (0.2f * scale.speed),
    frictionOffsetThreshold         (0.04f * scale.length),
    frictionCorrelationDistance     (0.025f * scale.length),

    flags                           (PxSceneFlag::eENABLE_PCM),

    cpuDispatcher                   (NULL),
    cudaContextManager              (NULL),

    userData                        (NULL),

    solverBatchSize                 (128),
    solverArticulationBatchSize     (16),

    nbContactDataBlocks             (0),
    maxNbContactDataBlocks          (1<<16),
    maxBiasCoefficient              (PX_MAX_F32),
    contactReportStreamBufferSize   (8192),
    ccdMaxPasses                    (1),
    ccdThreshold                    (PX_MAX_F32),
    ccdMaxSeparation                (0.04f * scale.length),
    wakeCounterResetValue           (20.0f*0.02f),
    sanityBounds                    (PxBounds3(PxVec3(-PX_MAX_BOUNDS_EXTENTS), PxVec3(PX_MAX_BOUNDS_EXTENTS))),
    gpuMaxNumPartitions             (8),
    gpuMaxNumStaticPartitions       (16),
    gpuComputeVersion               (0),
    contactPairSlabSize             (256),
    sceneQuerySystem                (NULL),
    tolerancesScale                 (scale)
{
}

PX_INLINE void PxSceneDesc::setToDefault(const PxTolerancesScale& scale)
{
    *this = PxSceneDesc(scale);
}

PX_INLINE bool PxSceneDesc::isValid() const
{
    if(!PxSceneQueryDesc::isValid())
        return false;

    if(!filterShader)
        return false;

    if( ((filterShaderDataSize == 0) && (filterShaderData != NULL)) ||
        ((filterShaderDataSize > 0) && (filterShaderData == NULL)) )
        return false;

    if(!limits.isValid())
        return false;

    if(bounceThresholdVelocity <= 0.0f)
        return false;
    if(frictionOffsetThreshold < 0.0f)
        return false;
    if(frictionCorrelationDistance <= 0)
        return false;

    if(maxBiasCoefficient < 0.0f)
        return false;

    if(!ccdMaxPasses)
        return false;
    if(ccdThreshold <= 0.0f)
        return false;
    if(ccdMaxSeparation < 0.0f)
        return false;

    if(!cpuDispatcher)
        return false;

    if(!contactReportStreamBufferSize)
        return false;

    if(maxNbContactDataBlocks < nbContactDataBlocks)
        return false;

    if(wakeCounterResetValue <= 0.0f)
        return false;

    if(!sanityBounds.isValid())
        return false;

    if(solverType == PxSolverType::ePGS && (flags & PxSceneFlag::eENABLE_EXTERNAL_FORCES_EVERY_ITERATION_TGS))
        return false;

#if PX_SUPPORT_GPU_PHYSX
    if(!PxIsPowerOfTwo(gpuMaxNumPartitions))
        return false;
    if(gpuMaxNumPartitions > 32)
        return false;
    if (gpuMaxNumPartitions == 0)
        return false;
    if(!gpuDynamicsConfig.isValid())
        return false;

    if (flags & PxSceneFlag::eENABLE_DIRECT_GPU_API)
    {
        if(!(flags & PxSceneFlag::eENABLE_GPU_DYNAMICS && broadPhaseType == PxBroadPhaseType::eGPU))
            return false;
    }
#endif

    if(contactPairSlabSize == 0)
        return false;

    return true;
}

#if !PX_DOXYGEN
} // namespace physx
#endif

#endif