// 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-2013 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_PHYSICS_CCT_CONTROLLER
#define PX_PHYSICS_CCT_CONTROLLER
/** \addtogroup character
@{
*/
#include "characterkinematic/PxCharacter.h"
#include "characterkinematic/PxExtended.h"
#include "characterkinematic/PxControllerObstacles.h"
#include "PxSceneQueryFiltering.h"
#ifndef PX_DOXYGEN
namespace physx
{
#endif
/**
\brief The type of controller, eg box, sphere or capsule.
*/
struct PxControllerShapeType
{
enum Enum
{
/**
\brief A box controller.
@see PxBoxController PxBoxControllerDesc
*/
eBOX,
/**
\brief A capsule controller
@see PxCapsuleController PxCapsuleControllerDesc
*/
eCAPSULE,
eFORCE_DWORD = 0x7fffffff
};
};
class PxShape;
class PxScene;
class PxController;
class PxRigidDynamic;
class PxMaterial;
struct PxFilterData;
class PxSceneQueryFilterCallback;
class PxControllerBehaviorCallback;
class PxObstacleContext;
class PxObstacle;
/**
\brief specifies how a CCT interacts with other CCTs.
This member controls if a character controller will collide with another controller. There are 3 options:
always collide, never collide and collide based on the shape group.
This flag only affects other controllers when they move; when this controller moves, the flag is ignored
and the flags of the other controllers determine collision.
*/
struct PxCCTInteractionMode
{
enum Enum
{
eINCLUDE, //!< Always collide character controllers.
eEXCLUDE, //!< Never collide character controllers.
/**
\brief Collide based on a group bitmask stored in the controller.
The groups to collide against are passed in the activeGroups member of #PxController::move(). The active
groups flags work on top of the Physics SDK filtering logic of the controllers kinematic actor to determine if a
collision should occur:
activeGroups & controller->getGroupsBitmask()
@see PxController.move() PxController.getGroupsBitmask() PxController.setGroupsBitmask()
*/
eUSE_FILTER,
};
};
/**
\brief specifies how a CCT interacts with non-walkable parts.
This is only used when slopeLimit is non zero.
*/
struct PxCCTNonWalkableMode
{
enum Enum
{
ePREVENT_CLIMBING, //!< Stops character from climbing up a slope, but doesn't move it otherwise
eFORCE_SLIDING, //!< Forces character to slide down non-walkable slopes
};
};
/**
\brief specifies which sides a character is colliding with.
*/
struct PxControllerFlag
{
enum Enum
{
eCOLLISION_SIDES = (1<<0), //!< Character is colliding to the sides.
eCOLLISION_UP = (1<<1), //!< Character has collision above.
eCOLLISION_DOWN = (1<<2), //!< Character has collision below.
};
};
/**
\brief Describes a controller's internal state.
*/
struct PxControllerState
{
PxVec3 deltaXP;
PxShape* touchedShape; // Shape on which the CCT is standing
ObstacleHandle touchedObstacleHandle; // Obstacle on which the CCT is standing
PxU32 collisionFlags; // Last known collision flags (PxControllerFlag)
bool standOnAnotherCCT; // Are we standing on another CCT?
bool standOnObstacle; // Are we standing on a user-defined obstacle?
bool isMovingUp; // is CCT moving up or not? (i.e. explicit jumping)
};
/**
\brief Describes a controller's internal statistics.
*/
struct PxControllerStats
{
PxU16 nbIterations;
PxU16 nbFullUpdates;
PxU16 nbPartialUpdates;
};
/**
\brief Describes a generic CCT hit.
*/
struct PxCCTHit
{
PxController* controller; //!< Current controller
PxExtendedVec3 worldPos; //!< Contact position in world space
PxVec3 worldNormal; //!< Contact normal in world space
PxVec3 dir; //!< Motion direction
PxF32 length; //!< Motion length
};
/**
\brief Describes a hit between a CCT and a shape. Passed to onShapeHit()
@see PxUserControllerHitReport.onShapeHit()
*/
struct PxControllerShapeHit : PxCCTHit
{
PxShape* shape; //!< Touched shape
PxU32 triangleIndex; //!< touched triangle index (only for meshes/heightfields)
};
/**
\brief Describes a hit between a CCT and another CCT. Passed to onControllerHit().
@see PxUserControllerHitReport.onControllerHit()
*/
struct PxControllersHit : PxCCTHit
{
PxController* other; //!< Touched controller
};
/**
\brief Describes a hit between a CCT and a user-defined obstacle. Passed to onObstacleHit().
@see PxUserControllerHitReport.onObstacleHit() PxObstacleContext
*/
struct PxControllerObstacleHit : PxCCTHit
{
const void* userData;
};
/**
\brief User callback class for character controller events.
\note Character controller hit reports are only generated when move is called.
@see PxControllerDesc.callback
*/
class PxUserControllerHitReport
{
public:
/**
\brief Called when current controller hits a shape.
\param[in] hit Provides information about the hit.
@see PxControllerShapeHit
*/
virtual void onShapeHit(const PxControllerShapeHit& hit) = 0;
/**
\brief Called when current controller hits another controller.
\param[in] hit Provides information about the hit.
@see PxControllersHit
*/
virtual void onControllerHit(const PxControllersHit& hit) = 0;
/**
\brief Called when current controller hits a user-defined obstacle.
\param[in] hit Provides information about the hit.
@see PxControllerObstacleHit PxObstacleContext
*/
virtual void onObstacleHit(const PxControllerObstacleHit& hit) = 0;
protected:
virtual ~PxUserControllerHitReport(){}
};
/**
\brief Dedicated filtering callback for CCT vs CCT.
This controls collisions between CCTs (one CCT vs anoter CCT). This additional callback is provided
in case the previously built-in filtering parameters are not flexible enough.
@see PxControllerFilters
*/
class PxControllerFilterCallback
{
public:
virtual ~PxControllerFilterCallback(){}
/**
\brief Filtering method for CCT-vs-CCT.
\param[in] a First CCT
\param[in] b Second CCT
\return true to keep the pair, false to filter it out
*/
virtual bool filter(const PxController& a, const PxController& b) = 0;
};
/**
\brief Filtering data for "move" call.
This controls both collisions between CCTs (one CCT vs anoter CCT) and collision between CCTs and the world.
Collisions between CCTs are mainly controlled by an 'active groups' bitmask, similar to what existed in
previous versions of the SDK. A group bitmask is stored in each controller. The groups to collide against
are passed in the activeGroups member of #PxController::move(). Collisions between the currently moved
CCT and another controller are enabled if:
activeGroups & controller->getGroupsBitmask() != 0
If collisions pass this test, the usual SDK filtering mechanism from the underlying kinematic shapes is then
used to refine the results.
Collision between CCTs and the PhysX world do not use the activeGroups, which are only defined for CCTs. The
only filtering mechanism used here is the one from the SDK, using the remaining PxControllerFilters data.
@see PxController.move() PxController.getGroupsBitmask() PxController.setGroupsBitmask() PxControllerFilterCallback
*/
class PxControllerFilters
{
public:
PX_INLINE PxControllerFilters(PxU32 groups=0xffffffff, const PxFilterData* filterData=NULL, PxSceneQueryFilterCallback* cb=NULL, PxControllerFilterCallback* cctFilterCb=NULL) :
mActiveGroups (groups),
mFilterData (filterData),
mFilterCallback (cb),
mFilterFlags (PxSceneQueryFilterFlag::eSTATIC|PxSceneQueryFilterFlag::eDYNAMIC|PxSceneQueryFilterFlag::ePREFILTER),
mCCTFilterCallback (cctFilterCb)
{}
PxU32 mActiveGroups; //!< a filtering mask for collision groups. If a bit is set, corresponding group is active.
const PxFilterData* mFilterData; //!< alternative filter data used to filter shapes
PxSceneQueryFilterCallback* mFilterCallback; //!< custom filter logic to filter out colliding objects.
PxSceneQueryFilterFlags mFilterFlags; //!< filter flags
PxControllerFilterCallback* mCCTFilterCallback;
};
/**
\brief Descriptor class for a character controller.
@see PxBoxController PxCapsuleController
*/
class PxControllerDesc
{
protected:
PxControllerShapeType::Enum type; //!< The type of the controller. This gets set by the derived class' ctor, the user should not have to change it.
/**
\brief constructor sets to default.
*/
PX_INLINE PxControllerDesc(PxControllerShapeType::Enum);
PX_INLINE virtual ~PxControllerDesc();
public:
/**
\brief returns true if the current settings are valid
\return True if the descriptor is valid.
*/
PX_INLINE virtual bool isValid() const;
/**
\brief Returns the character controller type
\return The controllers type.
@see PxControllerType PxCapsuleControllerDesc PxBoxControllerDesc
*/
PX_INLINE PxControllerShapeType::Enum getType() const { return type; }
/**
\brief The position of the character
\note The character's initial position must be such that it does not overlap the static geometry.
Default: Zero
*/
PxExtendedVec3 position;
/**
\brief Specifies the 'up' direction
In order to provide stepping functionality the SDK must be informed about the up direction.
Default: (0, 1, 0)
*/
PxVec3 upDirection;
/**
\brief The maximum slope which the character can walk up.
In general it is desirable to limit where the character can walk, in particular it is unrealistic
for the character to be able to climb arbitary slopes.
The limit is expressed as the cosine of desired limit angle. A value of 0 disables this feature.
Default: 0.707
@see upDirection invisibleWallHeight maxJumpHeight
*/
PxF32 slopeLimit;
/**
\brief Height of invisible walls created around non-walkable triangles
The library can automatically create invisible walls around non-walkable triangles defined
by the 'slopeLimit' parameter. This defines the height of those walls. If it is 0.0, then
no extra triangles are created.
Default: 0.0
@see upDirection slopeLimit maxJumpHeight
*/
PxF32 invisibleWallHeight;
/**
\brief Maximum height a jumping character can reach
This is only used if invisible walls are created ('invisibleWallHeight' is non zero).
When a character jumps, the non-walkable triangles he might fly over are not found
by the collision queries (since the character's bounding volume does not touch them).
Thus those non-walkable triangles do not create invisible walls, and it is possible
for a jumping character to land on a non-walkable triangle, while he wouldn't have
reached that place by just walking.
The 'maxJumpHeight' variable is used to extend the size of the collision volume
downward. This way, all the non-walkable triangles are properly found by the collision
queries and it becomes impossible to 'jump over' invisible walls.
If the character in your game can not jump, it is safe to use 0.0 here. Otherwise it
is best to keep this value as small as possible, since a larger collision volume
means more triangles to process.
Default: 0.0
@see upDirection slopeLimit invisibleWallHeight
*/
PxF32 maxJumpHeight;
/**
\brief The contact offset used by the controller.
Specifies a skin around the object within which contacts will be generated.
Use it to avoid numerical precision issues.
This is dependant on the scale of the users world, but should be a small, positive
non zero value.
Default: 0.1
*/
PxF32 contactOffset;
/**
\brief Defines the maximum height of an obstacle which the character can climb.
A small value will mean that the character gets stuck and cannot walk up stairs etc,
a value which is too large will mean that the character can climb over unrealistically
high obstacles.
Default: 0.5
@see upDirection
*/
PxF32 stepOffset;
/**
\brief Density of underlying kinematic actor
The CCT creates a PhysX's kinematic actor under the hood. This controls its density.
Default: 10.0
*/
PxF32 density;
/**
\brief Scale coeff for underlying kinematic actor
The CCT creates a PhysX's kinematic actor under the hood. This controls its scale factor.
This should be a number a bit smaller than 1.0.
Default: 0.8
*/
PxF32 scaleCoeff;
/**
\brief Cached volume growth
Amount of space around the controller we cache to improve performance. This is a scale factor
that should be higher than 1.0f but not too big, ideally lower than 2.0f.
Default: 1.5
*/
PxF32 volumeGrowth;
/**
\brief Specifies a user report callback.
This report callback is called when the character collides with shapes and other characters.
Setting this to NULL disables the callback.
Default: NULL
@see PxUserControllerHitReport
*/
PxUserControllerHitReport* callback;
/**
\brief Specifies a user behavior callback.
This behavior callback is called to customize the controller's behavior w.r.t. touched shapes.
Setting this to NULL disables the callback.
Default: NULL
@see PxControllerBehaviorCallback
*/
PxControllerBehaviorCallback* behaviorCallback;
/**
\brief The interaction mode controls if a character controller collides with other controllers.
The default is to collide controllers.
Default: PxCCTInteractionMode::eINCLUDE
@see PxCCTInteractionMode
*/
PxCCTInteractionMode::Enum interactionMode;
/**
\brief The non-walkable mode controls if a character controller slides or not on a non-walkable part.
This is only used when slopeLimit is non zero.
Default: PxCCTNonWalkableMode::ePREVENT_CLIMBING
@see PxCCTNonWalkableMode
*/
PxCCTNonWalkableMode::Enum nonWalkableMode;
/**
\brief The group bitmasks defines collision filtering when PxCCTInteractionMode::eUSE_FILTER is used.
Default: 0xffffffff
@see PxCCTInteractionMode
*/
PxU32 groupsBitmask;
/**
\brief The material for the actor associated with the controller.
The controller internally creates a rigid body actor. This parameter specifies the material of the actor.
Default: NULL
@see PxMaterial
*/
PxMaterial* material;
/**
\brief User specified data associated with the controller.
Default: NULL
*/
void* userData;
};
PX_INLINE PxControllerDesc::PxControllerDesc(PxControllerShapeType::Enum t) : type(t)
{
upDirection = PxVec3(0.0f, 1.0f, 0.0f);
slopeLimit = 0.707f;
contactOffset = 0.1f;
stepOffset = 0.5f;
density = 10.0f;
scaleCoeff = 0.8f;
volumeGrowth = 1.5f;
callback = NULL;
behaviorCallback = NULL;
userData = NULL;
interactionMode = PxCCTInteractionMode::eINCLUDE;
nonWalkableMode = PxCCTNonWalkableMode::ePREVENT_CLIMBING;
groupsBitmask = 0xffffffff;
position.x = PxExtended(0.0);
position.y = PxExtended(0.0);
position.z = PxExtended(0.0);
material = NULL;
invisibleWallHeight = 0.0f;
maxJumpHeight = 0.0f;
}
PX_INLINE PxControllerDesc::~PxControllerDesc()
{
}
PX_INLINE bool PxControllerDesc::isValid() const
{
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;
return true;
}
/**
\brief Base class for character controllers.
@see PxCapsuleController PxBoxController
*/
class PxController
{
protected:
PX_INLINE PxController() {}
virtual ~PxController() {}
public:
/**
\brief Return the type of controller
@see PxControllerType
*/
virtual PxControllerShapeType::Enum getType() const = 0;
/**
\brief Releases the controller.
*/
virtual void release() = 0;
/**
\brief Moves the character using a "collide-and-slide" algorithm.
\param[in] disp Displacement vector
\param[in] minDist The minimum travelled distance to consider. If travelled distance is smaller, the character doesn't move.
This is used to stop the recursive motion algorithm when remaining distance to travel is small.
\param[in] elapsedTime Time elapsed since last call
\param[in] filters User-defined filters for this move
\param[in] obstacles Potential additional obstacles the CCT should collide with.
\return Collision flags, collection of ::PxControllerFlag
*/
virtual PxU32 move(const PxVec3& disp, PxF32 minDist, PxF32 elapsedTime, const PxControllerFilters& filters, const PxObstacleContext* obstacles=NULL) = 0;
/**
\brief Sets controller's position.
The position controlled by this function is the center of the collision shape.
\warning This is a 'teleport' function, it doesn't check for collisions.
\warning The character's position must be such that it does not overlap the static geometry.
To move the character under normal conditions use the #move() function.
\param[in] position The new (center) positon for the controller.
\return Currently always returns true.
@see PxControllerDesc.position getPosition() getFootPosition() setFootPosition() move()
*/
virtual bool setPosition(const PxExtendedVec3& position) = 0;
/**
\brief Retrieve the raw position of the controller.
The position retrieved by this function is the center of the collision shape. To retrieve the bottom position of the shape,
a.k.a. the foot position, use the getFootPosition() function.
The position is updated by calls to move(). Calling this method without calling
move() will return the last position or the initial position of the controller.
\return The controller's center position
@see PxControllerDesc.position setPosition() getFootPosition() setFootPosition() move()
*/
virtual const PxExtendedVec3& getPosition() const = 0;
/**
\brief Set controller's foot position.
The position controlled by this function is the bottom of the collision shape, a.k.a. the foot position.
\note The foot position takes the contact offset into account
\warning This is a 'teleport' function, it doesn't check for collisions.
To move the character under normal conditions use the #move() function.
\param[in] position The new (bottom) positon for the controller.
\return Currently always returns true.
@see PxControllerDesc.position setPosition() getPosition() getFootPosition() move()
*/
virtual bool setFootPosition(const PxExtendedVec3& position) = 0;
/**
\brief Retrieve the "foot" position of the controller, i.e. the position of the bottom of the CCT's shape.
\note The foot position takes the contact offset into account
\return The controller's foot position
@see PxControllerDesc.position setPosition() getPosition() setFootPosition() move()
*/
virtual PxExtendedVec3 getFootPosition() const = 0;
/**
\brief Get the rigid body actor associated with this controller (see PhysX documentation).
The behavior upon manually altering this actor is undefined, you should primarily
use it for reading const properties.
\return the actor associated with the controller.
*/
virtual PxRigidDynamic* getActor() const = 0;
/**
\brief The step height.
\param[in] offset The new step offset for the controller.
@see PxControllerDesc.stepOffset
*/
virtual void setStepOffset(const PxF32 offset) =0;
/**
\brief Retrieve the step height.
\return The step offset for the controller.
@see setStepOffset()
*/
virtual PxF32 getStepOffset() const =0;
/**
\brief Sets the interaction mode for the CCT.
\param[in] flag The new value of the interaction mode.
\see PxCCTInteractionMode
*/
virtual void setInteraction(PxCCTInteractionMode::Enum flag) = 0;
/**
\brief Retrieves the interaction mode for the CCT.
\return The current interaction mode.
\see PxCCTInteractionMode
*/
virtual PxCCTInteractionMode::Enum getInteraction() const = 0;
/**
\brief Sets the non-walkable mode for the CCT.
\param[in] flag The new value of the non-walkable mode.
\see PxCCTNonWalkableMode
*/
virtual void setNonWalkableMode(PxCCTNonWalkableMode::Enum flag) = 0;
/**
\brief Retrieves the non-walkable mode for the CCT.
\return The current non-walkable mode.
\see PxCCTNonWalkableMode
*/
virtual PxCCTNonWalkableMode::Enum getNonWalkableMode() const = 0;
/**
\brief Sets the groups bitmask.
\param[in] bitmask The new groups bitmask value
\see PxCCTInteractionMode
*/
virtual void setGroupsBitmask(PxU32 bitmask) = 0;
/**
\brief Retrieves the groups bitmask
\return The current groups bitmask
\see PxCCTInteractionMode
*/
virtual PxU32 getGroupsBitmask() const = 0;
/**
\brief Retrieve the contact offset.
\return The contact offset for the controller.
@see PxControllerDesc.contactOffset
*/
virtual PxF32 getContactOffset() const =0;
/**
\brief Retrieve the 'up' direction.
\return The up direction for the controller.
@see PxControllerDesc.upDirection
*/
virtual PxVec3 getUpDirection() const =0;
/**
\brief Sets the 'up' direction.
\param[in] up The up direction for the controller.
@see PxControllerDesc.upDirection
*/
virtual void setUpDirection(const PxVec3& up) =0;
/**
\brief Retrieve the slope limit.
\return The slope limit for the controller.
@see PxControllerDesc.slopeLimit
*/
virtual PxF32 getSlopeLimit() const =0;
/**
\brief Flushes internal geometry cache.
The character controller uses caching in order to speed up collision testing. The cache is
automatically flushed when a change to static objects is detected in the scene. For example when a
static shape is added, updated, or removed from the scene, the cache is automatically invalidated.
However there may be situations that cannot be automatically detected, and those require manual
invalidation of the cache. Currently the user must call this when the filtering behavior changes (the
PxControllerFilters parameter of the PxController::move call). While the controller in principle
could detect a change in these parameters, it cannot detect a change in the behavior of the filtering
function.
@see PxController.move
*/
virtual void invalidateCache() = 0;
/**
\brief Retrieve the scene associated with the controller.
\return The physics scene
*/
virtual PxScene* getScene() = 0;
/**
\brief Returns the user data associated with this controller.
\return The user pointer associated with the controller.
@see PxControllerDesc.userData
*/
virtual void* getUserData() const = 0;
/**
\brief Returns information about the controller's internal state.
\param[out] state The controller's internal state
@see PxControllerState
*/
virtual void getState(PxControllerState& state) const = 0;
/**
\brief Returns the controller's internal statistics.
\param[out] stats The controller's internal statistics
@see PxControllerStats
*/
virtual void getStats(PxControllerStats& stats) const = 0;
/**
\brief Resizes the controller.
This function attempts to resize the controller to a given size, while making sure the bottom
position of the controller remains constant. In other words the function modifies both the
height and the (center) position of the controller. This is a helper function that can be used
to implement a 'crouch' functionality for example.
\param[in] height Desired controller's height
*/
virtual void resize(PxReal height) = 0;
};
#ifndef PX_DOXYGEN
} // namespace physx
#endif
/** @} */
#endif