include/characterkinematic/PxController.h

File members: include/characterkinematic/PxController.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_CONTROLLER_H
#define PX_CONTROLLER_H

#include "characterkinematic/PxExtended.h"
#include "characterkinematic/PxControllerObstacles.h"
#include "PxQueryFiltering.h"
#include "foundation/PxErrorCallback.h"

#if !PX_DOXYGEN
namespace physx
{
#endif

struct PxControllerShapeType
{
    enum Enum
    {
        eBOX,

        eCAPSULE,

        eFORCE_DWORD = 0x7fffffff
    };
};

class PxShape;
class PxScene;
class PxController;
class PxRigidDynamic;
class PxMaterial;
struct PxFilterData;
class PxQueryFilterCallback;
class PxControllerBehaviorCallback;
class PxObstacleContext;
class PxObstacle;

struct PxControllerNonWalkableMode
{
    enum Enum
    {
        ePREVENT_CLIMBING,
        ePREVENT_CLIMBING_AND_FORCE_SLIDING
    };
};

struct PxControllerCollisionFlag
{
    enum Enum
    {
        eCOLLISION_SIDES    = (1<<0),
        eCOLLISION_UP       = (1<<1),
        eCOLLISION_DOWN     = (1<<2)
    };
};

typedef PxFlags<PxControllerCollisionFlag::Enum, PxU8> PxControllerCollisionFlags;
PX_FLAGS_OPERATORS(PxControllerCollisionFlag::Enum, PxU8)

struct PxControllerState
{
    PxVec3              deltaXP;
    PxShape*            touchedShape;
    PxRigidActor*       touchedActor;
    PxObstacleHandle    touchedObstacleHandle;  // Obstacle on which the CCT is standing
    PxU32               collisionFlags;
    bool                standOnAnotherCCT;
    bool                standOnObstacle;
    bool                isMovingUp;
};

struct PxControllerStats
{
    PxU16           nbIterations;
    PxU16           nbFullUpdates;
    PxU16           nbPartialUpdates;
    PxU16           nbTessellation;
};

struct PxControllerHit
{
    PxController*   controller;
    PxExtendedVec3  worldPos;
    PxVec3          worldNormal;
    PxVec3          dir;
    PxF32           length;
};

struct PxControllerShapeHit : public PxControllerHit
{
    PxShape*        shape;
    PxRigidActor*   actor;
    PxU32           triangleIndex;
};

struct PxControllersHit : public PxControllerHit
{
    PxController*   other;
};

struct PxControllerObstacleHit : public PxControllerHit
{
    const void*     userData;
};

class PxUserControllerHitReport
{
public:

    virtual void onShapeHit(const PxControllerShapeHit& hit) = 0;

    virtual void onControllerHit(const PxControllersHit& hit) = 0;

    virtual void onObstacleHit(const PxControllerObstacleHit& hit) = 0;

protected:
    virtual ~PxUserControllerHitReport(){}
};

class PxControllerFilterCallback
{
public:
    virtual ~PxControllerFilterCallback(){}

    virtual bool filter(const PxController& a, const PxController& b) = 0;
};

class PxControllerFilters
{
    public:

    PX_INLINE                   PxControllerFilters(const PxFilterData* filterData=NULL, PxQueryFilterCallback* cb=NULL, PxControllerFilterCallback* cctFilterCb=NULL) :
                                    mFilterData         (filterData),
                                    mFilterCallback     (cb),
                                    mFilterFlags        (PxQueryFlag::eSTATIC|PxQueryFlag::eDYNAMIC|PxQueryFlag::ePREFILTER),
                                    mCCTFilterCallback  (cctFilterCb)
                                {}

    // CCT-vs-shapes:
    const PxFilterData*         mFilterData;
    PxQueryFilterCallback*      mFilterCallback;
    PxQueryFlags                mFilterFlags;
    // CCT-vs-CCT:
    PxControllerFilterCallback* mCCTFilterCallback;
};

class PxControllerDesc
{
public:

    PX_INLINE virtual   bool            isValid()       const;

    PX_INLINE   PxControllerShapeType::Enum     getType()       const   { return mType;     }

    PxExtendedVec3                      position;

    PxVec3                              upDirection;

    PxF32                               slopeLimit;

    PxF32                               invisibleWallHeight;

    PxF32                               maxJumpHeight;

    PxF32                               contactOffset;

    PxF32                               stepOffset;

    PxF32                               density;

    PxF32                               scaleCoeff;

    PxF32                               volumeGrowth;

    PxUserControllerHitReport*          reportCallback;

    PxControllerBehaviorCallback*       behaviorCallback;

    PxControllerNonWalkableMode::Enum   nonWalkableMode;

    PxMaterial*                         material;

    bool                                registerDeletionListener;

    PxClientID                          clientID;

    void*                               userData;

protected:
    const PxControllerShapeType::Enum   mType;

    PX_INLINE                           PxControllerDesc(PxControllerShapeType::Enum);
    PX_INLINE virtual                   ~PxControllerDesc();

    PX_INLINE                           PxControllerDesc(const PxControllerDesc&);

    PX_INLINE PxControllerDesc&         operator=(const PxControllerDesc&);

    PX_INLINE void                      copy(const PxControllerDesc&);
};

PX_INLINE PxControllerDesc::PxControllerDesc(PxControllerShapeType::Enum t) :
    position                    (PxExtended(0.0), PxExtended(0.0), PxExtended(0.0)),
    upDirection                 (0.0f, 1.0f, 0.0f),
    slopeLimit                  (0.707f),
    invisibleWallHeight         (0.0f),
    maxJumpHeight               (0.0f),
    contactOffset               (0.1f),
    stepOffset                  (0.5f),
    density                     (10.0f),
    scaleCoeff                  (0.8f),
    volumeGrowth                (1.5f),
    reportCallback              (NULL),
    behaviorCallback            (NULL),
    nonWalkableMode             (PxControllerNonWalkableMode::ePREVENT_CLIMBING),
    material                    (NULL),
    registerDeletionListener    (true),
    clientID                    (PX_DEFAULT_CLIENT),
    userData                    (NULL),
    mType                       (t)
{
}

PX_INLINE PxControllerDesc::PxControllerDesc(const PxControllerDesc& other) : mType(other.mType)
{
    copy(other);
}

PX_INLINE PxControllerDesc& PxControllerDesc::operator=(const PxControllerDesc& other)
{
    copy(other);
    return *this;
}

PX_INLINE void PxControllerDesc::copy(const PxControllerDesc& other)
{
    upDirection                 = other.upDirection;
    slopeLimit                  = other.slopeLimit;
    contactOffset               = other.contactOffset;
    stepOffset                  = other.stepOffset;
    density                     = other.density;
    scaleCoeff                  = other.scaleCoeff;
    volumeGrowth                = other.volumeGrowth;
    reportCallback              = other.reportCallback;
    behaviorCallback            = other.behaviorCallback;
    userData                    = other.userData;
    nonWalkableMode             = other.nonWalkableMode;
    position.x                  = other.position.x;
    position.y                  = other.position.y;
    position.z                  = other.position.z;
    material                    = other.material;
    invisibleWallHeight         = other.invisibleWallHeight;
    maxJumpHeight               = other.maxJumpHeight;
    registerDeletionListener    = other.registerDeletionListener;
    clientID                    = other.clientID;
}

PX_INLINE PxControllerDesc::~PxControllerDesc()
{
}

PX_INLINE bool PxControllerDesc::isValid() const
{
    if(     mType!=PxControllerShapeType::eBOX
        &&  mType!=PxControllerShapeType::eCAPSULE)
        return false;
    if(scaleCoeff<0.0f)
        return false;
    if(volumeGrowth<1.0f)
        return false;
    if(density<0.0f)
        return false;
    if(slopeLimit<0.0f)
        return false;
    if(stepOffset<0.0f)
        return false;
    if(contactOffset<=0.0f)
        return false;
    if(!material)
        return false;
    if(!toVec3(position).isFinite())
        return false;   //the float version needs to be finite otherwise actor creation will fail.

    return true;
}

class PxController
{
public:
    virtual     PxControllerShapeType::Enum getType()       const           = 0;

    virtual     void                    release() = 0;

    virtual     PxControllerCollisionFlags  move(const PxVec3& disp, PxF32 minDist, PxF32 elapsedTime, const PxControllerFilters& filters, const PxObstacleContext* obstacles=NULL) = 0;

    virtual     bool                    setPosition(const PxExtendedVec3& position) = 0;

    virtual     const PxExtendedVec3&   getPosition()           const   = 0;

    virtual     bool                    setFootPosition(const PxExtendedVec3& position) = 0;

    virtual     PxExtendedVec3          getFootPosition()       const   = 0;

    virtual     PxRigidDynamic*         getActor()              const   = 0;

    virtual     void                    setStepOffset(const PxF32 offset) =0;

    virtual     PxF32                   getStepOffset()                     const       =0;

    virtual     void                        setNonWalkableMode(PxControllerNonWalkableMode::Enum flag)  = 0;

    virtual     PxControllerNonWalkableMode::Enum   getNonWalkableMode()                const       = 0;

    virtual     PxF32                   getContactOffset()                  const       =0;

    virtual     void                    setContactOffset(PxF32 offset)                  =0;

    virtual     PxVec3                  getUpDirection()                    const       =0;

    virtual     void                    setUpDirection(const PxVec3& up)                =0;

    virtual     PxF32                   getSlopeLimit()                     const       =0;

    virtual     void                    setSlopeLimit(PxF32 slopeLimit)                 =0;

    virtual     void                    invalidateCache()           = 0;

    virtual     PxScene*                getScene()                      = 0;

    virtual     void*                   getUserData()       const       = 0;

    virtual     void                    setUserData(void* userData)     = 0;

    virtual     void                    getState(PxControllerState& state)  const       = 0;

    virtual     void                    getStats(PxControllerStats& stats)  const       = 0;

    virtual     void                    resize(PxReal height)   = 0;

protected:
    PX_INLINE                           PxController()                  {}
    virtual                             ~PxController()                 {}
};

#if !PX_DOXYGEN
} // namespace physx
#endif

#endif