feat(physics): wire physx sdk into build
This commit is contained in:
474
engine/third_party/physx/source/physxcharacterkinematic/src/CctCharacterController.h
vendored
Normal file
474
engine/third_party/physx/source/physxcharacterkinematic/src/CctCharacterController.h
vendored
Normal file
@@ -0,0 +1,474 @@
|
||||
// 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-2025 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 CCT_CHARACTER_CONTROLLER
|
||||
#define CCT_CHARACTER_CONTROLLER
|
||||
|
||||
//#define USE_CONTACT_NORMAL_FOR_SLOPE_TEST
|
||||
|
||||
#include "geometry/PxTriangle.h"
|
||||
#include "foundation/PxHashSet.h"
|
||||
#include "characterkinematic/PxController.h"
|
||||
#include "characterkinematic/PxControllerObstacles.h"
|
||||
#include "CctCharacterControllerManager.h"
|
||||
#include "CctUtils.h"
|
||||
#include "foundation/PxArray.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
struct PxFilterData;
|
||||
class PxQueryFilterCallback;
|
||||
class PxObstacle;
|
||||
class RenderBuffer;
|
||||
|
||||
namespace Cct
|
||||
{
|
||||
struct CCTParams
|
||||
{
|
||||
CCTParams();
|
||||
|
||||
PxControllerNonWalkableMode::Enum mNonWalkableMode;
|
||||
PxQuat mQuatFromUp;
|
||||
PxVec3 mUpDirection;
|
||||
PxF32 mSlopeLimit;
|
||||
PxF32 mContactOffset;
|
||||
PxF32 mStepOffset;
|
||||
PxF32 mInvisibleWallHeight;
|
||||
PxF32 mMaxJumpHeight;
|
||||
PxF32 mMaxEdgeLength2;
|
||||
bool mTessellation;
|
||||
bool mHandleSlope; // True to handle walkable parts according to slope
|
||||
bool mOverlapRecovery;
|
||||
bool mPreciseSweeps;
|
||||
bool mPreventVerticalSlidingAgainstCeiling;
|
||||
};
|
||||
|
||||
// typedef PxArray<PxTriangle> TriArray;
|
||||
typedef PxArray<PxU32> IntArray;
|
||||
|
||||
// PT: using private inheritance to control access, and make sure allocations are SIMD friendly
|
||||
class TriArray : private PxArray<PxTriangle>
|
||||
{
|
||||
public:
|
||||
|
||||
PX_FORCE_INLINE PxTriangle* reserve(PxU32 nbTris)
|
||||
{
|
||||
// PT: customized version of "reserveContainerMemory"
|
||||
|
||||
const PxU32 maxNbEntries = PxArray<PxTriangle>::capacity();
|
||||
const PxU32 realRequiredSize = PxArray<PxTriangle>::size() + nbTris;
|
||||
// PT: allocate one more tri to make sure we can safely V4Load the last one...
|
||||
const PxU32 requiredSize = realRequiredSize + 1;
|
||||
|
||||
if(requiredSize>maxNbEntries)
|
||||
{
|
||||
// PT: ok so the commented out growing policy was introduced by PX-837 but it produces
|
||||
// large memory usage regressions (see PX-881) while not actually making things run
|
||||
// faster. Our benchmarks show no performance difference, but up to +38% more memory
|
||||
// used with this "standard" growing policy. So for now we just go back to the initial
|
||||
// growing policy. It should be fine since PX-837 was not actually reported by a customer,
|
||||
// it was just a concern that appeared while looking at the code. Ideally we'd use a pool
|
||||
// with fixed-size slabs to get the best of both worlds but it would make iterating over
|
||||
// triangles more complicated and would need more refactoring. So for now we don't bother,
|
||||
// but we'll keep this note here for the next time this problem shows up.
|
||||
// PT: new August 2018: turns out PX-837 was correct. Not doing this produces very large
|
||||
// performance problems (like: the app freezes!) in SampleCCT. We didn't see it because
|
||||
// it's an internal sample that it rarely used these days...
|
||||
const PxU32 naturalGrowthSize = maxNbEntries ? maxNbEntries*2 : 2;
|
||||
const PxU32 newSize = PxMax(requiredSize, naturalGrowthSize);
|
||||
// const PxU32 newSize = requiredSize;
|
||||
|
||||
PxArray<PxTriangle>::reserve(newSize);
|
||||
}
|
||||
|
||||
PxTriangle* buf = PxArray<PxTriangle>::end();
|
||||
// ...but we still want the size to reflect the correct number
|
||||
PxArray<PxTriangle>::forceSize_Unsafe(realRequiredSize);
|
||||
return buf;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void pushBack(const PxTriangle& tri)
|
||||
{
|
||||
PxTriangle* memory = reserve(1);
|
||||
memory->verts[0] = tri.verts[0];
|
||||
memory->verts[1] = tri.verts[1];
|
||||
memory->verts[2] = tri.verts[2];
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU32 size() const
|
||||
{
|
||||
return PxArray<PxTriangle>::size();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxTriangle* begin() const
|
||||
{
|
||||
return PxArray<PxTriangle>::begin();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void clear()
|
||||
{
|
||||
PxArray<PxTriangle>::clear();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void forceSize_Unsafe(PxU32 size)
|
||||
{
|
||||
PxArray<PxTriangle>::forceSize_Unsafe(size);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxTriangle& getTriangle(PxU32 index) const
|
||||
{
|
||||
return (*this)[index];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/* Exclude from documentation */
|
||||
/** \cond */
|
||||
|
||||
struct TouchedGeomType
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eUSER_BOX,
|
||||
eUSER_CAPSULE,
|
||||
eMESH,
|
||||
eBOX,
|
||||
eSPHERE,
|
||||
eCAPSULE,
|
||||
eCUSTOM,
|
||||
|
||||
eLAST,
|
||||
|
||||
eFORCE_DWORD = 0x7fffffff
|
||||
};
|
||||
};
|
||||
|
||||
class SweptVolume;
|
||||
|
||||
struct TouchedGeom
|
||||
{
|
||||
TouchedGeomType::Enum mType;
|
||||
const void* mTGUserData; // PxController or PxShape pointer
|
||||
const PxRigidActor* mActor; // PxActor for PxShape pointers (mandatory with shared shapes)
|
||||
PxExtendedVec3 mOffset; // Local origin, typically the center of the world bounds around the character. We translate both
|
||||
// touched shapes & the character so that they are nearby this PxVec3, then add the offset back to
|
||||
// computed "world" impacts.
|
||||
protected:
|
||||
~TouchedGeom(){}
|
||||
};
|
||||
|
||||
struct TouchedUserBox : public TouchedGeom
|
||||
{
|
||||
PxExtendedBox mBox;
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(TouchedUserBox)==sizeof(TouchedGeom)+sizeof(PxExtendedBox));
|
||||
|
||||
struct TouchedUserCapsule : public TouchedGeom
|
||||
{
|
||||
PxExtendedCapsule mCapsule;
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(TouchedUserCapsule)==sizeof(TouchedGeom)+sizeof(PxExtendedCapsule));
|
||||
|
||||
struct TouchedMesh : public TouchedGeom
|
||||
{
|
||||
PxU32 mNbTris;
|
||||
PxU32 mIndexWorldTriangles;
|
||||
};
|
||||
|
||||
struct TouchedBox : public TouchedGeom
|
||||
{
|
||||
PxVec3 mCenter;
|
||||
PxVec3 mExtents;
|
||||
PxQuat mRot;
|
||||
};
|
||||
|
||||
struct TouchedSphere : public TouchedGeom
|
||||
{
|
||||
PxVec3 mCenter; //!< Sphere's center
|
||||
PxF32 mRadius; //!< Sphere's radius
|
||||
};
|
||||
|
||||
struct TouchedCustom : public TouchedGeom
|
||||
{
|
||||
PxVec3 mCenter; //!< Custom geometry's center
|
||||
PxCustomGeometry::Callbacks* mCustomCallbacks; //!< Custom geometry's callback object
|
||||
};
|
||||
|
||||
struct TouchedCapsule : public TouchedGeom
|
||||
{
|
||||
PxVec3 mP0; //!< Start of segment
|
||||
PxVec3 mP1; //!< End of segment
|
||||
PxF32 mRadius; //!< Capsule's radius
|
||||
};
|
||||
|
||||
struct SweptContact
|
||||
{
|
||||
PxExtendedVec3 mWorldPos; // Contact position in world space
|
||||
PxVec3 mWorldNormal; // Contact normal in world space
|
||||
PxF32 mDistance; // Contact distance
|
||||
PxU32 mInternalIndex; // Reserved for internal usage
|
||||
PxU32 mTriangleIndex; // Triangle index for meshes/heightfields
|
||||
TouchedGeom* mGeom;
|
||||
|
||||
PX_FORCE_INLINE void setWorldPos(const PxVec3& localImpact, const PxExtendedVec3& offset)
|
||||
{
|
||||
mWorldPos.x = PxExtended(localImpact.x) + offset.x;
|
||||
mWorldPos.y = PxExtended(localImpact.y) + offset.y;
|
||||
mWorldPos.z = PxExtended(localImpact.z) + offset.z;
|
||||
}
|
||||
};
|
||||
|
||||
// PT: user-defined obstacles. Note that "user" is from the SweepTest class' point of view,
|
||||
// i.e. the PhysX CCT module is the user in this case. This is to limit coupling between the
|
||||
// core CCT module and the PhysX classes.
|
||||
struct UserObstacles// : PxObstacleContext
|
||||
{
|
||||
PxU32 mNbBoxes;
|
||||
const PxExtendedBox* mBoxes;
|
||||
const void** mBoxUserData;
|
||||
|
||||
PxU32 mNbCapsules;
|
||||
const PxExtendedCapsule* mCapsules;
|
||||
const void** mCapsuleUserData;
|
||||
};
|
||||
|
||||
struct InternalCBData_OnHit{};
|
||||
struct InternalCBData_FindTouchedGeom{};
|
||||
|
||||
enum SweepTestFlag
|
||||
{
|
||||
STF_HIT_NON_WALKABLE = (1<<0),
|
||||
STF_WALK_EXPERIMENT = (1<<1),
|
||||
STF_VALIDATE_TRIANGLE_DOWN = (1<<2), // Validate touched triangle data (down pass)
|
||||
STF_VALIDATE_TRIANGLE_SIDE = (1<<3), // Validate touched triangle data (side pass)
|
||||
STF_TOUCH_OTHER_CCT = (1<<4), // Are we standing on another CCT or not? (only updated for down pass)
|
||||
STF_TOUCH_OBSTACLE = (1<<5), // Are we standing on an obstacle or not? (only updated for down pass)
|
||||
STF_NORMALIZE_RESPONSE = (1<<6),
|
||||
STF_FIRST_UPDATE = (1<<7),
|
||||
STF_IS_MOVING_UP = (1<<8)
|
||||
};
|
||||
|
||||
enum SweepPass
|
||||
{
|
||||
SWEEP_PASS_UP,
|
||||
SWEEP_PASS_SIDE,
|
||||
SWEEP_PASS_DOWN,
|
||||
SWEEP_PASS_SENSOR
|
||||
};
|
||||
|
||||
class Controller;
|
||||
|
||||
template<class T>
|
||||
struct TouchedObject
|
||||
{
|
||||
TouchedObject(bool regDl)
|
||||
: mTouchedObject(NULL), mRegisterDeletionListener(regDl), mCctManager(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const T* operator->() const { return mTouchedObject; }
|
||||
PX_FORCE_INLINE bool operator==(const TouchedObject& otherObject) { return mTouchedObject == otherObject.mTouchedObject; }
|
||||
PX_FORCE_INLINE bool operator==(const T* otherObject) { return mTouchedObject == otherObject; }
|
||||
PX_FORCE_INLINE bool operator==(const PxBase* otherObject) { return mTouchedObject == otherObject; }
|
||||
PX_FORCE_INLINE operator bool() const { return mTouchedObject != NULL; }
|
||||
PX_FORCE_INLINE TouchedObject& operator=(const T* assignedObject)
|
||||
{
|
||||
if(mRegisterDeletionListener && (mTouchedObject != assignedObject))
|
||||
{
|
||||
if(mTouchedObject)
|
||||
mCctManager->unregisterObservedObject(mTouchedObject);
|
||||
|
||||
if(assignedObject)
|
||||
mCctManager->registerObservedObject(assignedObject);
|
||||
}
|
||||
mTouchedObject = assignedObject;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const T* get() const { return mTouchedObject; }
|
||||
|
||||
void setCctManager(CharacterControllerManager* cm) { mCctManager = cm; }
|
||||
|
||||
private:
|
||||
TouchedObject& operator=(const TouchedObject&);
|
||||
|
||||
const T* mTouchedObject;
|
||||
bool mRegisterDeletionListener;
|
||||
CharacterControllerManager* mCctManager;
|
||||
};
|
||||
|
||||
class SweepTest
|
||||
{
|
||||
PX_NOCOPY(SweepTest)
|
||||
public:
|
||||
SweepTest(bool registerDeletionListener);
|
||||
~SweepTest();
|
||||
|
||||
PxControllerCollisionFlags moveCharacter( const InternalCBData_FindTouchedGeom* userData,
|
||||
InternalCBData_OnHit* user_data2,
|
||||
SweptVolume& volume,
|
||||
const PxVec3& direction,
|
||||
const UserObstacles& userObstacles,
|
||||
PxF32 min_dist,
|
||||
const PxControllerFilters& filters,
|
||||
bool constrainedClimbingMode,
|
||||
bool standingOnMoving,
|
||||
const PxRigidActor*& touchedActor,
|
||||
const PxShape*& touchedShape,
|
||||
PxU64 contextID);
|
||||
|
||||
bool doSweepTest(const InternalCBData_FindTouchedGeom* userDataTouchedGeom,
|
||||
InternalCBData_OnHit* userDataOnHit,
|
||||
const UserObstacles& userObstacles,
|
||||
SweptVolume& swept_volume,
|
||||
const PxVec3& direction, const PxVec3& sideVector, PxU32 max_iter,
|
||||
PxU32* nb_collisions, PxF32 min_dist, const PxControllerFilters& filters, SweepPass sweepPass,
|
||||
const PxRigidActor*& touchedActor, const PxShape*& touchedShape, PxU64 contextID);
|
||||
|
||||
void findTouchedObstacles(const UserObstacles& userObstacles, const PxExtendedBounds3& world_box);
|
||||
|
||||
void voidTestCache();
|
||||
void onRelease(const PxBase& observed);
|
||||
void updateCachedShapesRegistration(PxU32 startIndex, bool unregister);
|
||||
|
||||
// observer notifications
|
||||
void onObstacleRemoved(PxObstacleHandle index);
|
||||
void onObstacleUpdated(PxObstacleHandle index, const PxObstacleContext* context, const PxVec3& origin, const PxVec3& unitDir, PxReal distance);
|
||||
void onObstacleAdded(PxObstacleHandle index, const PxObstacleContext* context, const PxVec3& origin, const PxVec3& unitDir, PxReal distance);
|
||||
|
||||
void onOriginShift(const PxVec3& shift);
|
||||
|
||||
PxRenderBuffer* mRenderBuffer;
|
||||
PxU32 mRenderFlags;
|
||||
TriArray mWorldTriangles;
|
||||
IntArray mTriangleIndices;
|
||||
IntArray mGeomStream;
|
||||
PxExtendedBounds3 mCacheBounds;
|
||||
PxU32 mCachedTriIndexIndex;
|
||||
mutable PxU32 mCachedTriIndex[3];
|
||||
PxU32 mNbCachedStatic;
|
||||
PxU32 mNbCachedT;
|
||||
public:
|
||||
#ifdef USE_CONTACT_NORMAL_FOR_SLOPE_TEST
|
||||
PxVec3 mContactNormalDownPass;
|
||||
#else
|
||||
PxVec3 mContactNormalDownPass;
|
||||
PxVec3 mContactNormalSidePass;
|
||||
float mTouchedTriMin;
|
||||
float mTouchedTriMax;
|
||||
//PxTriangle mTouchedTriangle;
|
||||
#endif
|
||||
//
|
||||
TouchedObject<PxShape> mTouchedShape; // Shape on which the CCT is standing
|
||||
TouchedObject<PxRigidActor> mTouchedActor; // Actor from touched shape
|
||||
PxObstacleHandle mTouchedObstacleHandle; // Obstacle on which the CCT is standing
|
||||
PxVec3 mTouchedPos; // Last known position of mTouchedShape/mTouchedObstacle
|
||||
// PT: TODO: union those
|
||||
PxVec3 mTouchedPosShape_Local;
|
||||
PxVec3 mTouchedPosShape_World;
|
||||
PxVec3 mTouchedPosObstacle_Local;
|
||||
PxVec3 mTouchedPosObstacle_World;
|
||||
//
|
||||
CCTParams mUserParams;
|
||||
PxF32 mVolumeGrowth; // Must be >1.0f and not too big
|
||||
PxF32 mContactPointHeight; // UBI
|
||||
PxU32 mSQTimeStamp;
|
||||
PxU16 mNbFullUpdates;
|
||||
PxU16 mNbPartialUpdates;
|
||||
PxU16 mNbTessellation;
|
||||
PxU16 mNbIterations;
|
||||
PxU32 mFlags;
|
||||
bool mRegisterDeletionListener;
|
||||
|
||||
PX_FORCE_INLINE void resetStats()
|
||||
{
|
||||
mNbFullUpdates = 0;
|
||||
mNbPartialUpdates = 0;
|
||||
mNbTessellation = 0;
|
||||
mNbIterations = 0;
|
||||
}
|
||||
|
||||
void setCctManager(CharacterControllerManager* cm)
|
||||
{
|
||||
mCctManager = cm;
|
||||
mTouchedActor.setCctManager(cm);
|
||||
mTouchedShape.setCctManager(cm);
|
||||
}
|
||||
|
||||
private:
|
||||
void updateTouchedGeoms( const InternalCBData_FindTouchedGeom* userData, const UserObstacles& userObstacles,
|
||||
const PxExtendedBounds3& worldBox, const PxControllerFilters& filters, const PxVec3& sideVector);
|
||||
|
||||
CharacterControllerManager* mCctManager;
|
||||
};
|
||||
|
||||
class CCTFilter // PT: internal filter data, could be replaced with PxControllerFilters eventually
|
||||
{
|
||||
public:
|
||||
PX_FORCE_INLINE CCTFilter() :
|
||||
mFilterData (NULL),
|
||||
mFilterCallback (NULL),
|
||||
mStaticShapes (false),
|
||||
mDynamicShapes (false),
|
||||
mPreFilter (false),
|
||||
mPostFilter (false),
|
||||
mCCTShapes (NULL)
|
||||
{
|
||||
}
|
||||
const PxFilterData* mFilterData;
|
||||
PxQueryFilterCallback* mFilterCallback;
|
||||
bool mStaticShapes;
|
||||
bool mDynamicShapes;
|
||||
bool mPreFilter;
|
||||
bool mPostFilter;
|
||||
PxHashSet<PxShape>* mCCTShapes;
|
||||
};
|
||||
|
||||
PxU32 getSceneTimestamp(const InternalCBData_FindTouchedGeom* userData);
|
||||
|
||||
void findTouchedGeometry(const InternalCBData_FindTouchedGeom* userData,
|
||||
const PxExtendedBounds3& world_aabb,
|
||||
|
||||
TriArray& world_triangles,
|
||||
IntArray& triIndicesArray,
|
||||
IntArray& geomStream,
|
||||
|
||||
const CCTFilter& filter,
|
||||
const CCTParams& params,
|
||||
PxU16& nbTessellation);
|
||||
|
||||
PxU32 shapeHitCallback(const InternalCBData_OnHit* userData, const SweptContact& contact, const PxVec3& dir, PxF32 length);
|
||||
PxU32 userHitCallback(const InternalCBData_OnHit* userData, const SweptContact& contact, const PxVec3& dir, PxF32 length);
|
||||
|
||||
} // namespace Cct
|
||||
|
||||
}
|
||||
|
||||
/** \endcond */
|
||||
#endif
|
||||
Reference in New Issue
Block a user