feat(physics): wire physx sdk into build

This commit is contained in:
2026-04-15 12:22:15 +08:00
parent 5bf258df6d
commit 31f40e2cbb
2044 changed files with 752623 additions and 1 deletions

View File

@@ -0,0 +1,84 @@
// 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 GU_ACTOR_SHAPE_MAP_H
#define GU_ACTOR_SHAPE_MAP_H
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxHashMap.h"
namespace physx
{
namespace Gu
{
typedef PxU64 ActorShapeData;
#define PX_INVALID_INDEX 0xffffffff
class ActorShapeMap
{
public:
PX_PHYSX_COMMON_API ActorShapeMap();
PX_PHYSX_COMMON_API ~ActorShapeMap();
PX_PHYSX_COMMON_API bool add(PxU32 actorIndex, const void* actor, const void* shape, ActorShapeData actorShapeData);
PX_PHYSX_COMMON_API bool remove(PxU32 actorIndex, const void* actor, const void* shape, ActorShapeData* removed);
PX_PHYSX_COMMON_API ActorShapeData find(PxU32 actorIndex, const void* actor, const void* shape) const;
struct ActorShape
{
PX_FORCE_INLINE ActorShape() {}
PX_FORCE_INLINE ActorShape(const void* actor, const void* shape) : mActor(actor), mShape(shape) {}
const void* mActor;
const void* mShape;
PX_FORCE_INLINE bool operator==(const ActorShape& p) const
{
return mActor == p.mActor && mShape == p.mShape;
}
};
private:
PxHashMap<ActorShape, ActorShapeData> mDatabase;
struct Cache
{
// const void* mActor;
const void* mShape;
ActorShapeData mData;
};
PxU32 mCacheSize;
Cache* mCache;
void resizeCache(PxU32 index);
};
}
}
#endif

View File

@@ -0,0 +1,203 @@
// 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 GU_BOUNDS_H
#define GU_BOUNDS_H
#include "foundation/PxBounds3.h"
#include "foundation/PxFlags.h"
#include "foundation/PxVecMath.h"
#include "geometry/PxGeometry.h"
#include "geometry/PxCapsuleGeometry.h"
#include <stddef.h>
#include "GuBox.h"
#include "GuCenterExtents.h"
#include "GuSphere.h"
#include "GuCapsule.h"
// PT: the PX_MAX_BOUNDS_EXTENTS value is too large and produces INF floats when the box values are squared in
// some collision routines. Thus, for the SQ subsystem we use this alternative (smaller) value to mark empty bounds.
// See PX-954 for details.
#define GU_EMPTY_BOUNDS_EXTENTS PxSqrt(0.25f * 1e33f)
namespace physx
{
class PxMeshScale;
namespace Gu
{
PX_FORCE_INLINE void computeCapsuleBounds(PxBounds3& bounds, const PxCapsuleGeometry& capsuleGeom, const PxTransform& pose, float contactOffset=0.0f, float inflation=1.0f)
{
const PxVec3 d = pose.q.getBasisVector0();
PxVec3 extents;
for(PxU32 ax = 0; ax<3; ax++)
extents[ax] = (PxAbs(d[ax]) * capsuleGeom.halfHeight + capsuleGeom.radius + contactOffset)*inflation;
bounds.minimum = pose.p - extents;
bounds.maximum = pose.p + extents;
}
//'contactOffset' and 'inflation' should not be used at the same time, i.e. either contactOffset==0.0f, or inflation==1.0f
PX_PHYSX_COMMON_API void computeBounds(PxBounds3& bounds, const PxGeometry& geometry, const PxTransform& transform, float contactOffset, float inflation); //AABB in world space.
PX_FORCE_INLINE PxBounds3 computeBounds(const PxGeometry& geometry, const PxTransform& pose)
{
PxBounds3 bounds;
computeBounds(bounds, geometry, pose, 0.0f, 1.0f);
return bounds;
}
void computeGlobalBox(PxBounds3& bounds, PxU32 nbPrims, const PxBounds3* PX_RESTRICT boxes, const PxU32* PX_RESTRICT primitives);
PX_PHYSX_COMMON_API void computeBoundsAroundVertices(PxBounds3& bounds, PxU32 nbVerts, const PxVec3* PX_RESTRICT verts);
PX_PHYSX_COMMON_API void computeTightBounds(PxBounds3& bounds, PxU32 nbVerts, const PxVec3* PX_RESTRICT verts, const PxTransform& pose, const PxMeshScale& scale, float contactOffset, float inflation);
PX_PHYSX_COMMON_API void computeLocalBoundsAndGeomEpsilon(const PxVec3* vertices, PxU32 nbVerties, PxBounds3& localBounds, PxReal& geomEpsilon);
#define StoreBounds(bounds, minV, maxV) \
V4StoreU(minV, &bounds.minimum.x); \
PX_ALIGN(16, PxVec4) max4; \
V4StoreA(maxV, &max4.x); \
bounds.maximum = PxVec3(max4.x, max4.y, max4.z);
// PT: TODO: - refactor with "inflateBounds" in GuBounds.cpp if possible
template<const bool useSIMD>
PX_FORCE_INLINE void inflateBounds(PxBounds3& dst, const PxBounds3& src, float enlargement)
{
const float coeff = 0.5f * enlargement;
if(useSIMD)
{
using namespace physx::aos;
Vec4V minV = V4LoadU(&src.minimum.x);
Vec4V maxV = V4LoadU(&src.maximum.x);
const Vec4V eV = V4Scale(V4Sub(maxV, minV), FLoad(coeff));
minV = V4Sub(minV, eV);
maxV = V4Add(maxV, eV);
StoreBounds(dst, minV, maxV);
}
else
{
// PT: this clumsy but necessary second codepath is used to read the last bound of the array
// (making sure we don't V4LoadU invalid memory). Implementation must stay in sync with the
// main codepath above. No, this is not very nice.
const PxVec3& minV = src.minimum;
const PxVec3& maxV = src.maximum;
const PxVec3 eV = (maxV - minV) * coeff;
dst.minimum = minV - eV;
dst.maximum = maxV + eV;
}
}
class ShapeData
{
public:
PX_PHYSX_COMMON_API ShapeData(const PxGeometry& g, const PxTransform& t, PxReal inflation);
// PT: used by overlaps (box, capsule, convex)
PX_FORCE_INLINE const PxVec3& getPrunerBoxGeomExtentsInflated() const { return mPrunerBoxGeomExtents; }
// PT: used by overlaps (box, capsule, convex)
PX_FORCE_INLINE const PxVec3& getPrunerWorldPos() const { return mGuBox.center; }
PX_FORCE_INLINE const PxBounds3& getPrunerInflatedWorldAABB() const { return mPrunerInflatedAABB; }
// PT: used by overlaps (box, capsule, convex)
PX_FORCE_INLINE const PxMat33& getPrunerWorldRot33() const { return mGuBox.rot; }
// PT: this one only used by overlaps so far (for sphere shape, pruner level)
PX_FORCE_INLINE const Gu::Sphere& getGuSphere() const
{
PX_ASSERT(mType == PxGeometryType::eSPHERE);
return reinterpret_cast<const Gu::Sphere&>(mGuSphere);
}
// PT: this one only used by sweeps so far (for box shape, NP level)
PX_FORCE_INLINE const Gu::Box& getGuBox() const
{
PX_ASSERT(mType == PxGeometryType::eBOX);
return mGuBox;
}
// PT: this one used by sweeps (NP level) and overlaps (pruner level) - for capsule shape
PX_FORCE_INLINE const Gu::Capsule& getGuCapsule() const
{
PX_ASSERT(mType == PxGeometryType::eCAPSULE);
return reinterpret_cast<const Gu::Capsule&>(mGuCapsule);
}
PX_FORCE_INLINE float getCapsuleHalfHeight() const
{
PX_ASSERT(mType == PxGeometryType::eCAPSULE);
return mGuBox.extents.x;
}
PX_FORCE_INLINE PxU32 isOBB() const { return PxU32(mIsOBB); }
PX_FORCE_INLINE PxGeometryType::Enum getType() const { return PxGeometryType::Enum(mType); }
PX_NOCOPY(ShapeData)
private:
// PT: box: pre-inflated box extents
// capsule: pre-inflated extents of box-around-capsule
// convex: pre-inflated extents of box-around-convex
// sphere: not used
PxVec3 mPrunerBoxGeomExtents; // used for pruners. This volume encloses but can differ from the original shape
// PT:
//
// box center = unchanged copy of initial shape's position, except for convex (position of box around convex)
// SIMD code will load it as a V4 (safe because member is not last of Gu structure)
//
// box rot = precomputed PxMat33 version of initial shape's rotation, except for convex (rotation of box around convex)
// SIMD code will load it as V4s (safe because member is not last of Gu structure)
//
// box extents = non-inflated initial box extents for box shape, half-height for capsule, otherwise not used
Gu::Box mGuBox;
PxBounds3 mPrunerInflatedAABB; // precomputed AABB for the pruner shape
PxU16 mIsOBB; // true for OBB, false for AABB. Also used as padding for mPrunerInflatedAABB, don't move.
PxU16 mType; // shape's type
// these union Gu shapes are only precomputed for narrow phase (not pruners), can be different from mPrunerVolume
// so need separate storage
union
{
PxU8 mGuCapsule[sizeof(Gu::Capsule)]; // 28
PxU8 mGuSphere[sizeof(Gu::Sphere)]; // 16
};
};
// PT: please make sure it fits in "one" cache line
PX_COMPILE_TIME_ASSERT(sizeof(ShapeData)==128);
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,219 @@
// 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 GU_BOX_H
#define GU_BOX_H
#include "foundation/PxTransform.h"
#include "foundation/PxMat33.h"
#include "common/PxPhysXCommonConfig.h"
namespace physx
{
namespace Gu
{
class Capsule;
PX_PHYSX_COMMON_API void computeOBBPoints(PxVec3* PX_RESTRICT pts, const PxVec3& center, const PxVec3& extents, const PxVec3& base0, const PxVec3& base1, const PxVec3& base2);
/**
\brief Represents an oriented bounding box.
As a center point, extents(radii) and a rotation. i.e. the center of the box is at the center point,
the box is rotated around this point with the rotation and it is 2*extents in width, height and depth.
*/
/**
Box geometry
The rot member describes the world space orientation of the box.
The center member gives the world space position of the box.
The extents give the local space coordinates of the box corner in the positive octant.
Dimensions of the box are: 2*extent.
Transformation to world space is: worldPoint = rot * localPoint + center
Transformation to local space is: localPoint = T(rot) * (worldPoint - center)
Where T(M) denotes the transpose of M.
*/
#if PX_VC
#pragma warning(push)
#pragma warning( disable : 4251 ) // class needs to have dll-interface to be used by clients of class
#endif
class PX_PHYSX_COMMON_API Box
{
public:
/**
\brief Constructor
*/
PX_FORCE_INLINE Box()
{
}
/**
\brief Constructor
\param origin Center of the OBB
\param extent Extents/radii of the obb.
\param base rotation to apply to the obb.
*/
//! Construct from center, extent and rotation
PX_FORCE_INLINE Box(const PxVec3& origin, const PxVec3& extent, const PxMat33& base) : rot(base), center(origin), extents(extent)
{}
//! Copy constructor
PX_FORCE_INLINE Box(const Box& other) : rot(other.rot), center(other.center), extents(other.extents)
{}
/**
\brief Destructor
*/
PX_FORCE_INLINE ~Box()
{
}
//! Assignment operator
PX_FORCE_INLINE const Box& operator=(const Box& other)
{
rot = other.rot;
center = other.center;
extents = other.extents;
return *this;
}
/**
\brief Setups an empty box.
*/
PX_INLINE void setEmpty()
{
center = PxVec3(0);
extents = PxVec3(-PX_MAX_REAL, -PX_MAX_REAL, -PX_MAX_REAL);
rot = PxMat33(PxIdentity);
}
/**
\brief Checks the box is valid.
\return true if the box is valid
*/
PX_INLINE bool isValid() const
{
// Consistency condition for (Center, Extents) boxes: Extents >= 0.0f
if(extents.x < 0.0f) return false;
if(extents.y < 0.0f) return false;
if(extents.z < 0.0f) return false;
return true;
}
/////////////
PX_FORCE_INLINE void setAxes(const PxVec3& axis0, const PxVec3& axis1, const PxVec3& axis2)
{
rot.column0 = axis0;
rot.column1 = axis1;
rot.column2 = axis2;
}
PX_FORCE_INLINE PxVec3 rotate(const PxVec3& src) const
{
return rot * src;
}
PX_FORCE_INLINE PxVec3 rotateInv(const PxVec3& src) const
{
return rot.transformTranspose(src);
}
PX_FORCE_INLINE PxVec3 transform(const PxVec3& src) const
{
return rot * src + center;
}
PX_FORCE_INLINE PxTransform getTransform() const
{
return PxTransform(center, PxQuat(rot));
}
PX_INLINE PxVec3 computeAABBExtent() const
{
const PxReal a00 = PxAbs(rot[0][0]);
const PxReal a01 = PxAbs(rot[0][1]);
const PxReal a02 = PxAbs(rot[0][2]);
const PxReal a10 = PxAbs(rot[1][0]);
const PxReal a11 = PxAbs(rot[1][1]);
const PxReal a12 = PxAbs(rot[1][2]);
const PxReal a20 = PxAbs(rot[2][0]);
const PxReal a21 = PxAbs(rot[2][1]);
const PxReal a22 = PxAbs(rot[2][2]);
const PxReal ex = extents.x;
const PxReal ey = extents.y;
const PxReal ez = extents.z;
return PxVec3( a00 * ex + a10 * ey + a20 * ez,
a01 * ex + a11 * ey + a21 * ez,
a02 * ex + a12 * ey + a22 * ez);
}
/**
Computes the obb points.
\param pts [out] 8 box points
*/
PX_FORCE_INLINE void computeBoxPoints(PxVec3* PX_RESTRICT pts) const
{
Gu::computeOBBPoints(pts, center, extents, rot.column0, rot.column1, rot.column2);
}
void create(const Gu::Capsule& capsule);
PxMat33 rot;
PxVec3 center;
PxVec3 extents;
};
PX_COMPILE_TIME_ASSERT(sizeof(Gu::Box) == 60);
//! A padded version of Gu::Box, to safely load its data using SIMD
class BoxPadded : public Box
{
public:
PX_FORCE_INLINE BoxPadded() {}
PX_FORCE_INLINE ~BoxPadded() {}
PxU32 padding;
};
PX_COMPILE_TIME_ASSERT(sizeof(Gu::BoxPadded) == 64);
#if PX_VC
#pragma warning(pop)
#endif
}
}
#endif

View File

@@ -0,0 +1,58 @@
// 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 GU_CACHED_FUNCS_H
#define GU_CACHED_FUNCS_H
#include "GuRaycastTests.h"
#include "GuSweepTests.h"
#include "GuOverlapTests.h"
namespace physx
{
namespace Gu
{
struct CachedFuncs
{
CachedFuncs() :
mCachedRaycastFuncs (Gu::getRaycastFuncTable()),
mCachedSweepFuncs (Gu::getSweepFuncTable()),
mCachedOverlapFuncs (Gu::getOverlapFuncTable())
{
}
const Gu::GeomRaycastTable& mCachedRaycastFuncs;
const Gu::GeomSweepFuncs& mCachedSweepFuncs;
const Gu::GeomOverlapTable* mCachedOverlapFuncs;
PX_NOCOPY(CachedFuncs)
};
}
}
#endif

View File

@@ -0,0 +1,87 @@
// 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 GU_CAPSULE_H
#define GU_CAPSULE_H
#include "GuSegment.h"
namespace physx
{
namespace Gu
{
/**
\brief Represents a capsule.
*/
class Capsule : public Segment
{
public:
/**
\brief Constructor
*/
PX_INLINE Capsule()
{
}
/**
\brief Constructor
\param seg Line segment to create capsule from.
\param _radius Radius of the capsule.
*/
PX_INLINE Capsule(const Segment& seg, PxF32 _radius) : Segment(seg), radius(_radius)
{
}
/**
\brief Constructor
\param _p0 First segment point
\param _p1 Second segment point
\param _radius Radius of the capsule.
*/
PX_INLINE Capsule(const PxVec3& _p0, const PxVec3& _p1, PxF32 _radius) : Segment(_p0, _p1), radius(_radius)
{
}
/**
\brief Destructor
*/
PX_INLINE ~Capsule()
{
}
PxF32 radius;
};
}
}
#endif

View File

@@ -0,0 +1,123 @@
// 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 GU_CENTER_EXTENTS_H
#define GU_CENTER_EXTENTS_H
#include "foundation/PxUserAllocated.h"
#include "foundation/PxBounds3.h"
namespace physx
{
namespace Gu
{
class CenterExtents : public physx::PxUserAllocated
{
public:
PX_FORCE_INLINE CenterExtents() {}
PX_FORCE_INLINE CenterExtents(const PxBounds3& b) { mCenter = b.getCenter(); mExtents = b.getExtents(); }
PX_FORCE_INLINE ~CenterExtents() {}
PX_FORCE_INLINE void getMin(PxVec3& min) const { min = mCenter - mExtents; }
PX_FORCE_INLINE void getMax(PxVec3& max) const { max = mCenter + mExtents; }
PX_FORCE_INLINE float getMin(PxU32 axis) const { return mCenter[axis] - mExtents[axis]; }
PX_FORCE_INLINE float getMax(PxU32 axis) const { return mCenter[axis] + mExtents[axis]; }
PX_FORCE_INLINE PxVec3 getMin() const { return mCenter - mExtents; }
PX_FORCE_INLINE PxVec3 getMax() const { return mCenter + mExtents; }
PX_FORCE_INLINE void setMinMax(const PxVec3& min, const PxVec3& max)
{
mCenter = (max + min)*0.5f;
mExtents = (max - min)*0.5f;
}
PX_FORCE_INLINE PxU32 isInside(const CenterExtents& box) const
{
if(box.getMin(0)>getMin(0)) return 0;
if(box.getMin(1)>getMin(1)) return 0;
if(box.getMin(2)>getMin(2)) return 0;
if(box.getMax(0)<getMax(0)) return 0;
if(box.getMax(1)<getMax(1)) return 0;
if(box.getMax(2)<getMax(2)) return 0;
return 1;
}
PX_FORCE_INLINE void setEmpty()
{
mExtents = PxVec3(-PX_MAX_BOUNDS_EXTENTS);
}
PX_FORCE_INLINE bool isEmpty() const
{
PX_ASSERT(isValid());
return mExtents.x<0.0f;
}
PX_FORCE_INLINE bool isFinite() const
{
return mCenter.isFinite() && mExtents.isFinite();
}
PX_FORCE_INLINE bool isValid() const
{
const PxVec3& c = mCenter;
const PxVec3& e = mExtents;
return (c.isFinite() && e.isFinite() && (((e.x >= 0.0f) && (e.y >= 0.0f) && (e.z >= 0.0f)) ||
((e.x == -PX_MAX_BOUNDS_EXTENTS) &&
(e.y == -PX_MAX_BOUNDS_EXTENTS) &&
(e.z == -PX_MAX_BOUNDS_EXTENTS))));
}
PX_FORCE_INLINE PxBounds3 transformFast(const PxMat33& matrix) const
{
PX_ASSERT(isValid());
return PxBounds3::basisExtent(matrix * mCenter, matrix, mExtents);
}
PxVec3 mCenter;
PxVec3 mExtents;
};
//! A padded version of CenterExtents, to safely load its data using SIMD
class CenterExtentsPadded : public CenterExtents
{
public:
PX_FORCE_INLINE CenterExtentsPadded() {}
PX_FORCE_INLINE ~CenterExtentsPadded() {}
PxU32 padding;
};
PX_COMPILE_TIME_ASSERT(sizeof(CenterExtentsPadded) == 7*4);
}
}
#endif

View File

@@ -0,0 +1,56 @@
// 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 GU_CONVEX_GEOMETRY_H
#define GU_CONVEX_GEOMETRY_H
#include "foundation/PxVec3.h"
#include "foundation/PxMat33.h"
#include "foundation/PxBounds3.h"
namespace physx
{
class PxConvexCoreGeometry;
class PxBounds3;
class PxRenderOutput;
namespace Gu
{
struct ConvexShape;
PX_PHYSX_COMMON_API bool makeConvexShape(const PxGeometry& geom, const PxTransform& pose, ConvexShape& convex);
PX_PHYSX_COMMON_API bool isGPUCompatible(const PxConvexCoreGeometry& convex);
PX_PHYSX_COMMON_API void computeMassInfo(const PxConvexCoreGeometry& convex, PxReal& density1Mass, PxMat33& inertiaTensor, PxVec3& centerOfMass);
PX_PHYSX_COMMON_API void visualize(const PxConvexCoreGeometry& convex, const PxTransform& pose, bool drawCore, const PxBounds3& cullbox, PxRenderOutput& out);
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
// 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 GU_COOKING_H
#define GU_COOKING_H
// PT: TODO: the SDK always had this questionable design decision that all APIs can include all high-level public headers,
// regardless of where they fit in the header hierarchy. For example PhysXCommon can include headers from the higher-level
// PhysX DLL. We take advantage of that here by including PxCooking from PhysXCommon. That way we can reuse the same code
// as before without decoupling it from high-level classes like PxConvexMeshDesc/etc. A cleaner solution would be to decouple
// the two and only use PxConvexMeshDesc/etc in the higher level cooking DLL. The lower-level Gu functions below would then
// operate either on Gu-level types (see e.g. PxBVH / GuBVH which was done this way), or on basic types like float and ints
// to pass vertex & triangle data around. We could also split the kitchen-sink PxCookingParams structure into separate classes
// for convex / triangle mesh / etc. Overall there might be some more refactoring to do here, and that's why these functions
// have been put in the "semi public" Gu API for now, instead of the Px API (which is more strict in terms of backward
// compatibility and how we deal with deprecated functions).
#include "cooking/PxCooking.h"
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxUtilities.h"
#include "foundation/PxMemory.h"
namespace physx
{
class PxInsertionCallback;
class PxOutputStream;
class PxBVHDesc;
class PxBVH;
class PxHeightField;
struct PxCookingParams;
namespace immediateCooking
{
PX_FORCE_INLINE static void gatherStrided(const void* src, void* dst, PxU32 nbElem, PxU32 elemSize, PxU32 stride)
{
const PxU8* s = reinterpret_cast<const PxU8*>(src);
PxU8* d = reinterpret_cast<PxU8*>(dst);
while(nbElem--)
{
PxMemCopy(d, s, elemSize);
d += elemSize;
s += stride;
}
}
PX_INLINE static bool platformMismatch()
{
// Get current endianness (the one for the platform where cooking is performed)
const PxI8 currentEndian = PxLittleEndian();
const bool mismatch = currentEndian!=1; // The files must be little endian - we don't have big endian platforms anymore.
return mismatch;
}
PX_C_EXPORT PX_PHYSX_COMMON_API PxInsertionCallback* getInsertionCallback(); // PT: should be a reference but using a pointer for C
// BVH
PX_C_EXPORT PX_PHYSX_COMMON_API bool cookBVH(const PxBVHDesc& desc, PxOutputStream& stream);
PX_C_EXPORT PX_PHYSX_COMMON_API PxBVH* createBVH(const PxBVHDesc& desc, PxInsertionCallback& insertionCallback);
PX_FORCE_INLINE PxBVH* createBVH(const PxBVHDesc& desc)
{
return createBVH(desc, *getInsertionCallback());
}
// Heightfield
PX_C_EXPORT PX_PHYSX_COMMON_API bool cookHeightField(const PxHeightFieldDesc& desc, PxOutputStream& stream);
PX_C_EXPORT PX_PHYSX_COMMON_API PxHeightField* createHeightField(const PxHeightFieldDesc& desc, PxInsertionCallback& insertionCallback);
PX_FORCE_INLINE PxHeightField* createHeightField(const PxHeightFieldDesc& desc)
{
return createHeightField(desc, *getInsertionCallback());
}
// Convex meshes
PX_C_EXPORT PX_PHYSX_COMMON_API bool cookConvexMesh(const PxCookingParams& params, const PxConvexMeshDesc& desc, PxOutputStream& stream, PxConvexMeshCookingResult::Enum* condition=NULL);
PX_C_EXPORT PX_PHYSX_COMMON_API PxConvexMesh* createConvexMesh(const PxCookingParams& params, const PxConvexMeshDesc& desc, PxInsertionCallback& insertionCallback, PxConvexMeshCookingResult::Enum* condition=NULL);
PX_FORCE_INLINE PxConvexMesh* createConvexMesh(const PxCookingParams& params, const PxConvexMeshDesc& desc)
{
return createConvexMesh(params, desc, *getInsertionCallback());
}
PX_C_EXPORT PX_PHYSX_COMMON_API bool validateConvexMesh(const PxCookingParams& params, const PxConvexMeshDesc& desc);
PX_C_EXPORT PX_PHYSX_COMMON_API bool computeHullPolygons(const PxCookingParams& params, const PxSimpleTriangleMesh& mesh, PxAllocatorCallback& inCallback, PxU32& nbVerts, PxVec3*& vertices,
PxU32& nbIndices, PxU32*& indices, PxU32& nbPolygons, PxHullPolygon*& hullPolygons);
// Triangle meshes
PX_C_EXPORT PX_PHYSX_COMMON_API bool validateTriangleMesh(const PxCookingParams& params, const PxTriangleMeshDesc& desc);
PX_C_EXPORT PX_PHYSX_COMMON_API PxTriangleMesh* createTriangleMesh(const PxCookingParams& params, const PxTriangleMeshDesc& desc, PxInsertionCallback& insertionCallback, PxTriangleMeshCookingResult::Enum* condition=NULL);
PX_C_EXPORT PX_PHYSX_COMMON_API bool cookTriangleMesh(const PxCookingParams& params, const PxTriangleMeshDesc& desc, PxOutputStream& stream, PxTriangleMeshCookingResult::Enum* condition=NULL);
PX_FORCE_INLINE PxTriangleMesh* createTriangleMesh(const PxCookingParams& params, const PxTriangleMeshDesc& desc)
{
return createTriangleMesh(params, desc, *getInsertionCallback());
}
// Tetrahedron & deformable volume meshes
PX_C_EXPORT PX_PHYSX_COMMON_API bool cookTetrahedronMesh(const PxCookingParams& params, const PxTetrahedronMeshDesc& meshDesc, PxOutputStream& stream);
PX_C_EXPORT PX_PHYSX_COMMON_API PxTetrahedronMesh* createTetrahedronMesh(const PxCookingParams& params, const PxTetrahedronMeshDesc& meshDesc, PxInsertionCallback& insertionCallback);
PX_FORCE_INLINE PxTetrahedronMesh* createTetrahedronMesh(const PxCookingParams& params, const PxTetrahedronMeshDesc& meshDesc)
{
return createTetrahedronMesh(params, meshDesc, *getInsertionCallback());
}
PX_C_EXPORT PX_PHYSX_COMMON_API bool cookDeformableVolumeMesh(const PxCookingParams& params, const PxTetrahedronMeshDesc& simulationMeshDesc, const PxTetrahedronMeshDesc& collisionMeshDesc,
const PxDeformableVolumeSimulationDataDesc& softbodyDataDesc, PxOutputStream& stream);
PX_C_EXPORT PX_PHYSX_COMMON_API PxDeformableVolumeMesh* createDeformableVolumeMesh(const PxCookingParams& params, const PxTetrahedronMeshDesc& simulationMeshDesc, const PxTetrahedronMeshDesc& collisionMeshDesc,
const PxDeformableVolumeSimulationDataDesc& softbodyDataDesc, PxInsertionCallback& insertionCallback);
PX_FORCE_INLINE PxDeformableVolumeMesh* createDeformableVolumeMesh(const PxCookingParams& params, const PxTetrahedronMeshDesc& simulationMeshDesc, const PxTetrahedronMeshDesc& collisionMeshDesc,
const PxDeformableVolumeSimulationDataDesc& deformableVolumeDataDesc)
{
return createDeformableVolumeMesh(params, simulationMeshDesc, collisionMeshDesc, deformableVolumeDataDesc, *getInsertionCallback());
}
PX_C_EXPORT PX_PHYSX_COMMON_API PxCollisionMeshMappingData* computeModelsMapping(const PxCookingParams& params,
PxTetrahedronMeshData& simulationMesh, const PxTetrahedronMeshData& collisionMesh,
const PxDeformableVolumeCollisionData& collisionData, const PxBoundedData* vertexToTet = NULL);
PX_C_EXPORT PX_PHYSX_COMMON_API PxCollisionTetrahedronMeshData* computeCollisionData(const PxCookingParams& params, const PxTetrahedronMeshDesc& collisionMeshDesc);
PX_C_EXPORT PX_PHYSX_COMMON_API PxSimulationTetrahedronMeshData* computeSimulationData(const PxCookingParams& params, const PxTetrahedronMeshDesc& simulationMeshDesc);
PX_C_EXPORT PX_PHYSX_COMMON_API PxDeformableVolumeMesh* assembleDeformableVolumeMesh(PxTetrahedronMeshData& simulationMesh,
PxDeformableVolumeSimulationData& simulationData, PxTetrahedronMeshData& collisionMesh, PxDeformableVolumeCollisionData& collisionData,
PxCollisionMeshMappingData& mappingData, PxInsertionCallback& insertionCallback);
}
}
#endif

View File

@@ -0,0 +1,136 @@
// 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 GU_DISTANCE_POINT_TETRAHEDRON_H
#define GU_DISTANCE_POINT_TETRAHEDRON_H
#include "foundation/PxVec3.h"
#include "foundation/PxVec4.h"
#include "common/PxPhysXCommonConfig.h"
#include "GuDistancePointTriangle.h"
#include "foundation/PxMathUtils.h"
namespace physx
{
namespace Gu
{
PX_INLINE PX_CUDA_CALLABLE PxVec4 PointOutsideOfPlane4(const PxVec3& p, const PxVec3& _a, const PxVec3& _b,
const PxVec3& _c, const PxVec3& _d)
{
const PxVec3 ap = p - _a;
const PxVec3 ab = _b - _a;
const PxVec3 ac = _c - _a;
const PxVec3 ad = _d - _a;
const PxVec3 v0 = ab.cross(ac);
const float signa0 = v0.dot(ap);
const float signd0 = v0.dot(ad);// V3Dot(v0, _d);
const PxVec3 v1 = ac.cross(ad);
const float signa1 = v1.dot(ap);
const float signd1 = v1.dot(ab);
const PxVec3 v2 = ad.cross(ab);
const float signa2 = v2.dot(ap);
const float signd2 = v2.dot(ac);// V3Dot(v2, _c);
const PxVec3 bd = _d - _b;
const PxVec3 bc = _c - _b;
const PxVec3 v3 = bd.cross(bc);
const float signd3 = v3.dot(p - _b);
const float signa3 = v3.dot(_a - _b);
//if combined signDist is least zero, p is outside of that face
PxVec4 result = PxVec4(signa0 * signd0, signa1 * signd1, signa2 * signd2, signa3 * signd3);
return result;
}
PX_PHYSX_COMMON_API PxVec3 closestPtPointTetrahedron(const PxVec3& p, const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxVec3& d, const PxVec4& result);
PX_INLINE PX_CUDA_CALLABLE PxVec3 closestPtPointTetrahedron(const PxVec3& p, const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxVec3& d)
{
const PxVec3 ab = b - a;
const PxVec3 ac = c - a;
const PxVec3 ad = d - a;
const PxVec3 bc = c - b;
const PxVec3 bd = d - b;
//point to face 0, 1, 2
PxVec3 bestClosestPt = closestPtPointTriangle2(p, a, b, c, ab, ac);
PxVec3 diff = bestClosestPt - p;
PxReal bestSqDist = diff.dot(diff);
// 0, 2, 3
PxVec3 closestPt = closestPtPointTriangle2(p, a, c, d, ac, ad);
diff = closestPt - p;
PxReal sqDist = diff.dot(diff);
if (sqDist < bestSqDist)
{
bestClosestPt = closestPt;
bestSqDist = sqDist;
}
// 0, 3, 1
closestPt = closestPtPointTriangle2(p, a, d, b, ad, ab);
diff = closestPt - p;
sqDist = diff.dot(diff);
if (sqDist < bestSqDist)
{
bestClosestPt = closestPt;
bestSqDist = sqDist;
}
// 1, 3, 2
closestPt = closestPtPointTriangle2(p, b, d, c, bd, bc);
diff = closestPt - p;
sqDist = diff.dot(diff);
if (sqDist < bestSqDist)
{
bestClosestPt = closestPt;
bestSqDist = sqDist;
}
return bestClosestPt;
}
PX_INLINE PX_CUDA_CALLABLE PxVec3 closestPtPointTetrahedronWithInsideCheck(const PxVec3& p, const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxVec3& d, const PxReal eps = 0)
{
PxVec4 tmpBarycentric;
PxComputeBarycentric(a, b, c, d, p, tmpBarycentric);
if ((tmpBarycentric.x >= -eps && tmpBarycentric.x <= 1.f + eps) && (tmpBarycentric.y >= -eps && tmpBarycentric.y <= 1.f + eps) &&
(tmpBarycentric.z >= -eps && tmpBarycentric.z <= 1.f + eps) && (tmpBarycentric.w >= -eps && tmpBarycentric.w <= 1.f + eps))
return p;
return closestPtPointTetrahedron(p, a, b, c, d);
}
}
}
#endif

View File

@@ -0,0 +1,215 @@
// 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 GU_DISTANCE_POINT_TRIANGLE_H
#define GU_DISTANCE_POINT_TRIANGLE_H
#include "foundation/PxVec3.h"
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxVecMath.h"
namespace physx
{
namespace Gu
{
// PT: special version:
// - inlined
// - doesn't compute (s,t) output params
// - expects precomputed edges in input
PX_FORCE_INLINE PX_CUDA_CALLABLE PxVec3 closestPtPointTriangle2(const PxVec3& p, const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxVec3& ab, const PxVec3& ac)
{
// Check if P in vertex region outside A
//const PxVec3 ab = b - a;
//const PxVec3 ac = c - a;
const PxVec3 ap = p - a;
const float d1 = ab.dot(ap);
const float d2 = ac.dot(ap);
if(d1<=0.0f && d2<=0.0f)
return a; // Barycentric coords 1,0,0
// Check if P in vertex region outside B
const PxVec3 bp = p - b;
const float d3 = ab.dot(bp);
const float d4 = ac.dot(bp);
if(d3>=0.0f && d4<=d3)
return b; // Barycentric coords 0,1,0
// Check if P in edge region of AB, if so return projection of P onto AB
const float vc = d1*d4 - d3*d2;
if(vc<=0.0f && d1>=0.0f && d3<=0.0f)
{
const float v = d1 / (d1 - d3);
return a + v * ab; // barycentric coords (1-v, v, 0)
}
// Check if P in vertex region outside C
const PxVec3 cp = p - c;
const float d5 = ab.dot(cp);
const float d6 = ac.dot(cp);
if(d6>=0.0f && d5<=d6)
return c; // Barycentric coords 0,0,1
// Check if P in edge region of AC, if so return projection of P onto AC
const float vb = d5*d2 - d1*d6;
if(vb<=0.0f && d2>=0.0f && d6<=0.0f)
{
const float w = d2 / (d2 - d6);
return a + w * ac; // barycentric coords (1-w, 0, w)
}
// Check if P in edge region of BC, if so return projection of P onto BC
const float va = d3*d6 - d5*d4;
if(va<=0.0f && (d4-d3)>=0.0f && (d5-d6)>=0.0f)
{
const float w = (d4-d3) / ((d4 - d3) + (d5-d6));
return b + w * (c-b); // barycentric coords (0, 1-w, w)
}
// P inside face region. Compute Q through its barycentric coords (u,v,w)
const float denom = 1.0f / (va + vb + vc);
const float v = vb * denom;
const float w = vc * denom;
return a + ab*v + ac*w;
}
//Scales and translates triangle and query points to fit into the unit box to make calculations less prone to numerical cancellation.
//The returned point will still be in the same space as the input points.
PX_FORCE_INLINE PX_CUDA_CALLABLE PxVec3 closestPtPointTriangle2UnitBox(const PxVec3& queryPoint, const PxVec3& triA, const PxVec3& triB, const PxVec3& triC)
{
const PxVec3 min = queryPoint.minimum(triA.minimum(triB.minimum(triC)));
const PxVec3 max = queryPoint.maximum(triA.maximum(triB.maximum(triC)));
const PxVec3 size = max - min;
PxReal invScaling = PxMax(PxMax(size.x, size.y), PxMax(1e-12f, size.z));
PxReal scaling = 1.0f / invScaling;
PxVec3 p = (queryPoint - min) * scaling;
PxVec3 a = (triA - min) * scaling;
PxVec3 b = (triB - min) * scaling;
PxVec3 c = (triC - min) * scaling;
PxVec3 result = closestPtPointTriangle2(p, a, b, c, b - a, c - a);
return result * invScaling + min;
}
// Given the point `c`, return the closest point on the triangle (1, 0, 0), (0, 1, 0), (0, 0, 1).
// This function is a specialization of `Gu::closestPtPointTriangle2` for this specific triangle.
PX_FORCE_INLINE PX_CUDA_CALLABLE PxVec3 closestPtPointBaryTriangle(PxVec3 c)
{
const PxReal third = 1.0f / 3.0f; // constexpr
c -= PxVec3(third * (c.x + c.y + c.z - 1.0f));
// two negative: return positive vertex
if (c.y < 0.0f && c.z < 0.0f)
return PxVec3(1.0f, 0.0f, 0.0f);
if (c.x < 0.0f && c.z < 0.0f)
return PxVec3(0.0f, 1.0f, 0.0f);
if (c.x < 0.0f && c.y < 0.0f)
return PxVec3(0.0f, 0.0f, 1.0f);
// one negative: return projection onto line if it is on the edge, or the largest vertex otherwise
if (c.x < 0.0f)
{
const PxReal d = c.x * 0.5f;
const PxReal y = c.y + d;
const PxReal z = c.z + d;
if (y > 1.0f)
return PxVec3(0.0f, 1.0f, 0.0f);
if (z > 1.0f)
return PxVec3(0.0f, 0.0f, 1.0f);
return PxVec3(0.0f, y, z);
}
if (c.y < 0.0f)
{
const PxReal d = c.y * 0.5f;
const PxReal x = c.x + d;
const PxReal z = c.z + d;
if (x > 1.0f)
return PxVec3(1.0f, 0.0f, 0.0f);
if (z > 1.0f)
return PxVec3(0.0f, 0.0f, 1.0f);
return PxVec3(x, 0.0f, z);
}
if (c.z < 0.0f)
{
const PxReal d = c.z * 0.5f;
const PxReal x = c.x + d;
const PxReal y = c.y + d;
if (x > 1.0f)
return PxVec3(1.0f, 0.0f, 0.0f);
if (y > 1.0f)
return PxVec3(0.0f, 1.0f, 0.0f);
return PxVec3(x, y, 0.0f);
}
return c;
}
PX_PHYSX_COMMON_API PxVec3 closestPtPointTriangle(const PxVec3& p, const PxVec3& a, const PxVec3& b, const PxVec3& c, float& s, float& t);
PX_FORCE_INLINE PxReal distancePointTriangleSquared(const PxVec3& point,
const PxVec3& triangleOrigin, const PxVec3& triangleEdge0, const PxVec3& triangleEdge1,
PxReal* param0=NULL, PxReal* param1=NULL)
{
const PxVec3 pt0 = triangleEdge0 + triangleOrigin;
const PxVec3 pt1 = triangleEdge1 + triangleOrigin;
float s,t;
const PxVec3 cp = closestPtPointTriangle(point, triangleOrigin, pt0, pt1, s, t);
if(param0)
*param0 = s;
if(param1)
*param1 = t;
return (cp - point).magnitudeSquared();
}
PX_PHYSX_COMMON_API aos::FloatV distancePointTriangleSquared( const aos::Vec3VArg point,
const aos::Vec3VArg a,
const aos::Vec3VArg b,
const aos::Vec3VArg c,
aos::FloatV& u,
aos::FloatV& v,
aos::Vec3V& closestP);
//Scales and translates triangle and query points to fit into the unit box to make calculations less prone to numerical cancellation.
//The returned point and squared distance will still be in the same space as the input points.
PX_PHYSX_COMMON_API aos::FloatV distancePointTriangleSquared2UnitBox(
const aos::Vec3VArg point,
const aos::Vec3VArg a,
const aos::Vec3VArg b,
const aos::Vec3VArg c,
aos::FloatV& u,
aos::FloatV& v,
aos::Vec3V& closestP);
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,56 @@
// 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 GU_DISTANCE_SEGMENT_BOX_H
#define GU_DISTANCE_SEGMENT_BOX_H
#include "foundation/PxMat33.h"
#include "GuSegment.h"
#include "GuBox.h"
namespace physx
{
namespace Gu
{
//! Compute the smallest distance from the (finite) line segment to the box.
PX_PHYSX_COMMON_API PxReal distanceSegmentBoxSquared( const PxVec3& segmentPoint0, const PxVec3& segmentPoint1,
const PxVec3& boxOrigin, const PxVec3& boxExtent, const PxMat33& boxBase,
PxReal* segmentParam = NULL,
PxVec3* boxParam = NULL);
PX_FORCE_INLINE PxReal distanceSegmentBoxSquared(const Gu::Segment& segment, const Gu::Box& box, PxReal* t = NULL, PxVec3* p = NULL)
{
return distanceSegmentBoxSquared(segment.p0, segment.p1, box.center, box.extents, box.rot, t, p);
}
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,76 @@
// 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 GU_DISTANCE_SEGMENT_SEGMENT_H
#define GU_DISTANCE_SEGMENT_SEGMENT_H
#include "common/PxPhysXCommonConfig.h"
#include "GuSegment.h"
#include "foundation/PxVecMath.h"
namespace physx
{
namespace Gu
{
// This version fixes accuracy issues (e.g. TTP 4617), but needs to do 2 square roots in order
// to find the normalized direction and length of the segments, and then
// a division in order to renormalize the output
PX_PHYSX_COMMON_API PxReal distanceSegmentSegmentSquared( const PxVec3& origin0, const PxVec3& dir0, PxReal extent0,
const PxVec3& origin1, const PxVec3& dir1, PxReal extent1,
PxReal* s=NULL, PxReal* t=NULL);
PX_PHYSX_COMMON_API PxReal distanceSegmentSegmentSquared( const PxVec3& origin0, const PxVec3& extent0,
const PxVec3& origin1, const PxVec3& extent1,
PxReal* s=NULL, PxReal* t=NULL);
PX_FORCE_INLINE PxReal distanceSegmentSegmentSquared( const Gu::Segment& segment0,
const Gu::Segment& segment1,
PxReal* s=NULL, PxReal* t=NULL)
{
return distanceSegmentSegmentSquared( segment0.p0, segment0.computeDirection(),
segment1.p0, segment1.computeDirection(),
s, t);
}
PX_PHYSX_COMMON_API aos::FloatV distanceSegmentSegmentSquared( const aos::Vec3VArg p1, const aos::Vec3VArg d1, const aos::Vec3VArg p2, const aos::Vec3VArg d2,
aos::FloatV& param0,
aos::FloatV& param1);
// This function do four segment segment closest point test in one go
aos::Vec4V distanceSegmentSegmentSquared4( const aos::Vec3VArg p, const aos::Vec3VArg d,
const aos::Vec3VArg p02, const aos::Vec3VArg d02,
const aos::Vec3VArg p12, const aos::Vec3VArg d12,
const aos::Vec3VArg p22, const aos::Vec3VArg d22,
const aos::Vec3VArg p32, const aos::Vec3VArg d32,
aos::Vec4V& s, aos::Vec4V& t);
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,48 @@
// 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 GU_FACTORY_H
#define GU_FACTORY_H
#include "foundation/PxSimpleTypes.h"
#include "common/PxPhysXCommonConfig.h"
#include "GuPrunerTypedef.h"
namespace physx
{
namespace Gu
{
class Pruner;
PX_C_EXPORT PX_PHYSX_COMMON_API Gu::Pruner* createBucketPruner(PxU64 contextID);
PX_C_EXPORT PX_PHYSX_COMMON_API Gu::Pruner* createAABBPruner(PxU64 contextID, bool dynamic, Gu::CompanionPrunerType type, Gu::BVHBuildStrategy buildStrategy, PxU32 nbObjectsPerNode);
PX_C_EXPORT PX_PHYSX_COMMON_API Gu::Pruner* createIncrementalPruner(PxU64 contextID);
}
}
#endif

View File

@@ -0,0 +1,53 @@
// 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 GU_INTERSECTION_BOX_BOX_H
#define GU_INTERSECTION_BOX_BOX_H
#include "foundation/PxMat33.h"
#include "foundation/PxBounds3.h"
#include "GuBox.h"
namespace physx
{
namespace Gu
{
PX_PHYSX_COMMON_API bool intersectOBBOBB(const PxVec3& e0, const PxVec3& c0, const PxMat33& r0, const PxVec3& e1, const PxVec3& c1, const PxMat33& r1, bool full_test);
PX_FORCE_INLINE bool intersectOBBAABB(const Gu::Box& obb, const PxBounds3& aabb)
{
PxVec3 center = aabb.getCenter();
PxVec3 extents = aabb.getExtents();
return intersectOBBOBB(obb.extents, obb.center, obb.rot, extents, center, PxMat33(PxIdentity), true);
}
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,59 @@
// 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 GU_INTERSECTION_TETRAHEDRON_BOX_H
#define GU_INTERSECTION_TETRAHEDRON_BOX_H
#include "foundation/PxVec3.h"
#include "foundation/PxBounds3.h"
#include "common/PxPhysXCommonConfig.h"
namespace physx
{
namespace Gu
{
class Box;
class BoxPadded;
/**
Tests if a tetrahedron overlaps a box (AABB).
\param a [in] tetrahedron's first point
\param b [in] tetrahedron's second point
\param c [in] tetrahedron's third point
\param d [in] tetrahedron's fourth point
\param box [in] The axis aligned box box to check for overlap
\return true if tetrahedron overlaps box
*/
PX_PHYSX_COMMON_API bool intersectTetrahedronBox(const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxVec3& d, const PxBounds3& box);
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,173 @@
// 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 GU_INTERSECTION_TETRAHEDRON_TETRAHEDRON_H
#define GU_INTERSECTION_TETRAHEDRON_TETRAHEDRON_H
#include "foundation/PxPlane.h"
#include "common/PxPhysXCommonConfig.h"
namespace physx
{
namespace Gu
{
struct Tetrahedron
{
PxVec3 verts[4];
PxPlane planes[4];
PxVec3 centroid;
};
PX_INLINE PX_CUDA_CALLABLE PxPlane createPlane(const PxVec3& pa, const PxVec3& pb, const PxVec3& pc, const PxVec3& pd)
{
PxPlane plane(pa, pb, pc);
PxReal distance = plane.distance(pd);
if (distance > 0.f)
{
plane.n = -plane.n;
plane.d = -plane.d;
}
return plane;
}
PX_INLINE PX_CUDA_CALLABLE void constructTetrahedron(const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxVec3& d,
Tetrahedron& tet)
{
tet.verts[0] = a; tet.verts[1] = b; tet.verts[2] = c; tet.verts[3] = d;
tet.planes[0] = createPlane(a, b, c, d);
tet.planes[1] = createPlane(a, b, d, c);
tet.planes[2] = createPlane(a, c, d, b);
tet.planes[3] = createPlane(b, c, d, a);
tet.centroid = (a + b + c) * (1.f / 3.f);
}
PX_INLINE PX_CUDA_CALLABLE PxReal minProject(const PxPlane& plane, const Tetrahedron& tet)
{
/*return PxMin(plane.distance(tet.verts[0]), PxMin(plane.distance(tet.verts[1]),
PxMin(plane.distance(tet.verts[2]), plane.distance(tet.verts[3]))));*/
return PxMin(plane.n.dot(tet.verts[0]),PxMin(plane.n.dot(tet.verts[1]),
PxMin(plane.n.dot(tet.verts[2]), plane.n.dot(tet.verts[3])))) + plane.d;
}
PX_INLINE PX_CUDA_CALLABLE PxReal testSeparatingAxis(const PxVec3& axis, const Tetrahedron& tet0, const Tetrahedron& tet1)
{
PxReal min0, max0, min1, max1;
min0 = max0 = tet0.verts[0].dot(axis);
min1 = max1 = tet1.verts[0].dot(axis);
for (PxU32 i = 1; i < 4; ++i)
{
PxReal proj0 = tet0.verts[i].dot(axis);
PxReal proj1 = tet1.verts[i].dot(axis);
min0 = PxMin(proj0, min0);
max0 = PxMax(proj0, max0);
min1 = PxMin(proj1, min1);
max1 = PxMax(proj1, max1);
}
return PxMax(min1 - max0, min0 - max1);
}
template <bool TDoCross = true>
PX_INLINE PX_CUDA_CALLABLE PxReal satIntersect(const Tetrahedron& tet0, const Tetrahedron& tet1, const PxReal tolerance)
{
PxReal sep = minProject(tet0.planes[0], tet1);
if (sep > tolerance)
return sep;
sep = PxMax(sep, minProject(tet0.planes[1], tet1));
if (sep > tolerance)
return sep;
sep = PxMax(sep, minProject(tet0.planes[2], tet1));
if (sep > tolerance)
return sep;
sep = PxMax(sep, minProject(tet0.planes[3], tet1));
if (sep > tolerance)
return sep;
sep = PxMax(sep, minProject(tet1.planes[0], tet0));
if (sep > tolerance)
return sep;
sep = PxMax(sep, minProject(tet1.planes[1], tet0));
if (sep > tolerance)
return sep;
sep = PxMax(sep, minProject(tet1.planes[2], tet0));
if (sep > tolerance)
return sep;
sep = PxMax(sep, minProject(tet1.planes[3], tet0));
if (sep > tolerance)
return sep;
if (TDoCross)
{
PxVec3 axes0[6];
PxVec3 axes1[6];
axes0[0] = tet0.verts[1] - tet0.verts[0];
axes0[1] = tet0.verts[2] - tet0.verts[0];
axes0[2] = tet0.verts[3] - tet0.verts[0];
axes0[3] = tet0.verts[2] - tet0.verts[1];
axes0[4] = tet0.verts[3] - tet0.verts[1];
axes0[5] = tet0.verts[3] - tet0.verts[2];
axes1[0] = tet1.verts[1] - tet1.verts[0];
axes1[1] = tet1.verts[2] - tet1.verts[0];
axes1[2] = tet1.verts[3] - tet1.verts[0];
axes1[3] = tet1.verts[2] - tet1.verts[1];
axes1[4] = tet1.verts[3] - tet1.verts[1];
axes1[5] = tet1.verts[3] - tet1.verts[2];
for (PxU32 i = 0; i < 6; ++i)
{
const PxVec3 axis0 = axes0[i];
for (PxU32 j = 0; j < 6; ++j)
{
const PxVec3 axis1 = axes1[j];
PxVec3 sepAxis = axis0.cross(axis1);
const PxReal magSq = sepAxis.magnitudeSquared();
if (magSq > 1e-5f)
{
sepAxis = sepAxis * (1.f / PxSqrt(magSq));
const PxReal tSep = testSeparatingAxis(sepAxis, tet0, tet1);
sep = PxMax(sep, tSep);
if (sep > tolerance)
return sep;
}
}
}
}
return sep;
}
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,89 @@
// 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 GU_INTERSECTION_TRIANGLE_BOX_H
#define GU_INTERSECTION_TRIANGLE_BOX_H
#include "foundation/PxMat33.h"
#include "common/PxPhysXCommonConfig.h"
namespace physx
{
namespace Gu
{
class Box;
class BoxPadded;
/**
Tests if a triangle overlaps a box (AABB). This is the reference non-SIMD code.
\param center [in] the box center
\param extents [in] the box extents
\param p0 [in] triangle's first point
\param p1 [in] triangle's second point
\param p2 [in] triangle's third point
\return true if triangle overlaps box
*/
PX_PHYSX_COMMON_API PxIntBool intersectTriangleBox_ReferenceCode(const PxVec3& center, const PxVec3& extents, const PxVec3& p0, const PxVec3& p1, const PxVec3& p2);
/**
Tests if a triangle overlaps a box (AABB). This is the optimized SIMD code.
WARNING: the function has various SIMD requirements, left to the calling code:
- function will load 4 bytes after 'center'. Make sure it's safe to load from there.
- function will load 4 bytes after 'extents'. Make sure it's safe to load from there.
- function will load 4 bytes after 'p0'. Make sure it's safe to load from there.
- function will load 4 bytes after 'p1'. Make sure it's safe to load from there.
- function will load 4 bytes after 'p2'. Make sure it's safe to load from there.
If you can't guarantee these requirements, please use the non-SIMD reference code instead.
\param center [in] the box center.
\param extents [in] the box extents
\param p0 [in] triangle's first point
\param p1 [in] triangle's second point
\param p2 [in] triangle's third point
\return true if triangle overlaps box
*/
PX_PHYSX_COMMON_API PxIntBool intersectTriangleBox_Unsafe(const PxVec3& center, const PxVec3& extents, const PxVec3& p0, const PxVec3& p1, const PxVec3& p2);
/**
Tests if a triangle overlaps a box (OBB).
There are currently no SIMD-related requirements for p0, p1, p2.
\param box [in] the box
\param p0 [in] triangle's first point
\param p1 [in] triangle's second point
\param p2 [in] triangle's third point
\return true if triangle overlaps box
*/
PX_PHYSX_COMMON_API PxIntBool intersectTriangleBox(const BoxPadded& box, const PxVec3& p0, const PxVec3& p1, const PxVec3& p2);
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,263 @@
// 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 GU_INTERSECTION_TRIANGLE_BOX_REF_H
#define GU_INTERSECTION_TRIANGLE_BOX_REF_H
#include "foundation/PxVec3.h"
/********************************************************/
/* AABB-triangle overlap test code */
/* by Tomas Akenine-M?r */
/* Function: int triBoxOverlap(float boxcenter[3], */
/* float boxhalfsize[3],float triverts[3][3]); */
/* History: */
/* 2001-03-05: released the code in its first version */
/* 2001-06-18: changed the order of the tests, faster */
/* */
/* Acknowledgement: Many thanks to Pierre Terdiman for */
/* suggestions and discussions on how to optimize code. */
/* Thanks to David Hunt for finding a ">="-bug! */
/********************************************************/
namespace physx
{
#define CROSS(dest,v1,v2) \
dest.x=v1.y*v2.z-v1.z*v2.y; \
dest.y=v1.z*v2.x-v1.x*v2.z; \
dest.z=v1.x*v2.y-v1.y*v2.x;
#define DOT(v1,v2) (v1.x*v2.x+v1.y*v2.y+v1.z*v2.z)
#define FINDMINMAX(x0, x1, x2, minimum, maximum) \
minimum = physx::intrinsics::selectMin(x0, x1); \
maximum = physx::intrinsics::selectMax(x0, x1); \
minimum = physx::intrinsics::selectMin(minimum, x2); \
maximum = physx::intrinsics::selectMax(maximum, x2);
static PX_CUDA_CALLABLE PX_FORCE_INLINE PxIntBool planeBoxOverlap(const PxVec3& normal, PxReal d, const PxVec3& maxbox)
{
PxVec3 vmin, vmax;
if (normal.x>0.0f)
{
vmin.x = -maxbox.x;
vmax.x = maxbox.x;
}
else
{
vmin.x = maxbox.x;
vmax.x = -maxbox.x;
}
if (normal.y>0.0f)
{
vmin.y = -maxbox.y;
vmax.y = maxbox.y;
}
else
{
vmin.y = maxbox.y;
vmax.y = -maxbox.y;
}
if (normal.z>0.0f)
{
vmin.z = -maxbox.z;
vmax.z = maxbox.z;
}
else
{
vmin.z = maxbox.z;
vmax.z = -maxbox.z;
}
if(normal.dot(vmin) + d > 0.0f)
return PxIntFalse;
if(normal.dot(vmax) + d >= 0.0f)
return PxIntTrue;
return PxIntFalse;
}
/*======================== X-tests ========================*/
#define AXISTEST_X01(a, b, fa, fb) \
p0 = a*v0.y - b*v0.z; \
p2 = a*v2.y - b*v2.z; \
minimum = physx::intrinsics::selectMin(p0, p2); \
maximum = physx::intrinsics::selectMax(p0, p2); \
rad = fa * extents.y + fb * extents.z; \
if(minimum>rad || maximum<-rad) return PxIntFalse;
#define AXISTEST_X2(a, b, fa, fb) \
p0 = a*v0.y - b*v0.z; \
p1 = a*v1.y - b*v1.z; \
minimum = physx::intrinsics::selectMin(p0, p1); \
maximum = physx::intrinsics::selectMax(p0, p1); \
rad = fa * extents.y + fb * extents.z; \
if(minimum>rad || maximum<-rad) return PxIntFalse;
/*======================== Y-tests ========================*/
#define AXISTEST_Y02(a, b, fa, fb) \
p0 = -a*v0.x + b*v0.z; \
p2 = -a*v2.x + b*v2.z; \
minimum = physx::intrinsics::selectMin(p0, p2); \
maximum = physx::intrinsics::selectMax(p0, p2); \
rad = fa * extents.x + fb * extents.z; \
if(minimum>rad || maximum<-rad) return PxIntFalse;
#define AXISTEST_Y1(a, b, fa, fb) \
p0 = -a*v0.x + b*v0.z; \
p1 = -a*v1.x + b*v1.z; \
minimum = physx::intrinsics::selectMin(p0, p1); \
maximum = physx::intrinsics::selectMax(p0, p1); \
rad = fa * extents.x + fb * extents.z; \
if(minimum>rad || maximum<-rad) return PxIntFalse;
/*======================== Z-tests ========================*/
#define AXISTEST_Z12(a, b, fa, fb) \
p1 = a*v1.x - b*v1.y; \
p2 = a*v2.x - b*v2.y; \
minimum = physx::intrinsics::selectMin(p1, p2); \
maximum = physx::intrinsics::selectMax(p1, p2); \
rad = fa * extents.x + fb * extents.y; \
if(minimum>rad || maximum<-rad) return PxIntFalse;
#define AXISTEST_Z0(a, b, fa, fb) \
p0 = a*v0.x - b*v0.y; \
p1 = a*v1.x - b*v1.y; \
minimum = physx::intrinsics::selectMin(p0, p1); \
maximum = physx::intrinsics::selectMax(p0, p1); \
rad = fa * extents.x + fb * extents.y; \
if(minimum>rad || maximum<-rad) return PxIntFalse;
namespace Gu
{
template <const bool bDoVertexChecks = false>
static PX_CUDA_CALLABLE PX_FORCE_INLINE PxIntBool intersectTriangleBox_RefImpl(const PxVec3& boxcenter, const PxVec3& extents, const PxVec3& tp0, const PxVec3& tp1, const PxVec3& tp2)
{
/* use separating axis theorem to test overlap between triangle and box */
/* need to test for overlap in these directions: */
/* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
/* we do not even need to test these) */
/* 2) normal of the triangle */
/* 3) crossproduct(edge from tri, {x,y,z}-directin) */
/* this gives 3x3=9 more tests */
// This is the fastest branch on Sun - move everything so that the boxcenter is in (0,0,0)
const PxVec3 v0 = tp0 - boxcenter;
const PxVec3 v1 = tp1 - boxcenter;
const PxVec3 v2 = tp2 - boxcenter;
if (bDoVertexChecks)
{
if (PxAbs(v0.x) <= extents.x && PxAbs(v0.y) <= extents.y && PxAbs(v0.z) <= extents.z)
return PxIntTrue;
if (PxAbs(v1.x) <= extents.x && PxAbs(v1.y) <= extents.y && PxAbs(v1.z) <= extents.z)
return PxIntTrue;
if (PxAbs(v2.x) <= extents.x && PxAbs(v2.y) <= extents.y && PxAbs(v2.z) <= extents.z)
return PxIntTrue;
}
// compute triangle edges
const PxVec3 e0 = v1 - v0; // tri edge 0
const PxVec3 e1 = v2 - v1; // tri edge 1
const PxVec3 e2 = v0 - v2; // tri edge 2
float minimum, maximum, rad, p0, p1, p2;
// Bullet 3: test the 9 tests first (this was faster)
float fex = PxAbs(e0.x);
float fey = PxAbs(e0.y);
float fez = PxAbs(e0.z);
AXISTEST_X01(e0.z, e0.y, fez, fey);
AXISTEST_Y02(e0.z, e0.x, fez, fex);
AXISTEST_Z12(e0.y, e0.x, fey, fex);
fex = PxAbs(e1.x);
fey = PxAbs(e1.y);
fez = PxAbs(e1.z);
AXISTEST_X01(e1.z, e1.y, fez, fey);
AXISTEST_Y02(e1.z, e1.x, fez, fex);
AXISTEST_Z0(e1.y, e1.x, fey, fex);
fex = PxAbs(e2.x);
fey = PxAbs(e2.y);
fez = PxAbs(e2.z);
AXISTEST_X2(e2.z, e2.y, fez, fey);
AXISTEST_Y1(e2.z, e2.x, fez, fex);
AXISTEST_Z12(e2.y, e2.x, fey, fex);
// Bullet 1:
// first test overlap in the {x,y,z}-directions
// find minimum, maximum of the triangle each direction, and test for overlap in
// that direction -- this is equivalent to testing a minimal AABB around
// the triangle against the AABB
// test in X-direction
FINDMINMAX(v0.x, v1.x, v2.x, minimum, maximum);
if(minimum>extents.x || maximum<-extents.x)
return PxIntFalse;
// test in Y-direction
FINDMINMAX(v0.y, v1.y, v2.y, minimum, maximum);
if(minimum>extents.y || maximum<-extents.y)
return PxIntFalse;
// test in Z-direction
FINDMINMAX(v0.z, v1.z, v2.z, minimum, maximum);
if(minimum>extents.z || maximum<-extents.z)
return PxIntFalse;
// Bullet 2:
// test if the box intersects the plane of the triangle
// compute plane equation of triangle: normal*x+d=0
PxVec3 normal;
CROSS(normal, e0, e1);
const float d = -DOT(normal, v0); // plane eq: normal.x+d=0
if(!planeBoxOverlap(normal, d, extents))
return PxIntFalse;
return PxIntTrue; // box and triangle overlaps
}
}
#undef CROSS
#undef DOT
#undef FINDMINMAX
#undef AXISTEST_X01
#undef AXISTEST_X2
#undef AXISTEST_Y02
#undef AXISTEST_Y1
#undef AXISTEST_Z12
#undef AXISTEST_Z0
}
#endif

View File

@@ -0,0 +1,57 @@
// 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 GU_INTERSECTION_TRIANGLE_TRIANGLE_H
#define GU_INTERSECTION_TRIANGLE_TRIANGLE_H
#include "GuSegment.h"
#include "common/PxPhysXCommonConfig.h"
namespace physx
{
namespace Gu
{
/**
Tests if a two triangles intersect
\param a1 [in] Fist point of the first triangle
\param b1 [in] Second point of the first triangle
\param c1 [in] Third point of the first triangle
\param a2 [in] Fist point of the second triangle
\param b2 [in] Second point of the second triangle
\param c2 [in] Third point of the second triangle
\param ignoreCoplanar [in] True to filter out coplanar triangles
\return true if triangles intersect
*/
PX_PHYSX_COMMON_API bool intersectTriangleTriangle( const PxVec3& a1, const PxVec3& b1, const PxVec3& c1,
const PxVec3& a2, const PxVec3& b2, const PxVec3& c2,
bool ignoreCoplanar = false);
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,115 @@
// 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 GU_OVERLAP_TESTS_H
#define GU_OVERLAP_TESTS_H
#include "foundation/PxVec3.h"
#include "foundation/PxTransform.h"
#include "foundation/PxAssert.h"
#include "foundation/PxErrors.h"
#include "foundation/PxFoundation.h"
#include "geometry/PxGeometry.h"
#include "geometry/PxGeometryHit.h"
#include "geometry/PxGeometryQueryContext.h"
namespace physx
{
namespace Gu
{
class Capsule;
class Sphere;
// PT: this is just a shadow of what it used to be. We currently don't use TRIGGER_INSIDE anymore, but I leave it for now,
// since I really want to put this back the way it was before.
enum TriggerStatus
{
TRIGGER_DISJOINT,
TRIGGER_INSIDE,
TRIGGER_OVERLAP
};
// PT: currently only used for convex triggers
struct TriggerCache
{
PxVec3 dir;
PxU16 state;
PxU16 gjkState; //gjk succeed or fail
};
#define UNUSED_OVERLAP_THREAD_CONTEXT NULL
// PT: we use a define to be able to quickly change the signature of all overlap functions.
// (this also ensures they all use consistent names for passed parameters).
// \param[in] geom0 first geometry object
// \param[in] pose0 pose of first geometry object
// \param[in] geom1 second geometry object
// \param[in] pose1 pose of second geometry object
// \param[in] cache optional cached data for triggers
// \param[in] threadContext optional per-thread context
#define GU_OVERLAP_FUNC_PARAMS const PxGeometry& geom0, const PxTransform& pose0, \
const PxGeometry& geom1, const PxTransform& pose1, \
Gu::TriggerCache* cache, PxOverlapThreadContext* threadContext
// PT: function pointer for Geom-indexed overlap functions
// See GU_OVERLAP_FUNC_PARAMS for function parameters details.
// \return true if an overlap was found, false otherwise
typedef bool (*GeomOverlapFunc) (GU_OVERLAP_FUNC_PARAMS);
// PT: typedef for a bundle of all overlap functions, i.e. the function table itself (indexed by geom-type).
typedef GeomOverlapFunc GeomOverlapTable[PxGeometryType::eGEOMETRY_COUNT];
// PT: retrieves the overlap function table (for access by external non-Gu modules)
PX_PHYSX_COMMON_API const GeomOverlapTable* getOverlapFuncTable();
PX_FORCE_INLINE bool overlap( const PxGeometry& geom0, const PxTransform& pose0,
const PxGeometry& geom1, const PxTransform& pose1,
const GeomOverlapTable* PX_RESTRICT overlapFuncs, PxOverlapThreadContext* threadContext)
{
PX_CHECK_AND_RETURN_VAL(pose0.isValid(), "Gu::overlap(): pose0 is not valid.", false);
PX_CHECK_AND_RETURN_VAL(pose1.isValid(), "Gu::overlap(): pose1 is not valid.", false);
if(geom0.getType() > geom1.getType())
{
GeomOverlapFunc overlapFunc = overlapFuncs[geom1.getType()][geom0.getType()];
PX_ASSERT(overlapFunc);
return overlapFunc(geom1, pose1, geom0, pose0, NULL, threadContext);
}
else
{
GeomOverlapFunc overlapFunc = overlapFuncs[geom0.getType()][geom1.getType()];
PX_ASSERT(overlapFunc);
return overlapFunc(geom0, pose0, geom1, pose1, NULL, threadContext);
}
}
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,227 @@
// 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 GU_PRUNER_H
#define GU_PRUNER_H
#include "foundation/PxUserAllocated.h"
#include "foundation/PxTransform.h"
#include "GuPrunerPayload.h"
#include "GuPrunerTypedef.h"
namespace physx
{
class PxRenderOutput;
class PxBounds3;
namespace Gu
{
class ShapeData;
struct PrunerRaycastCallback
{
PrunerRaycastCallback() {}
virtual ~PrunerRaycastCallback() {}
virtual bool invoke(PxReal& distance, PxU32 primIndex, const PrunerPayload* payloads, const PxTransform* transforms) = 0;
};
struct PrunerOverlapCallback
{
PrunerOverlapCallback() {}
virtual ~PrunerOverlapCallback() {}
virtual bool invoke(PxU32 primIndex, const PrunerPayload* payloads, const PxTransform* transforms) = 0;
};
class BasePruner : public PxUserAllocated
{
public:
BasePruner() {}
virtual ~BasePruner() {}
// shift the origin of the pruner objects
virtual void shiftOrigin(const PxVec3& shift) = 0;
// additional 'internal' interface
virtual void visualize(PxRenderOutput&, PxU32, PxU32) const {}
};
class Pruner : public BasePruner
{
public:
Pruner() {}
virtual ~Pruner() {}
/**
\brief Adds objects to the pruner.
\param[out] results Returned handles for added objects
\param[in] bounds Bounds of added objects. These bounds are used as-is so they should be pre-inflated if inflation is needed.
\param[in] data Payloads for added objects.
\param[in] transforms Transforms of added objects.
\param[in] count Number of objects in the arrays
\param[in] hasPruningStructure True if added objects have pruning structure. The structure will be merged later, adding the objects will not invalidate the pruner.
\return true if success, false if internal allocation failed. The first failing add results in a INVALID_PRUNERHANDLE.
\see PxPruningStructure
*/
virtual bool addObjects(PrunerHandle* results, const PxBounds3* bounds, const PrunerPayload* data, const PxTransform* transforms, PxU32 count, bool hasPruningStructure) = 0;
/**
\brief Removes objects from the pruner.
\param[in] handles The objects to remove
\param[in] count The number of objects to remove
\param[in] removalCallback Optional callback, called for each removed object (giving access to its payload for keeping external structures in sync)
*/
virtual void removeObjects(const PrunerHandle* handles, PxU32 count, PrunerPayloadRemovalCallback* removalCallback) = 0;
/**
\brief Updates objects with new bounds & transforms.
There are two ways to use this function:
1) manual bounds update: you can manually update the bounds via "getPayloadData" calls prior to calling "updateObjects".
In this case "updateObjects" only notifies the system that the data for these objects has changed. In this mode the
"inflation", "boundsIndices", "newBounds" and "newTransforms" parameters should remain null.
2) synchronization mode: in this case the new bounds (and optionally the new transforms) have been computed by an
external source and "updateObjects" tells the system to update its data from passed buffers. The new bounds are
always inflated by the "inflation" parameter while being copied. "boundsIndices" is an optional remap table, allowing
this call to only update a subset of the existing bounds (i.e. the updated bounds don't have to be first copied to a
separate contiguous buffer).
\param[in] handles The objects to update
\param[in] count The number of objects to update
\param[in] inflation Bounds inflation value
\param[in] boundsIndices The indices of the bounds in the bounds array (or NULL)
\param[in] newBounds Updated bounds array (or NULL)
\param[in] newTransforms Updated transforms array (or NULL)
*/
virtual void updateObjects(const PrunerHandle* handles, PxU32 count, float inflation=0.0f, const PxU32* boundsIndices=NULL, const PxBounds3* newBounds=NULL, const PxTransform32* newTransforms=NULL) = 0;
/**
\brief Gets rid of internal accel struct.
*/
virtual void purge() = 0;
/**
\brief Makes the queries consistent with previous changes.
This function must be called before starting queries on an updated Pruner and assert otherwise.
*/
virtual void commit() = 0;
/**
\brief Merges pruning structure to current pruner, parameters may differ for each pruner implementation.
\param[in] mergeParams Implementation-dependent merge data
*/
virtual void merge(const void* mergeParams) = 0;
/**
* Query functions
*
* Note: return value may disappear if PrunerCallback contains the necessary information
* currently it is still used for the dynamic pruner internally (to decide if added objects must be queried)
*/
virtual bool raycast(const PxVec3& origin, const PxVec3& unitDir, PxReal& inOutDistance, PrunerRaycastCallback&) const = 0;
virtual bool overlap(const Gu::ShapeData& queryVolume, PrunerOverlapCallback&) const = 0;
virtual bool sweep(const Gu::ShapeData& queryVolume, const PxVec3& unitDir, PxReal& inOutDistance, PrunerRaycastCallback&) const = 0;
/**
\brief Retrieves the object's payload and data associated with the handle.
This function returns the payload associated with a given handle. Additionally it can return the
destination addresses for the object's bounds & transform. The user can then write the new bounds
and transform there, before eventually calling updateObjects().
\param[in] handle Object handle (initially returned by addObjects())
\param[out] data Optional location where to store the internal data associated with the payload.
\return The payload associated with the given handle.
*/
virtual const PrunerPayload& getPayloadData(PrunerHandle handle, PrunerPayloadData* data=NULL) const = 0;
/**
\brief Preallocate space
\param[in] nbEntries The number of entries to preallocate space for
*/
virtual void preallocate(PxU32 nbEntries) = 0;
/**
\brief Sets object's transform
\note This is equivalent to retrieving the transform's address with "getPayloadData" and writing
the transform there.
\param[in] handle Object handle (initially returned by addObjects())
\param[in] transform New transform
\return True if success
*/
virtual bool setTransform(PrunerHandle handle, const PxTransform& transform) = 0;
// PT: from the SQ branch, maybe temporary, unclear if a getType() function would be better etc
virtual bool isDynamic() const { return false; }
virtual void getGlobalBounds(PxBounds3&) const = 0;
};
/**
* Pruner building accel structure over time base class
*/
class DynamicPruner : public Pruner
{
public:
/**
* sets the rebuild hint rate used for step building the accel structure.
*/
virtual void setRebuildRateHint(PxU32 nbStepsForRebuild) = 0;
/**
* Steps the accel structure build.
* synchronousCall specifies if initialization can happen. It should not initialize build when called from a different thread
* returns true if finished
*/
virtual bool buildStep(bool synchronousCall = true) = 0;
/**
* Prepares new tree build
* returns true if new tree is needed
*/
virtual bool prepareBuild() = 0;
};
}
}
#endif

View File

@@ -0,0 +1,63 @@
// 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 GU_PRUNER_MERGE_DATA_H
#define GU_PRUNER_MERGE_DATA_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
namespace Gu
{
struct BVHNode;
// PT: TODO: refactor with BVHCoreData ?
struct AABBPrunerMergeData
{
AABBPrunerMergeData()
{
// PT: it's important to NOT initialize anything by default (for binary serialization)
}
PxU32 mNbNodes; // Nb nodes in AABB tree
BVHNode* mAABBTreeNodes; // AABB tree runtime nodes
PxU32 mNbObjects; // Nb objects in AABB tree
PxU32* mAABBTreeIndices; // AABB tree indices
void init(PxU32 nbNodes=0, BVHNode* nodes=NULL, PxU32 nbObjects=0, PxU32* indices=NULL)
{
mNbNodes = nbNodes;
mAABBTreeNodes = nodes;
mNbObjects = nbObjects;
mAABBTreeIndices = indices;
}
};
}
}
#endif

View File

@@ -0,0 +1,72 @@
// 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 GU_PRUNER_PAYLOAD_H
#define GU_PRUNER_PAYLOAD_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxTransform.h"
namespace physx
{
class PxBounds3;
namespace Gu
{
// PT: anonymous payload structure used by the pruners. This is similar in spirit to a userData pointer.
struct PrunerPayload
{
size_t data[2]; // Enough space for two arbitrary pointers
PX_FORCE_INLINE bool operator == (const PrunerPayload& other) const
{
return (data[0] == other.data[0]) && (data[1] == other.data[1]);
}
};
// PT: pointers to internal data associated with a pruner payload. The lifetime of these pointers
// is usually limited and they should be used immediately after retrieval.
struct PrunerPayloadData
{
PxBounds3* mBounds; // Pointer to internal bounds.
PxTransform* mTransform; // Pointer to internal transform, or NULL.
};
// PT: called for each removed payload. Gives users a chance to cleanup their data
// structures without duplicating the pruner-data to payload mapping on their side.
struct PrunerPayloadRemovalCallback
{
PrunerPayloadRemovalCallback() {}
virtual ~PrunerPayloadRemovalCallback() {}
virtual void invoke(PxU32 nbRemoved, const PrunerPayload* removed) = 0;
};
}
}
#endif

View File

@@ -0,0 +1,64 @@
// 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 GU_PRUNER_TYPEDEF_H
#define GU_PRUNER_TYPEDEF_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
namespace Gu
{
typedef PxU32 PrunerHandle;
static const PrunerHandle INVALID_PRUNERHANDLE = 0xffffffff;
typedef PxU32 PoolIndex;
static const PxU32 INVALID_POOL_ID = 0xffffffff;
typedef PxU32 TreeNodeIndex;
static const PxU32 INVALID_NODE_ID = 0xffffffff;
enum CompanionPrunerType
{
COMPANION_PRUNER_NONE,
COMPANION_PRUNER_BUCKET,
COMPANION_PRUNER_INCREMENTAL,
COMPANION_PRUNER_AABB_TREE
};
enum BVHBuildStrategy
{
BVH_SPLATTER_POINTS,
BVH_SPLATTER_POINTS_SPLIT_GEOM_CENTER,
BVH_SAH
};
}
}
#endif

View File

@@ -0,0 +1,463 @@
// 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 GU_QUERY_SYSTEM_H
#define GU_QUERY_SYSTEM_H
#include "foundation/PxUserAllocated.h"
#include "foundation/PxBitMap.h"
#include "foundation/PxArray.h"
#include "foundation/PxMutex.h"
#include "foundation/PxBounds3.h"
#include "GuPruner.h"
#include "GuActorShapeMap.h"
namespace physx
{
class PxGeometry;
namespace Gu
{
class BVH;
class Adapter
{
public:
Adapter() {}
virtual ~Adapter() {}
virtual const PxGeometry& getGeometry(const PrunerPayload& payload) const = 0;
};
class PrunerFilter
{
public:
PrunerFilter() {}
virtual ~PrunerFilter() {}
virtual bool processPruner(PxU32 prunerIndex/*, const PxQueryThreadContext* context*/) const = 0;
};
typedef PxU32 PrunerInfo;
PX_FORCE_INLINE PrunerInfo createPrunerInfo(PxU32 prunerIndex, bool isDynamic) { return (prunerIndex << 1) | PxU32(isDynamic); }
PX_FORCE_INLINE PxU32 getPrunerIndex(PrunerInfo info) { return PxU32(info)>>1; }
PX_FORCE_INLINE PxU32 getDynamic(PrunerInfo info) { return PxU32(info) & 1; }
PX_FORCE_INLINE ActorShapeData createActorShapeData(PrunerInfo info, PrunerHandle h) { return (ActorShapeData(h) << 32) | ActorShapeData(info); }
PX_FORCE_INLINE PrunerInfo getPrunerInfo(ActorShapeData data) { return PrunerInfo(data); }
PX_FORCE_INLINE PrunerHandle getPrunerHandle(ActorShapeData data) { return PrunerHandle(data >> 32); }
#define INVALID_ACTOR_SHAPE_DATA PxU64(-1)
class QuerySystem : public PxUserAllocated
{
public: // PT: TODO: public only to implement checkPrunerIndex easily, revisit this
struct PrunerExt : public PxUserAllocated
{
PrunerExt(Pruner* pruner, PxU32 preallocated);
~PrunerExt();
void flushMemory();
void addToDirtyList(PrunerHandle handle, PxU32 dynamic, const PxTransform& transform, const PxBounds3* userBounds=NULL);
void removeFromDirtyList(PrunerHandle handle);
bool processDirtyList(const Adapter& adapter, float inflation);
Pruner* mPruner;
PxBitMap mDirtyMap;
PxArray<PrunerHandle> mDirtyList;
PxU32 mNbStatic; // nb static objects in pruner
PxU32 mNbDynamic; // nb dynamic objects in pruner
bool mDirtyStatic; // true if dirty list contains a static
struct Data
{
PxTransform mPose;
PxBounds3 mBounds;
};
PxArray<Data> mDirtyData;
PX_NOCOPY(PrunerExt)
};
public:
PX_PHYSX_COMMON_API QuerySystem(PxU64 contextID, float inflation, const Adapter& adapter, bool usesTreeOfPruners=false);
PX_PHYSX_COMMON_API ~QuerySystem();
PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; }
PX_FORCE_INLINE const Adapter& getAdapter() const { return mAdapter; }
PX_FORCE_INLINE PxU32 getStaticTimestamp() const { return mStaticTimestamp; }
PX_PHYSX_COMMON_API PxU32 addPruner(Pruner* pruner, PxU32 preallocated);
PX_PHYSX_COMMON_API void removePruner(PxU32 prunerIndex);
PX_FORCE_INLINE PxU32 getNbPruners() const { return mPrunerExt.size(); }
PX_FORCE_INLINE const Pruner* getPruner(PxU32 index) const { return mPrunerExt[index]->mPruner; }
PX_FORCE_INLINE Pruner* getPruner(PxU32 index) { return mPrunerExt[index]->mPruner; }
PX_PHYSX_COMMON_API ActorShapeData addPrunerShape(const PrunerPayload& payload, PxU32 prunerIndex, bool dynamic, const PxTransform& transform, const PxBounds3* userBounds=NULL);
PX_PHYSX_COMMON_API void removePrunerShape(ActorShapeData data, PrunerPayloadRemovalCallback* removalCallback);
PX_PHYSX_COMMON_API void updatePrunerShape(ActorShapeData data, bool immediately, const PxTransform& transform, const PxBounds3* userBounds=NULL);
PX_PHYSX_COMMON_API const PrunerPayload& getPayloadData(ActorShapeData data, PrunerPayloadData* ppd=NULL) const;
PX_PHYSX_COMMON_API void commitUpdates();
PX_PHYSX_COMMON_API void update(bool buildStep, bool commit);
PX_PHYSX_COMMON_API void sync(PxU32 prunerIndex, const PrunerHandle* handles, const PxU32* boundsIndices, const PxBounds3* bounds, const PxTransform32* transforms, PxU32 count);
PX_PHYSX_COMMON_API void flushMemory();
PX_PHYSX_COMMON_API void raycast(const PxVec3& origin, const PxVec3& unitDir, float& inOutDistance, PrunerRaycastCallback& cb, const PrunerFilter* prunerFilter) const;
PX_PHYSX_COMMON_API void overlap(const ShapeData& queryVolume, PrunerOverlapCallback& cb, const PrunerFilter* prunerFilter) const;
PX_PHYSX_COMMON_API void sweep(const ShapeData& queryVolume, const PxVec3& unitDir, float& inOutDistance, PrunerRaycastCallback& cb, const PrunerFilter* prunerFilter) const;
PxU32 startCustomBuildstep();
void customBuildstep(PxU32 index);
void finishCustomBuildstep();
void createTreeOfPruners();
private:
const Adapter& mAdapter;
PxArray<PrunerExt*> mPrunerExt;
PxArray<PxU32> mDirtyPruners;
PxArray<PxU32> mFreePruners;
Gu::BVH* mTreeOfPruners;
const PxU64 mContextID;
PxU32 mStaticTimestamp;
const float mInflation; // SQ_PRUNER_EPSILON
PxMutex mSQLock; // to make sure only one query updates the dirty pruner structure if multiple queries run in parallel
volatile bool mPrunerNeedsUpdating;
volatile bool mTimestampNeedsUpdating;
const bool mUsesTreeOfPruners;
void processDirtyLists();
PX_FORCE_INLINE void invalidateStaticTimestamp() { mStaticTimestamp++; }
PX_NOCOPY(QuerySystem)
};
}
}
#include "geometry/PxGeometryHit.h"
#include "geometry/PxSphereGeometry.h"
#include "geometry/PxCapsuleGeometry.h"
#include "geometry/PxBoxGeometry.h"
#include "geometry/PxConvexMeshGeometry.h"
#include "GuCachedFuncs.h"
#include "GuCapsule.h"
#include "GuBounds.h"
#if PX_VC
#pragma warning(disable: 4355 ) // "this" used in base member initializer list
#endif
namespace physx
{
namespace Gu
{
// PT: TODO: use templates instead of v-calls?
// PT: we decouple the filter callback from the rest, so that the same filter callback can easily be reused for all pruner queries.
// This combines the pre-filter callback and fetching the payload's geometry in a single call. Return null to ignore that object.
struct PrunerFilterCallback
{
virtual ~PrunerFilterCallback() {}
// Query's hit flags can be tweaked per object. (Note that 'hitFlags' is unused for overlaps though)
virtual const PxGeometry* validatePayload(const PrunerPayload& payload, PxHitFlags& hitFlags) = 0;
};
struct DefaultPrunerRaycastCallback : public PrunerRaycastCallback, public PxRaycastThreadContext
{
PxRaycastThreadContext* mContext;
PrunerFilterCallback& mFilterCB;
const GeomRaycastTable& mCachedRaycastFuncs;
const PxVec3& mOrigin;
const PxVec3& mDir;
PxGeomRaycastHit* mLocalHits;
const PxU32 mMaxLocalHits;
const PxHitFlags mHitFlags;
PxGeomRaycastHit mClosestHit;
PrunerPayload mClosestPayload;
bool mFoundHit;
const bool mAnyHit;
DefaultPrunerRaycastCallback(PrunerFilterCallback& filterCB, const GeomRaycastTable& funcs, const PxVec3& origin, const PxVec3& dir, float distance, PxU32 maxLocalHits, PxGeomRaycastHit* localHits, PxHitFlags hitFlags, bool anyHit, PxRaycastThreadContext* context=NULL) :
mContext (context ? context : this),
mFilterCB (filterCB),
mCachedRaycastFuncs (funcs),
mOrigin (origin),
mDir (dir),
mLocalHits (localHits),
mMaxLocalHits (maxLocalHits),
mHitFlags (hitFlags),
mFoundHit (false),
mAnyHit (anyHit)
{
mClosestHit.distance = distance;
}
virtual bool reportHits(const PrunerPayload& /*payload*/, PxU32 /*nbHits*/, PxGeomRaycastHit* /*hits*/)
{
return true;
}
virtual bool invoke(PxReal& aDist, PxU32 primIndex, const PrunerPayload* payloads, const PxTransform* transforms) PX_OVERRIDE PX_FINAL
{
PX_ASSERT(payloads && transforms);
const PrunerPayload& payload = payloads[primIndex];
PxHitFlags filteredHitFlags = mHitFlags;
const PxGeometry* shapeGeom = mFilterCB.validatePayload(payload, filteredHitFlags);
if(!shapeGeom)
return true;
const RaycastFunc func = mCachedRaycastFuncs[shapeGeom->getType()];
const PxU32 nbHits = func(*shapeGeom, transforms[primIndex], mOrigin, mDir, aDist, filteredHitFlags, mMaxLocalHits, mLocalHits, sizeof(PxGeomRaycastHit), mContext);
if(!nbHits || !reportHits(payload, nbHits, mLocalHits))
return true;
const PxGeomRaycastHit& localHit = mLocalHits[0];
if(localHit.distance < mClosestHit.distance)
{
mFoundHit = true;
if(mAnyHit)
return false;
aDist = localHit.distance;
mClosestHit = localHit;
mClosestPayload = payload;
}
return true;
}
PX_NOCOPY(DefaultPrunerRaycastCallback)
};
struct DefaultPrunerRaycastAnyCallback : public DefaultPrunerRaycastCallback
{
PxGeomRaycastHit mLocalHit;
DefaultPrunerRaycastAnyCallback(PrunerFilterCallback& filterCB, const GeomRaycastTable& funcs, const PxVec3& origin, const PxVec3& dir, float distance) :
DefaultPrunerRaycastCallback (filterCB, funcs, origin, dir, distance, 1, &mLocalHit, PxHitFlag::eANY_HIT, true) {}
};
struct DefaultPrunerRaycastClosestCallback : public DefaultPrunerRaycastCallback
{
PxGeomRaycastHit mLocalHit;
DefaultPrunerRaycastClosestCallback(PrunerFilterCallback& filterCB, const GeomRaycastTable& funcs, const PxVec3& origin, const PxVec3& dir, float distance, PxHitFlags hitFlags) :
DefaultPrunerRaycastCallback (filterCB, funcs, origin, dir, distance, 1, &mLocalHit, hitFlags, false) {}
};
struct DefaultPrunerOverlapCallback : public PrunerOverlapCallback, public PxOverlapThreadContext
{
PxOverlapThreadContext* mContext;
PrunerFilterCallback& mFilterCB;
const GeomOverlapTable* mCachedFuncs;
const PxGeometry& mGeometry;
const PxTransform& mPose;
PxHitFlags mUnused;
DefaultPrunerOverlapCallback(PrunerFilterCallback& filterCB, const GeomOverlapTable* funcs, const PxGeometry& geometry, const PxTransform& pose, PxOverlapThreadContext* context=NULL) :
mContext (context ? context : this),
mFilterCB (filterCB),
mCachedFuncs (funcs),
mGeometry (geometry),
mPose (pose)
{
}
virtual bool reportHit(const PrunerPayload& /*payload*/)
{
return true;
}
virtual bool invoke(PxU32 primIndex, const PrunerPayload* payloads, const PxTransform* transforms) PX_OVERRIDE PX_FINAL
{
PX_ASSERT(payloads && transforms);
const PrunerPayload& payload = payloads[primIndex];
const PxGeometry* shapeGeom = mFilterCB.validatePayload(payload, mUnused);
if(!shapeGeom || !Gu::overlap(mGeometry, mPose, *shapeGeom, transforms[primIndex], mCachedFuncs, mContext))
return true;
return reportHit(payload);
}
PX_NOCOPY(DefaultPrunerOverlapCallback)
};
struct BoxShapeCast
{
static PX_FORCE_INLINE PxU32 sweep( const GeomSweepFuncs& sf, const PxGeometry& geom, const PxTransform& pose,
const PxGeometry& queryGeom, const PxTransform& queryPose, const ShapeData& queryVolume,
const PxVec3& unitDir, PxReal distance, PxGeomSweepHit& sweepHit, PxHitFlags hitFlags, PxReal inflation, PxSweepThreadContext* context)
{
PX_ASSERT(queryGeom.getType()==PxGeometryType::eBOX);
const bool precise = hitFlags & PxHitFlag::ePRECISE_SWEEP;
const SweepBoxFunc func = precise ? sf.preciseBoxMap[geom.getType()] : sf.boxMap[geom.getType()];
return PxU32(func(geom, pose, static_cast<const PxBoxGeometry&>(queryGeom), queryPose, queryVolume.getGuBox(), unitDir, distance, sweepHit, hitFlags, inflation, context));
}
};
struct SphereShapeCast
{
static PX_FORCE_INLINE PxU32 sweep( const GeomSweepFuncs& sf, const PxGeometry& geom, const PxTransform& pose,
const PxGeometry& queryGeom, const PxTransform& queryPose, const ShapeData& /*queryVolume*/,
const PxVec3& unitDir, PxReal distance, PxGeomSweepHit& sweepHit, PxHitFlags hitFlags, PxReal inflation, PxSweepThreadContext* context)
{
PX_ASSERT(queryGeom.getType()==PxGeometryType::eSPHERE);
// PT: we don't use sd.getGuSphere() here because PhysX doesn't expose a set of 'SweepSphereFunc' functions,
// we have to go through a capsule (which is then seen as a sphere internally when the half-length is zero).
const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(queryGeom);
const PxCapsuleGeometry capsuleGeom(sphereGeom.radius, 0.0f);
const Capsule worldCapsule(queryPose.p, queryPose.p, sphereGeom.radius); // AP: precompute?
const bool precise = hitFlags & PxHitFlag::ePRECISE_SWEEP;
const SweepCapsuleFunc func = precise ? sf.preciseCapsuleMap[geom.getType()] : sf.capsuleMap[geom.getType()];
return PxU32(func(geom, pose, capsuleGeom, queryPose, worldCapsule, unitDir, distance, sweepHit, hitFlags, inflation, context));
}
};
struct CapsuleShapeCast
{
static PX_FORCE_INLINE PxU32 sweep( const GeomSweepFuncs& sf, const PxGeometry& geom, const PxTransform& pose,
const PxGeometry& queryGeom, const PxTransform& queryPose, const ShapeData& queryVolume,
const PxVec3& unitDir, PxReal distance, PxGeomSweepHit& sweepHit, PxHitFlags hitFlags, PxReal inflation, PxSweepThreadContext* context)
{
PX_ASSERT(queryGeom.getType()==PxGeometryType::eCAPSULE);
const bool precise = hitFlags & PxHitFlag::ePRECISE_SWEEP;
const SweepCapsuleFunc func = precise ? sf.preciseCapsuleMap[geom.getType()] : sf.capsuleMap[geom.getType()];
return PxU32(func(geom, pose, static_cast<const PxCapsuleGeometry&>(queryGeom), queryPose, queryVolume.getGuCapsule(), unitDir, distance, sweepHit, hitFlags, inflation, context));
}
};
struct ConvexShapeCast
{
static PX_FORCE_INLINE PxU32 sweep( const GeomSweepFuncs& sf, const PxGeometry& geom, const PxTransform& pose,
const PxGeometry& queryGeom, const PxTransform& queryPose, const ShapeData& /*queryVolume*/,
const PxVec3& unitDir, PxReal distance, PxGeomSweepHit& sweepHit, PxHitFlags hitFlags, PxReal inflation, PxSweepThreadContext* context)
{
PX_ASSERT(queryGeom.getType()==PxGeometryType::eCONVEXMESH);
const SweepConvexFunc func = sf.convexMap[geom.getType()];
return PxU32(func(geom, pose, static_cast<const PxConvexMeshGeometry&>(queryGeom), queryPose, unitDir, distance, sweepHit, hitFlags, inflation, context));
}
};
struct DefaultPrunerSweepCallback : public PrunerRaycastCallback, public PxSweepThreadContext
{
virtual bool reportHit(const PrunerPayload& /*payload*/, PxGeomSweepHit& /*hit*/)
{
return true;
}
};
template<class ShapeCast>
struct DefaultPrunerSweepCallbackT : public DefaultPrunerSweepCallback
{
PxSweepThreadContext* mContext;
PrunerFilterCallback& mFilterCB;
const GeomSweepFuncs& mCachedFuncs;
const PxGeometry& mGeometry;
const PxTransform& mPose;
const ShapeData& mQueryVolume;
const PxVec3& mDir;
PxGeomSweepHit mLocalHit;
const PxHitFlags mHitFlags;
PxGeomSweepHit mClosestHit;
PrunerPayload mClosestPayload;
bool mFoundHit;
const bool mAnyHit;
DefaultPrunerSweepCallbackT(PrunerFilterCallback& filterCB, const GeomSweepFuncs& funcs,
const PxGeometry& geometry, const PxTransform& pose, const ShapeData& queryVolume,
const PxVec3& dir, float distance, PxHitFlags hitFlags, bool anyHit, PxSweepThreadContext* context=NULL) :
mContext (context ? context : this),
mFilterCB (filterCB),
mCachedFuncs (funcs),
mGeometry (geometry),
mPose (pose),
mQueryVolume (queryVolume),
mDir (dir),
mHitFlags (hitFlags),
mFoundHit (false),
mAnyHit (anyHit)
{
mClosestHit.distance = distance;
}
virtual bool invoke(PxReal& aDist, PxU32 primIndex, const PrunerPayload* payloads, const PxTransform* transforms) PX_OVERRIDE PX_FINAL
{
PX_ASSERT(payloads && transforms);
const PrunerPayload& payload = payloads[primIndex];
PxHitFlags filteredHitFlags = mHitFlags;
const PxGeometry* shapeGeom = mFilterCB.validatePayload(payload, filteredHitFlags);
if(!shapeGeom)
return true;
// PT: ### TODO: missing bit from PhysX version here
const float inflation = 0.0f; // ####
const PxU32 retVal = ShapeCast::sweep(mCachedFuncs, *shapeGeom, transforms[primIndex], mGeometry, mPose, mQueryVolume, mDir, aDist, mLocalHit, filteredHitFlags, inflation, mContext);
if(!retVal || !reportHit(payload, mLocalHit))
return true;
if(mLocalHit.distance < mClosestHit.distance)
{
mFoundHit = true;
if(mAnyHit)
return false;
aDist = mLocalHit.distance;
mClosestHit = mLocalHit;
mClosestPayload = payload;
}
return true;
}
PX_NOCOPY(DefaultPrunerSweepCallbackT)
};
typedef DefaultPrunerSweepCallbackT<SphereShapeCast> DefaultPrunerSphereSweepCallback;
typedef DefaultPrunerSweepCallbackT<BoxShapeCast> DefaultPrunerBoxSweepCallback;
typedef DefaultPrunerSweepCallbackT<CapsuleShapeCast> DefaultPrunerCapsuleSweepCallback;
typedef DefaultPrunerSweepCallbackT<ConvexShapeCast> DefaultPrunerConvexSweepCallback;
}
}
#endif

View File

@@ -0,0 +1,74 @@
// 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 GU_RAYCAST_TESTS_H
#define GU_RAYCAST_TESTS_H
#include "foundation/PxSimpleTypes.h"
#include "geometry/PxGeometry.h"
#include "geometry/PxGeometryHit.h"
#include "geometry/PxGeometryQueryContext.h"
namespace physx
{
#define UNUSED_RAYCAST_THREAD_CONTEXT NULL
// PT: we use a define to be able to quickly change the signature of all raycast functions.
// (this also ensures they all use consistent names for passed parameters).
// \param[in] geom geometry object to raycast against
// \param[in] pose pose of geometry object
// \param[in] rayOrigin ray's origin
// \param[in] rayDir ray's unit dir
// \param[in] maxDist ray's length/max distance
// \param[in] hitFlags query behavior flags
// \param[in] maxHits max number of hits = size of 'hits' buffer
// \param[out] hits result buffer where to write raycast hits
// \param[in] stride size of hit structure
// \param[in] threadContext optional per-thread context
#define GU_RAY_FUNC_PARAMS const PxGeometry& geom, const PxTransform& pose, \
const PxVec3& rayOrigin, const PxVec3& rayDir, PxReal maxDist, \
PxHitFlags hitFlags, PxU32 maxHits, PxGeomRaycastHit* PX_RESTRICT hits, PxU32 stride, PxRaycastThreadContext* threadContext
namespace Gu
{
// PT: function pointer for Geom-indexed raycast functions
// See GU_RAY_FUNC_PARAMS for function parameters details.
// \return number of hits written to 'hits' result buffer
// \note there's no mechanism to report overflow. Returned number of hits is just clamped to maxHits.
typedef PxU32 (*RaycastFunc) (GU_RAY_FUNC_PARAMS);
// PT: typedef for a bundle of all raycast functions, i.e. the function table itself (indexed by geom-type).
typedef RaycastFunc GeomRaycastTable[PxGeometryType::eGEOMETRY_COUNT];
// PT: retrieves the raycast function table (for access by external non-Gu modules)
PX_PHYSX_COMMON_API const GeomRaycastTable& getRaycastFuncTable();
} // namespace Gu
}
#endif

View File

@@ -0,0 +1,704 @@
// 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 GU_SLOW_GJK_EPA_H
#define GU_SLOW_GJK_EPA_H
#include "foundation/PxBasicTemplates.h"
#include "foundation/PxVec3.h"
#include "foundation/PxVec4.h"
#include "GuBounds.h"
namespace physx
{
namespace Gu
{
// The reference implementation of GJK-EPA algorithm
namespace RefGjkEpa
{
template <typename Support>
struct Convex
{
static const PxU32 MAX_VERTS = 32;
PX_CUDA_CALLABLE
Convex(const Support& s, const PxTransform& p)
:
mS(s), mPose(p), mNumVerts(0)
{
const PxVec3 X(1, 0, 0), Y(0, 1, 0), Z(0, 0, 1);
const PxBounds3 bounds(PxVec3(mS.supportLocal(-X).x, mS.supportLocal(-Y).y, mS.supportLocal(-Z).z),
PxVec3(mS.supportLocal(X).x, mS.supportLocal(Y).y, mS.supportLocal(Z).z));
PxReal maxExtent = bounds.getDimensions().maxElement();
mAccuracy = PxMax(maxExtent * 0.01f, FLT_EPSILON);
}
PX_CUDA_CALLABLE PX_INLINE
PxReal getAccuracy() const
{ return mAccuracy; }
PX_CUDA_CALLABLE PX_INLINE
PxBounds3 getBounds() const
{
const PxVec3 X(mPose.q.getInvBasisVector0()),
Y(mPose.q.getInvBasisVector1()),
Z(mPose.q.getInvBasisVector2());
return PxBounds3(PxVec3(mPose.transform(mS.supportLocal(-X)).x,
mPose.transform(mS.supportLocal(-Y)).y,
mPose.transform(mS.supportLocal(-Z)).z),
PxVec3(mPose.transform(mS.supportLocal(X)).x,
mPose.transform(mS.supportLocal(Y)).y,
mPose.transform(mS.supportLocal(Z)).z));
}
PX_CUDA_CALLABLE
PxU8 supportIndex(const PxVec3& dir)
{
PxVec3 d = dir;
PxVec3 v = mPose.transform(mS.supportLocal(mPose.rotateInv(d)));
PxU32 closest = MAX_VERTS;
const PxReal WELD_DIST_SQ = mAccuracy * mAccuracy;
PxReal distSq = FLT_MAX;
for (PxI32 i = mNumVerts - 1; i >= 0; --i)
{
PxReal dSq = (mVerts[i] - v).magnitudeSquared();
if (dSq < WELD_DIST_SQ)
return PxU8(i);
if (distSq > dSq)
{
distSq = dSq;
closest = i;
}
}
PX_ASSERT(closest < MAX_VERTS || mNumVerts == 0);
if (mNumVerts == MAX_VERTS)
return PxU8(closest);
mVerts[mNumVerts++] = v;
return PxU8(mNumVerts - 1);
}
PX_CUDA_CALLABLE PX_INLINE
const PxVec3& supportVertex(PxU8 index) const
{ PX_ASSERT(index < mNumVerts); return mVerts[index]; }
PX_CUDA_CALLABLE PX_INLINE
const PxTransform& getPose() const
{ return mPose; }
private:
const Support& mS;
const PxTransform& mPose;
PxVec3 mVerts[MAX_VERTS];
PxU32 mNumVerts;
PxF32 mAccuracy;
};
template <typename Support>
struct GjkDistance
{
PX_CUDA_CALLABLE
GjkDistance(Convex<Support>& convexA, Convex<Support>& convexB)
:
mConvexA(convexA), mConvexB(convexB),
mNumVerts(0), mNumBestVerts(0), mIteration(0), mClosest(FLT_MAX)
{
mVerts[0] = mVerts[1] = mVerts[2] = mVerts[3] = Vert::make(PxVec3(0), 0, 0, 0);
PxVec3 dir = mConvexB.getBounds().getCenter() - mConvexA.getBounds().getCenter();
if (dir.normalize() < FLT_EPSILON) dir = PxVec3(1, 0, 0);
addPoint(dir);
}
PX_CUDA_CALLABLE PX_INLINE
PxReal getAccuracy() const
{ return PxMin(mConvexA.getAccuracy(), mConvexB.getAccuracy()); }
PX_CUDA_CALLABLE
// adds a new point (the difference of the shapes support points in a given direction)
// to the simplex. returns the projection of the difference of the support points on
// the direction. positive values mean a gap, negative - an overlap. FLT_MAX signals
// to finalize the algorithm. mIteration > MAX_ITERATIONS indicate that the algorithm
// got stuck. most likely adding several same points over and over, but unable to
// finish because of the floating point precision problems
PxReal addPoint(const PxVec3& dir)
{
if (++mIteration > MAX_ITERATIONS)
return FLT_MAX;
const PxU8 aI = mConvexA.supportIndex(dir), bI = mConvexB.supportIndex(-dir);
const PxVec3 p = mConvexA.supportVertex(aI) - mConvexB.supportVertex(bI);
for (PxU32 i = 0; i < mNumVerts; ++i)
{
const Vert& v = mVerts[i];
if (v.aI == aI && v.bI == bI)
return FLT_MAX;
}
mVerts[mNumVerts++] = Vert::make(p, 0.0f, aI, bI);
return p.dot(-dir);
}
PX_CUDA_CALLABLE
void computeClosest()
{
Vert verts[4]; verts[0] = mVerts[0]; verts[1] = mVerts[1]; verts[2] = mVerts[2]; verts[3] = mVerts[3];
verts[0].s = verts[1].s = verts[2].s = verts[3].s = 0;
PxU32 numVerts = mNumVerts;
switch (numVerts)
{
case 1:
{
verts[0].s = 1.0f;
break;
}
case 2:
{
const PxVec3 a = verts[0].p, b = verts[1].p;
const PxVec3 ba = a - b;
const PxReal sba = ba.dot(-b);
if (sba <= 0)
{
verts[0] = verts[1];
verts[0].s = 1.0f;
numVerts = 1;
break;
}
verts[0].s = sba / ba.magnitudeSquared();
verts[1].s = 1.0f - verts[0].s;
break;
}
case 3:
{
const PxVec3 a = verts[0].p, b = verts[1].p, c = verts[2].p;
const PxVec3 ca = a - c, cb = b - c;
const PxReal sca = ca.dot(-c), scb = cb.dot(-c);
if (sca <= 0 && scb <= 0)
{
verts[0] = verts[2];
verts[0].s = 1.0f;
numVerts = 1;
break;
}
const PxVec3 abc = (b - a).cross(c - a);
const PxReal iabc = 1.0f / abc.magnitudeSquared();
const PxVec3 pabc = abc * abc.dot(a) * iabc;
const PxReal tca = abc.dot((c - pabc).cross(a - pabc));
if (sca > 0 && tca <= 0)
{
verts[1] = verts[2];
verts[0].s = sca / ca.magnitudeSquared();
verts[1].s = 1.0f - verts[0].s;
numVerts = 2;
break;
}
const PxReal tbc = abc.dot((b - pabc).cross(c - pabc));
if (scb > 0 && tbc <= 0)
{
verts[0] = verts[1];
verts[1] = verts[2];
verts[0].s = scb / cb.magnitudeSquared();
verts[1].s = 1.0f - verts[0].s;
numVerts = 2;
break;
}
verts[0].s = tbc * iabc;
verts[1].s = tca * iabc;
verts[2].s = 1.0f - verts[0].s - verts[1].s;
if (abc.dot(a) > 0) PxSwap(verts[0], verts[1]);
break;
}
case 4:
{
const PxVec3 a = verts[0].p, b = verts[1].p, c = verts[2].p, d = verts[3].p;
const PxVec3 da = a - d, db = b - d, dc = c - d;
const PxReal sda = da.dot(-d), sdb = db.dot(-d), sdc = dc.dot(-d);
if (sda <= 0 && sdb <= 0 && sdc <= 0)
{
verts[0] = verts[3];
verts[0].s = 1.0f;
numVerts = 1;
break;
}
const PxVec3 dab = (a - d).cross(b - d);
const PxReal idab = 1.0f / dab.magnitudeSquared();
const PxVec3 pdab = dab * dab.dot(d) * idab;
const PxVec3 dbc = (b - d).cross(c - d);
const PxReal idbc = 1.0f / dbc.magnitudeSquared();
const PxVec3 pdbc = dbc * dbc.dot(d) * idbc;
const PxVec3 dca = (c - d).cross(a - d);
const PxReal idca = 1.0f / dca.magnitudeSquared();
const PxVec3 pdca = dca * dca.dot(d) * idca;
const PxReal tda = dab.dot((d - pdab).cross(a - pdab));
const PxReal tad = dca.dot((a - pdca).cross(d - pdca));
if (sda > 0 && tda <= 0 && tad <= 0)
{
verts[1] = verts[3];
verts[0].s = sda / da.magnitudeSquared();
verts[1].s = 1.0f - verts[0].s;
numVerts = 2;
break;
}
const PxReal tdb = dbc.dot((d - pdbc).cross(b - pdbc));
const PxReal tbd = dab.dot((b - pdab).cross(d - pdab));
if (sdb > 0 && tdb <= 0 && tbd <= 0)
{
verts[0] = verts[1];
verts[1] = verts[3];
verts[0].s = sdb / db.magnitudeSquared();
verts[1].s = 1.0f - verts[0].s;
numVerts = 2;
break;
}
const PxReal tcd = dbc.dot((c - pdbc).cross(d - pdbc));
const PxReal tdc = dca.dot((d - pdca).cross(c - pdca));
if (sdc > 0 && tdc <= 0 && tcd <= 0)
{
verts[0] = verts[2];
verts[1] = verts[3];
verts[0].s = sdc / dc.magnitudeSquared();
verts[1].s = 1.0f - verts[0].s;
numVerts = 2;
break;
}
const PxVec3 abc = (b - a).cross(c - a);
if (tda > 0 && tbd > 0 && dab.dot(d) < 0 && abc.dot(dab) > 0)
{
verts[2] = verts[3];
verts[0].s = tbd * idab;
verts[1].s = tda * idab;
verts[2].s = 1.0f - verts[0].s - verts[1].s;
numVerts = 3;
break;
}
if (tdb > 0 && tcd > 0 && dbc.dot(d) < 0 && abc.dot(dbc) > 0)
{
verts[0] = verts[1];
verts[1] = verts[2];
verts[2] = verts[3];
verts[0].s = tcd * idbc;
verts[1].s = tdb * idbc;
verts[2].s = 1.0f - verts[0].s - verts[1].s;
numVerts = 3;
break;
}
if (tdc > 0 && tad > 0 && dca.dot(d) < 0 && abc.dot(dca) > 0)
{
verts[1] = verts[3];
verts[0].s = tdc * idca;
verts[2].s = tad * idca;
verts[1].s = 1.0f - verts[0].s - verts[2].s;
numVerts = 3;
break;
}
break;
}
}
PxVec3 closest = verts[0].p * verts[0].s + verts[1].p * verts[1].s + verts[2].p * verts[2].s + verts[3].p * verts[3].s;
if (closest.magnitude() < mClosest.magnitude() - FLT_EPSILON)
{
mClosest = closest;
mVerts[0] = verts[0]; mVerts[1] = verts[1]; mVerts[2] = verts[2]; mVerts[3] = verts[3];
mNumVerts = numVerts;
}
else
--mNumVerts;
}
PX_CUDA_CALLABLE PX_INLINE
PxReal getDist() const
{ return mClosest.magnitude(); }
PX_CUDA_CALLABLE PX_INLINE
PxVec3 getDir() const
{ return -mClosest.getNormalized(); }
PX_CUDA_CALLABLE
void computePoints(PxVec3& pointA, PxVec3& pointB)
{
PxVec3 pA(0), pB(0);
for (PxU32 i = 0; i < mNumVerts; ++i)
{
pA += mConvexA.supportVertex(mVerts[i].aI) * mVerts[i].s;
pB += mConvexB.supportVertex(mVerts[i].bI) * mVerts[i].s;
}
pointA = pA; pointB = pB;
}
private:
static const PxU32 MAX_ITERATIONS = 100;
struct Vert
{
PxVec3 p;
PxReal s;
PxU8 aI, bI;
PX_CUDA_CALLABLE PX_INLINE
static Vert make(const PxVec3& p, PxReal s, PxU8 aI, PxU8 bI)
{ Vert v; v.p = p; v.s = s; v.aI = aI; v.bI = bI; return v; }
};
Convex<Support>& mConvexA;
Convex<Support>& mConvexB;
PxU32 mNumVerts, mNumBestVerts, mIteration;
Vert mVerts[4];
PxVec3 mClosest;
};
template <typename Support>
PX_CUDA_CALLABLE
static PxReal computeGjkDistance(const Support& a, const Support& b, const PxTransform& poseA, const PxTransform& poseB,
PxReal maxDist, PxVec3& pointA, PxVec3& pointB, PxVec3& axis)
{
Convex<Support> convexA(a, poseA), convexB(b, poseB);
GjkDistance<Support> gjk(convexA, convexB);
const PxReal distEps = 0.01f * gjk.getAccuracy();
while (true)
{
gjk.computeClosest();
const PxReal closestDist = gjk.getDist();
if (closestDist < distEps)
return 0;
const PxVec3 dir = gjk.getDir();
const PxReal proj = gjk.addPoint(dir);
if (proj >= closestDist - distEps)
{
PxVec3 pA, pB;
gjk.computePoints(pA, pB);
pointA = pA; pointB = pB;
axis = -dir;
return closestDist;
}
if (proj > maxDist)
return FLT_MAX;
}
}
template <typename Support>
struct EpaDepth
{
PX_CUDA_CALLABLE
EpaDepth(Convex<Support>& convexA, Convex<Support>& convexB)
:
mConvexA(convexA), mConvexB(convexB),
mNumVerts(0), mNumFaces(0),
mClosest(Face::make(PxVec4(PxZero), 0, 0, 0)),
mProj(-FLT_MAX)
{
PxVec3 dir0 = mConvexB.getBounds().getCenter() - mConvexA.getBounds().getCenter();
if (dir0.normalize() < FLT_EPSILON) dir0 = PxVec3(1, 0, 0);
PxVec3 dir1, dir2; PxComputeBasisVectors(dir0, dir1, dir2);
addPoint(dir0); addPoint(-dir0); addPoint(dir1);
if (mNumVerts < 3) addPoint(-dir1);
if (mNumVerts < 3) addPoint(dir2);
if (mNumVerts < 3) addPoint(-dir2);
mProj = -FLT_MAX;
}
PX_CUDA_CALLABLE PX_INLINE
bool isValid() const
{ return mNumFaces > 0; }
PX_CUDA_CALLABLE PX_INLINE
PxReal getAccuracy() const
{ return PxMin(mConvexA.getAccuracy(), mConvexB.getAccuracy()); }
PX_CUDA_CALLABLE PX_INLINE
PxVec3 supportVertex(PxU8 aI, PxU8 bI)
{ return mConvexA.supportVertex(aI) - mConvexB.supportVertex(bI); }
PX_CUDA_CALLABLE
bool makePlane(PxU8 i0, PxU8 i1, PxU8 i2, PxVec4& plane)
{
const Vert v0 = mVerts[i0], v1 = mVerts[i1], v2 = mVerts[i2];
const PxVec3 a = supportVertex(v0.aI, v0.bI), b = supportVertex(v1.aI, v1.bI), c = supportVertex(v2.aI, v2.bI);
const PxVec3 abc = (b - a).cross(c - a) + (c - b).cross(a - b) + (a - c).cross(b - c);
const PxReal labc = abc.magnitude();
const PxReal normalEps = FLT_EPSILON;
if (labc < normalEps)
return false;
const PxVec3 n = abc / labc;
const PxReal d = n.dot(-a);
plane = PxVec4(n, d);
return true;
}
PX_CUDA_CALLABLE
// adds a new point (the difference of the shapes support points in a given direction)
// to the polytope. removes all faces below the new point, keeps the track of open edges
// created by the face removal, and then creates a fan of new faces each containing the
// new point and one of the open edges. returns the projection of the difference of the
// support points on the direction. FLT_MAX signals to finalize the algorithm.
PxReal addPoint(const PxVec3& dir)
{
if (mNumVerts > MAX_VERTS - 1)
return FLT_MAX;
const PxU8 aI = mConvexA.supportIndex(dir), bI = mConvexB.supportIndex(-dir);
const PxVec3 p = mConvexA.supportVertex(aI) - mConvexB.supportVertex(bI);
PxReal proj = p.dot(-dir);
if (proj > mProj)
{
mProj = proj;
mBest = mClosest;
}
for (PxU32 i = 0; i < mNumVerts; ++i)
if (aI == mVerts[i].aI && bI == mVerts[i].bI)
return FLT_MAX;
Vert& v = mVerts[mNumVerts++];
v = Vert::make(aI, bI);
if (mNumVerts < 3)
return 0;
if (mNumVerts == 3)
{
PxVec4 plane0, plane1;
if (!makePlane(0, 1, 2, plane0) || !makePlane(1, 0, 2, plane1))
return FLT_MAX;
mFaces[mNumFaces++] = Face::make(plane0, 0, 1, 2);
mFaces[mNumFaces++] = Face::make(plane1, 1, 0, 2);
return 0;
}
const PxReal testEps = 0.01f * getAccuracy();
Edge edges[MAX_EDGES];
PxU32 numEdges = 0;
for (PxI32 i = mNumFaces - 1; i >= 0; --i)
{
Face& f = mFaces[i];
if (f.plane.dot(PxVec4(p, 1)) > testEps)
{
for (PxU32 j = 0; j < 3; ++j)
{
bool add = true;
const PxU8 v0 = f.v[j], v1 = f.v[(j + 1) % 3];
for (PxI32 k = numEdges - 1; k >= 0; --k)
{
const Edge& e = edges[k];
if (v0 == e.v[1] && v1 == e.v[0])
{
add = false;
edges[k] = edges[--numEdges];
break;
}
}
if (add)
edges[numEdges++] = Edge::make(v0, v1);
}
mFaces[i] = mFaces[--mNumFaces];
}
}
if (numEdges == 0)
return FLT_MAX;
if (mNumFaces > MAX_FACES - numEdges)
return FLT_MAX;
for (PxU32 i = 0; i < numEdges; ++i)
{
const Edge& e = edges[i];
PxU8 i0 = e.v[0], i1 = e.v[1], i2 = PxU8(mNumVerts - 1);
PxVec4 plane;
if (!makePlane(i0, i1, i2, plane))
return FLT_MAX;
mFaces[mNumFaces++] = Face::make(plane, i0, i1, i2);
}
return proj;
}
PX_CUDA_CALLABLE
void computeClosest()
{
PX_ASSERT(mNumFaces > 0);
PxU32 closest = PxU32(-1);
PxReal closestW = -FLT_MAX;
for (PxU32 i = 0; i < mNumFaces; ++i)
{
const PxReal w = mFaces[i].plane.w;
if (w > closestW)
{
closest = i;
closestW = w;
}
}
PX_ASSERT(closest != PxU32(-1));
mClosest = mFaces[closest];
if (mNumFaces == 2)
mBest = mClosest;
}
PX_CUDA_CALLABLE PX_INLINE
PxReal getDist() const
{ return mClosest.plane.w; }
PX_CUDA_CALLABLE PX_INLINE
PxVec3 getDir() const
{ return mClosest.plane.getXYZ(); }
PX_CUDA_CALLABLE PX_INLINE
PxReal getBestDist() const
{ return mBest.plane.w; }
PX_CUDA_CALLABLE PX_INLINE
PxVec3 getBestDir() const
{ return mBest.plane.getXYZ(); }
PX_CUDA_CALLABLE
void computePoints(PxVec3& pointA, PxVec3& pointB)
{
const Vert v0 = mVerts[mBest.v[0]], v1 = mVerts[mBest.v[1]], v2 = mVerts[mBest.v[2]];
const PxVec3 va0 = mConvexA.supportVertex(v0.aI), va1 = mConvexA.supportVertex(v1.aI), va2 = mConvexA.supportVertex(v2.aI);
const PxVec3 vb0 = mConvexB.supportVertex(v0.bI), vb1 = mConvexB.supportVertex(v1.bI), vb2 = mConvexB.supportVertex(v2.bI);
const PxVec3 a = va0 - vb0, b = va1 - vb1, c = va2 - vb2;
const PxVec3 abc = (b - a).cross(c - a);
const PxReal iabc = 1.0f / abc.magnitudeSquared();
const PxVec3 pabc = abc * abc.dot(a) * iabc;
const PxReal tbc = abc.dot((b - pabc).cross(c - pabc));
const PxReal tca = abc.dot((c - pabc).cross(a - pabc));
const PxReal tab = abc.dot((a - pabc).cross(b - pabc));
const PxReal sa = tbc * iabc, sb = tca * iabc, sc = tab * iabc;
pointA = va0 * sa + va1 * sb + va2 * sc;
pointB = vb0 * sa + vb1 * sb + vb2 * sc;
}
private:
static const PxU32 MAX_VERTS = 32;
static const PxU32 MAX_FACES = 2 * MAX_VERTS - 4;
static const PxU32 MAX_EDGES = MAX_VERTS + MAX_FACES - 2;
struct Vert
{
PxU8 aI, bI;
PX_CUDA_CALLABLE PX_INLINE
static Vert make(PxU8 aI, PxU8 bI)
{ Vert v; v.aI = aI; v.bI = bI; return v; }
};
struct Face
{
PxVec4 plane;
PxU8 v[3];
PX_CUDA_CALLABLE PX_INLINE
static Face make(const PxVec4& plane, PxU8 v0, PxU8 v1, PxU8 v2)
{ Face f; f.plane = plane; f.v[0] = v0; f.v[1] = v1; f.v[2] = v2; return f; }
};
struct Edge
{
PxU8 v[2];
PX_CUDA_CALLABLE PX_INLINE
static Edge make(PxU8 v0, PxU8 v1)
{ Edge e; e.v[0] = v0; e.v[1] = v1; return e; }
};
Convex<Support>& mConvexA;
Convex<Support>& mConvexB;
Vert mVerts[MAX_VERTS];
Face mFaces[MAX_FACES];
PxU32 mNumVerts, mNumFaces;
Face mClosest, mBest;
PxReal mProj;
};
template <typename Support>
PX_CUDA_CALLABLE
static PxReal computeEpaDepth(const Support& a, const Support& b, const PxTransform& poseA, const PxTransform& poseB,
PxVec3& pointA, PxVec3& pointB, PxVec3& axis)
{
Convex<Support> convexA(a, poseA), convexB(b, poseB);
EpaDepth<Support> epa(convexA, convexB);
if (!epa.isValid())
return FLT_MAX;
const PxReal distEps = 0.01f * epa.getAccuracy();
while (true)
{
epa.computeClosest();
const PxReal closestDist = epa.getDist();
const PxVec3 dir = epa.getDir();
const PxReal proj = epa.addPoint(dir);
if (proj >= closestDist - distEps)
{
PxVec3 pA, pB;
epa.computePoints(pA, pB);
pointA = pA; pointB = pB;
axis = -epa.getBestDir();
return epa.getBestDist();
}
}
}
}
}
}
#endif

View File

@@ -0,0 +1,175 @@
// 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 GU_SEGMENT_H
#define GU_SEGMENT_H
#include "foundation/PxVec3.h"
namespace physx
{
namespace Gu
{
/**
\brief Represents a line segment.
Line segment geometry
In some cases this structure will be used to represent the infinite line that passes point0 and point1.
*/
class Segment
{
public:
/**
\brief Constructor
*/
PX_INLINE Segment()
{
}
/**
\brief Constructor
*/
PX_INLINE Segment(const PxVec3& _p0, const PxVec3& _p1) : p0(_p0), p1(_p1)
{
}
/**
\brief Copy constructor
*/
PX_INLINE Segment(const Segment& seg) : p0(seg.p0), p1(seg.p1)
{
}
/**
\brief Destructor
*/
PX_INLINE ~Segment()
{
}
//! Assignment operator
PX_INLINE Segment& operator=(const Segment& other)
{
p0 = other.p0;
p1 = other.p1;
return *this;
}
//! Equality operator
PX_INLINE bool operator==(const Segment& other) const
{
return (p0==other.p0 && p1==other.p1);
}
//! Inequality operator
PX_INLINE bool operator!=(const Segment& other) const
{
return (p0!=other.p0 || p1!=other.p1);
}
PX_INLINE const PxVec3& getOrigin() const
{
return p0;
}
//! Return the vector from point0 to point1
PX_INLINE PxVec3 computeDirection() const
{
return p1 - p0;
}
//! Return the vector from point0 to point1
PX_INLINE void computeDirection(PxVec3& dir) const
{
dir = p1 - p0;
}
//! Return the center of the segment segment
PX_INLINE PxVec3 computeCenter() const
{
return (p0 + p1)*0.5f;
}
PX_INLINE PxF32 computeLength() const
{
return (p1-p0).magnitude();
}
PX_INLINE PxF32 computeSquareLength() const
{
return (p1-p0).magnitudeSquared();
}
// PT: TODO: remove this one
//! Return the square of the length of vector from point0 to point1
PX_INLINE PxReal lengthSquared() const
{
return ((p1 - p0).magnitudeSquared());
}
// PT: TODO: remove this one
//! Return the length of vector from point0 to point1
PX_INLINE PxReal length() const
{
return ((p1 - p0).magnitude());
}
/* PX_INLINE void setOriginDirection(const PxVec3& origin, const PxVec3& direction)
{
p0 = p1 = origin;
p1 += direction;
}*/
/**
\brief Computes a point on the segment
\param[out] pt point on segment
\param[in] t point's parameter [t=0 => pt = mP0, t=1 => pt = mP1]
*/
PX_INLINE void computePoint(PxVec3& pt, PxF32 t) const
{
pt = p0 + t * (p1 - p0);
}
// PT: TODO: remove this one
//! Return the point at parameter t along the line: point0 + t*(point1-point0)
PX_INLINE PxVec3 getPointAt(PxReal t) const
{
return (p1 - p0)*t + p0;
}
PxVec3 p0; //!< Start of segment
PxVec3 p1; //!< End of segment
};
PX_COMPILE_TIME_ASSERT(sizeof(Gu::Segment) == 24);
}
}
#endif

View File

@@ -0,0 +1,102 @@
// 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 GU_SPHERE_H
#define GU_SPHERE_H
#include "foundation/PxVec3.h"
namespace physx
{
/**
\brief Represents a sphere defined by its center point and radius.
*/
namespace Gu
{
class Sphere
{
public:
/**
\brief Constructor
*/
PX_INLINE Sphere()
{
}
/**
\brief Constructor
*/
PX_INLINE Sphere(const PxVec3& _center, PxF32 _radius) : center(_center), radius(_radius)
{
}
/**
\brief Copy constructor
*/
PX_INLINE Sphere(const Sphere& sphere) : center(sphere.center), radius(sphere.radius)
{
}
/**
\brief Destructor
*/
PX_INLINE ~Sphere()
{
}
PX_INLINE void set(const PxVec3& _center, float _radius) { center = _center; radius = _radius; }
/**
\brief Checks the sphere is valid.
\return true if the sphere is valid
*/
PX_INLINE bool isValid() const
{
// Consistency condition for spheres: Radius >= 0.0f
return radius >= 0.0f;
}
/**
\brief Tests if a point is contained within the sphere.
\param[in] p the point to test
\return true if inside the sphere
*/
PX_INLINE bool contains(const PxVec3& p) const
{
return (center-p).magnitudeSquared() <= radius*radius;
}
PxVec3 center; //!< Sphere's center
PxF32 radius; //!< Sphere's radius
};
}
}
#endif

View File

@@ -0,0 +1,90 @@
// 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 GU_SQ_INTERNAL_H
#define GU_SQ_INTERNAL_H
#include "foundation/PxSimpleTypes.h"
#include "common/PxPhysXCommonConfig.h"
#define SQ_DEBUG_VIZ_STATIC_COLOR PxU32(PxDebugColor::eARGB_BLUE)
#define SQ_DEBUG_VIZ_DYNAMIC_COLOR PxU32(PxDebugColor::eARGB_RED)
#define SQ_DEBUG_VIZ_STATIC_COLOR2 PxU32(PxDebugColor::eARGB_DARKBLUE)
#define SQ_DEBUG_VIZ_DYNAMIC_COLOR2 PxU32(PxDebugColor::eARGB_DARKRED)
#define SQ_DEBUG_VIZ_COMPOUND_COLOR PxU32(PxDebugColor::eARGB_MAGENTA)
namespace physx
{
class PxRenderOutput;
class PxBounds3;
namespace Gu
{
class BVH;
class AABBTree;
class IncrementalAABBTree;
class IncrementalAABBTreeNode;
}
class DebugVizCallback
{
public:
DebugVizCallback() {}
virtual ~DebugVizCallback() {}
virtual bool visualizeNode(const physx::Gu::IncrementalAABBTreeNode& node, const physx::PxBounds3& bounds) = 0;
};
}
PX_PHYSX_COMMON_API void visualizeTree(physx::PxRenderOutput& out, physx::PxU32 color, const physx::Gu::BVH* tree);
PX_PHYSX_COMMON_API void visualizeTree(physx::PxRenderOutput& out, physx::PxU32 color, const physx::Gu::AABBTree* tree);
PX_PHYSX_COMMON_API void visualizeTree(physx::PxRenderOutput& out, physx::PxU32 color, const physx::Gu::IncrementalAABBTree* tree, physx::DebugVizCallback* cb=NULL);
// PT: macros to try limiting the code duplication in headers. Mostly it just redefines the
// SqPruner API in implementation classes, and you shouldn't have to worry about it.
// Note that this assumes pool-based pruners with an mPool class member (for now).
#define DECLARE_BASE_PRUNER_API \
virtual void shiftOrigin(const PxVec3& shift); \
virtual void visualize(PxRenderOutput& out, PxU32 primaryColor, PxU32 secondaryColor) const;
#define DECLARE_PRUNER_API_COMMON \
virtual bool addObjects(PrunerHandle* results, const PxBounds3* bounds, const PrunerPayload* data, const PxTransform* transforms, PxU32 count, bool hasPruningStructure); \
virtual void removeObjects(const PrunerHandle* handles, PxU32 count, PrunerPayloadRemovalCallback* removalCallback); \
virtual void updateObjects(const PrunerHandle* handles, PxU32 count, float inflation, const PxU32* boundsIndices, const PxBounds3* newBounds, const PxTransform32* newTransforms); \
virtual void purge(); \
virtual void commit(); \
virtual void merge(const void* mergeParams); \
virtual bool raycast(const PxVec3& origin, const PxVec3& unitDir, PxReal& inOutDistance, Gu::PrunerRaycastCallback&) const; \
virtual bool overlap(const Gu::ShapeData& queryVolume, Gu::PrunerOverlapCallback&) const; \
virtual bool sweep(const Gu::ShapeData& queryVolume, const PxVec3& unitDir, PxReal& inOutDistance, Gu::PrunerRaycastCallback&) const; \
virtual const PrunerPayload& getPayloadData(PrunerHandle handle, PrunerPayloadData* data) const { return mPool.getPayloadData(handle, data); } \
virtual void preallocate(PxU32 entries) { mPool.preallocate(entries); } \
virtual bool setTransform(PrunerHandle handle, const PxTransform& transform) { return mPool.setTransform(handle, transform); } \
virtual void getGlobalBounds(PxBounds3&) const;
#endif

View File

@@ -0,0 +1,153 @@
// 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 GU_SWEEP_TESTS_H
#define GU_SWEEP_TESTS_H
#include "foundation/PxTransform.h"
#include "geometry/PxGeometry.h"
#include "geometry/PxGeometryHit.h"
#include "geometry/PxGeometryQueryContext.h"
namespace physx
{
class PxConvexCoreGeometry;
class PxConvexMeshGeometry;
class PxCapsuleGeometry;
class PxTriangle;
class PxBoxGeometry;
#define UNUSED_SWEEP_THREAD_CONTEXT NULL
// PT: TODO: unify this with raycast calls (names and order of params)
// PT: we use defines to be able to quickly change the signature of all sweep functions.
// (this also ensures they all use consistent names for passed parameters).
// \param[in] geom geometry object to sweep against
// \param[in] pose pose of geometry object
// \param[in] unitDir sweep's unit dir
// \param[in] distance sweep's length/max distance
// \param[out] sweepHit hit result
// \param[in] hitFlags query behavior flags
// \param[in] inflation optional inflation value for swept shape
// \param[in] threadContext optional per-thread context
// PT: sweep parameters for capsule
#define GU_CAPSULE_SWEEP_FUNC_PARAMS const PxGeometry& geom, const PxTransform& pose, \
const PxCapsuleGeometry& capsuleGeom_, const PxTransform& capsulePose_, const Gu::Capsule& lss, \
const PxVec3& unitDir, PxReal distance, \
PxGeomSweepHit& sweepHit, const PxHitFlags hitFlags, PxReal inflation, PxSweepThreadContext* threadContext
// PT: sweep parameters for box
#define GU_BOX_SWEEP_FUNC_PARAMS const PxGeometry& geom, const PxTransform& pose, \
const PxBoxGeometry& boxGeom_, const PxTransform& boxPose_, const Gu::Box& box, \
const PxVec3& unitDir, PxReal distance, \
PxGeomSweepHit& sweepHit, const PxHitFlags hitFlags, PxReal inflation, PxSweepThreadContext* threadContext
// VR: sweep parameters for convex core
#define GU_CONVEXCORE_SWEEP_FUNC_PARAMS const PxGeometry& geom, const PxTransform& pose, \
const PxConvexCoreGeometry& convexGeom, const PxTransform& convexPose, \
const PxVec3& unitDir, PxReal distance, \
PxGeomSweepHit& sweepHit, const PxHitFlags hitFlags, PxReal inflation, PxSweepThreadContext* threadContext
// PT: sweep parameters for convex mesh
#define GU_CONVEX_SWEEP_FUNC_PARAMS const PxGeometry& geom, const PxTransform& pose, \
const PxConvexMeshGeometry& convexGeom, const PxTransform& convexPose, \
const PxVec3& unitDir, PxReal distance, \
PxGeomSweepHit& sweepHit, const PxHitFlags hitFlags, PxReal inflation, PxSweepThreadContext* threadContext
namespace Gu
{
class Capsule;
class Box;
// PT: function pointer for Geom-indexed capsule sweep functions
// See GU_CAPSULE_SWEEP_FUNC_PARAMS for function parameters details.
// \return true if a hit was found, false otherwise
typedef bool (*SweepCapsuleFunc) (GU_CAPSULE_SWEEP_FUNC_PARAMS);
// PT: function pointer for Geom-indexed box sweep functions
// See GU_BOX_SWEEP_FUNC_PARAMS for function parameters details.
// \return true if a hit was found, false otherwise
typedef bool (*SweepBoxFunc) (GU_BOX_SWEEP_FUNC_PARAMS);
// function pointer for Geom-indexed convex core sweep functions
// See GU_CONVEXCORE_SWEEP_FUNC_PARAMS for function parameters details.
// \return true if a hit was found, false otherwise
typedef bool (*SweepConvexCoreFunc) (GU_CONVEXCORE_SWEEP_FUNC_PARAMS);
// PT: function pointer for Geom-indexed convex mesh sweep functions
// See GU_CONVEX_SWEEP_FUNC_PARAMS for function parameters details.
// \return true if a hit was found, false otherwise
typedef bool (*SweepConvexFunc) (GU_CONVEX_SWEEP_FUNC_PARAMS);
// PT: typedef for bundles of all sweep functions, i.e. the function tables themselves (indexed by geom-type).
typedef SweepCapsuleFunc GeomSweepCapsuleTable [PxGeometryType::eGEOMETRY_COUNT];
typedef SweepBoxFunc GeomSweepBoxTable [PxGeometryType::eGEOMETRY_COUNT];
typedef SweepConvexCoreFunc GeomSweepConvexCoreTable[PxGeometryType::eGEOMETRY_COUNT];
typedef SweepConvexFunc GeomSweepConvexTable [PxGeometryType::eGEOMETRY_COUNT];
struct GeomSweepFuncs
{
GeomSweepCapsuleTable capsuleMap;
GeomSweepCapsuleTable preciseCapsuleMap;
GeomSweepBoxTable boxMap;
GeomSweepBoxTable preciseBoxMap;
GeomSweepConvexCoreTable convexCoreMap;
GeomSweepConvexTable convexMap;
};
// PT: grabs all sweep function tables at once (for access by external non-Gu modules)
PX_PHYSX_COMMON_API const GeomSweepFuncs& getSweepFuncTable();
// PT: signature for sweep-vs-triangles functions.
// We use defines to be able to quickly change the signature of all sweep functions.
// (this also ensures they all use consistent names for passed parameters).
// \param[in] nbTris number of triangles in input array
// \param[in] triangles array of triangles to sweep the shape against
// \param[in] doubleSided true if input triangles are double-sided
// \param[in] x geom to sweep against input triangles
// \param[in] pose pose of geom x
// \param[in] unitDir sweep's unit dir
// \param[in] distance sweep's length/max distance
// \param[out] hit hit result
// \param[in] cachedIndex optional initial triangle index (must be <nbTris)
// \param[in] inflation optional inflation value for swept shape
// \param[in] hitFlags query behavior flags
#define GU_SWEEP_TRIANGLES_FUNC_PARAMS(x) PxU32 nbTris, const PxTriangle* triangles, bool doubleSided, \
const x& geom, const PxTransform& pose, \
const PxVec3& unitDir, PxReal distance, \
PxGeomSweepHit& hit, const PxU32* cachedIndex, \
PxReal inflation, PxHitFlags hitFlags
bool sweepCapsuleTriangles (GU_SWEEP_TRIANGLES_FUNC_PARAMS(PxCapsuleGeometry));
bool sweepBoxTriangles (GU_SWEEP_TRIANGLES_FUNC_PARAMS(PxBoxGeometry));
bool sweepBoxTriangles_Precise (GU_SWEEP_TRIANGLES_FUNC_PARAMS(PxBoxGeometry));
} // namespace Gu
}
#endif