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,424 @@
// 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 CUDA_NP_COMMON_H
#define CUDA_NP_COMMON_H
#include "foundation/PxVec3.h"
#include <stdio.h>
#include "convexFormat.h"
#include "cutil_math.h"
#include "PxgCommonDefines.h"
#include "PxgPersistentContactManifold.h"
#include "assert.h"
#define CONVEX_PLANE_WARPS_PER_BLOCK 4
#define GJK_EPA_WARPS_PER_BLOCK 1
#define NUM_TMP_CONTACTS_PER_PAIR 32
//The smallest epsilon we will permit (scaled by PxTolerancesScale.length)
#define PCM_WITNESS_POINT_LOWER_EPS 1e-2f
//The largest epsilon we will permit (scaled by PxTolerancesScale.length)
#define PCM_WITNESS_POINT_UPPER_EPS 5e-2f
namespace physx
{
struct PxgPersistentContactManifold;
struct PxgPersistentContactMultiManifold;
struct PxgContactManagerInput;
struct PxsContactManagerOutput;
class PxsContactManager;
struct PxsTorsionalFrictionData;
namespace Sc
{
class ShapeInteraction;
}
struct PxgPairManagementData
{
PxgContactManagerInput* mContactManagerInputData;
PxsContactManagerOutput* mContactManagerOutputData;
PxsContactManager** mCpuContactManagerMapping;
Sc::ShapeInteraction** mShapeInteractions;
PxReal* mRestDistances;
PxsTorsionalFrictionData* mTorsionalData;
PxU32* mTempAccumulator;
PxU32* mBlockSharedAccumulator;
PxU32* mRemoveIndices;
PxU32 mNbPairs;
PxU32 mNbToRemove;
void* mPersistentContactManagers;// either PxgPersistentContactManifold or PxgPersistentMultiManagementData
PxgPairManagementData() : mContactManagerInputData(NULL), mContactManagerOutputData(NULL), mCpuContactManagerMapping(NULL), mShapeInteractions(NULL),
mRestDistances(NULL), mTorsionalData(NULL), mTempAccumulator(NULL), mBlockSharedAccumulator(NULL), mNbPairs(0)
{
}
};
struct PX_ALIGN_PREFIX(16) PxgPatchAndContactCounters
{
enum OverflowError
{
NO_OVERFLOW = 0,
CONTACT_BUFFER_OVERFLOW = 1 << 0,
FORCE_BUFFER_OVERFLOW = 1 << 1,
PATCH_BUFFER_OVERFLOW = 1 << 2
};
PxU32 patchesBytes;
PxU32 contactsBytes;
PxU32 forceAndIndiceBytes;
PxU32 overflowError;
__device__
void setOverflowError(const OverflowError& err)
{
PX_UNUSED(err);
#if __CUDA_ARCH__
atomicOr(&overflowError, PxU32(err));
#endif
}
__host__ __device__
PxU32 getOverflowError() const
{
return overflowError;
}
} PX_ALIGN_SUFFIX(16);
}
__host__ __device__ inline
physx::ConvexHullCooked::Valency u32ToValency(physx::PxU32 countOffset)
{
physx::ConvexHullCooked::Valency v;
v.mCount = u32High(countOffset);
v.mOffset = u32Low(countOffset);
return v;
}
__host__ __device__ inline
physx::PxU32 valencyToPxU32(const physx::ConvexHullCooked::Valency& v)
{
return merge(v.mCount, v.mOffset);
}
__host__ __device__ inline
physx::PxU8 getNbAdjVerts(physx::PxU32 val)
{
return u16Low(u32Low(val));
}
__host__ __device__ inline
physx::PxU16 getNbEdges(physx::PxU32 val)
{
return u32High(val);
}
__host__ __device__ inline
physx::PxU8 getNbPolygons(physx::PxU32 val)
{
return u16Low(u32Low(val));
}
__host__ __device__ inline
physx::PxU16 getVRef8(physx::PxU32 val)
{
return u32High(val);
}
__host__ __device__ inline
physx::PxU8 getNbVerts(physx::PxU32 val)
{
return u16High(u32Low(val));
}
__host__ __device__ inline
physx::PxU8 getMinIndex(physx::PxU32 val)
{
return u16Low(u32Low(val));
}
__host__ __device__ inline
physx::PxU32 merge(physx::PxU16 hi, physx::PxU8 lohi, physx::PxU8 lolo)
{
return merge(hi, merge(lohi, lolo));
}
__host__ __device__ inline bool isValidTet(const physx::PxVec3& worldV0, const physx::PxVec3& worldV1, const physx::PxVec3& worldV2, const physx::PxVec3& worldV3)
{
return (worldV1 - worldV0).dot((worldV2 - worldV0).cross(worldV3 - worldV0)) > 1e-9f;
}
//device only functions
#if PX_CUDA_COMPILER
#include "reduction.cuh"
class MeshScaling
{
public:
__device__ MeshScaling(const physx::PxVec3& scale_, const physx::PxQuat& rotation_)
{
scale = scale_;
rotation = rotation_;
idtMeshScale = (scale.x == 1.0f && scale.y == 1.0f && scale.z == 1.0f);
flipNormal = ((scale.x * scale.y * scale.z) < 0.0f);
}
__device__ inline physx::PxVec3 vertex2Shape(const physx::PxVec3& v) const
{
using namespace physx;
PxVec3 temp = rotation.rotate(v);
temp.x *= scale.x;
temp.y *= scale.y;
temp.z *= scale.z;
return rotation.rotateInv(temp);
}
__device__ inline physx::PxVec3 shape2Vertex(const physx::PxVec3& v) const
{
using namespace physx;
PxVec3 temp = rotation.rotate(v);
temp.x /= scale.x;
temp.y /= scale.y;
temp.z /= scale.z;
return rotation.rotateInv(temp);
}
//Transforms a normal vector from vertex to shape space. This keeps the normal vector perpendicular to surfaces that get scaled with the same transform.
//Does not preserve length. Is applicable to other covariant vectors too.
__device__ inline physx::PxVec3 vertex2ShapeNormalVector(const physx::PxVec3& normal) const
{
return shape2Vertex(normal);
}
//Transforms a normal vector from shape to vertex space. This keeps the normal vector perpendicular to surfaces that get scaled with the same transform.
//Does not preserve length. Is applicable to other covariant vectors too.
__device__ inline physx::PxVec3 shape2VertexNormalVector(const physx::PxVec3& normal) const
{
return vertex2Shape(normal);
}
__device__ inline void getShapeSpaceVert(physx::PxVec3& triV0, physx::PxVec3& triV1, physx::PxVec3& triV2,
physx::PxVec3& v0, physx::PxVec3& v1, physx::PxVec3& v2) const
{
if (idtMeshScale)
{
v0 = triV0;
v1 = triV1;
v2 = triV2;
}
else
{
// Triangle scaling, triangle verts in shape space
triV0 = vertex2Shape(triV0);
triV1 = vertex2Shape(triV1);
triV2 = vertex2Shape(triV2);
v0 = triV0;
v1 = flipNormal ? triV2 : triV1;
v2 = flipNormal ? triV1 : triV2;
}
}
physx::PxVec3 scale;
physx::PxQuat rotation;
bool idtMeshScale;
bool flipNormal;
};
//Applies a potentially non-uniform scaling to the point v. The scaling can be expressed in a rotated coordinate frame defined by the quaternion called rotation.
__device__ inline
physx::PxVec3 vertex2Shape(const physx::PxVec3& v, const physx::PxVec3& scale, const physx::PxQuat& rotation)
{
using namespace physx;
PxVec3 temp = rotation.rotate(v);
temp.x *= scale.x;
temp.y *= scale.y;
temp.z *= scale.z;
return rotation.rotateInv(temp);
}
//Removes a potentially non-uniform scaling from the point v. The scaling can be expressed in a rotated coordinate frame defined by the quaternion called rotation.
__device__ inline
physx::PxVec3 shape2Vertex(const physx::PxVec3& v, const physx::PxVec3& scale, const physx::PxQuat& rotation)
{
using namespace physx;
PxVec3 temp = rotation.rotate(v);
temp.x /= scale.x;
temp.y /= scale.y;
temp.z /= scale.z;
return rotation.rotateInv(temp);
}
//Transforms a normal vector from vertex to shape space. This keeps the normal vector perpendicular to surfaces that get scaled with the same transform.
//Does not preserve length. Is applicable to other covariant vectors too.
__device__ inline
physx::PxVec3 vertex2ShapeNormalVector(const physx::PxVec3& normal, const physx::PxVec3& scale, const physx::PxQuat& rotation)
{
return shape2Vertex(normal, scale, rotation);
}
//Transforms a normal vector from shape to vertex space. This keeps the normal vector perpendicular to surfaces that get scaled with the same transform.
//Does not preserve length. Is applicable to other covariant vectors too.
__device__ inline
physx::PxVec3 shape2VertexNormalVector(const physx::PxVec3& normal, const physx::PxVec3& scale, const physx::PxQuat& rotation)
{
return vertex2Shape(normal, scale, rotation);
}
__device__ inline static
void prepareVertices(const PxTransform& transf,
PxVec3 scale, PxQuat rot,
PxU32 nbHullVertices,
const float4* pVertices,
PxVec3* s_vertices
)
{
assert(transf.isFinite());
for (PxU32 i = threadIdx.x; i < nbHullVertices; i += WARP_SIZE)
{
float4 f = pVertices[i];
s_vertices[i] = transf.transform(vertex2Shape(PxVec3(f.x, f.y, f.z), scale, rot));
assert(s_vertices[i].isFinite());
}
}
__device__ inline static
void prepareVertices(PxVec3 scale, PxQuat rot,
PxU32 nbHullVertices,
const float4* pVertices,
PxVec3* s_vertices
)
{
for (PxU32 i = threadIdx.x; i < nbHullVertices; i += WARP_SIZE)
{
float4 f = pVertices[i];
s_vertices[i] = vertex2Shape(PxVec3(f.x, f.y, f.z), scale, rot);
}
}
#define MESH_MANIFOLD_EPSILON 0.05f
#define BOX_MARGIN_RATIO 0.25f
__device__ inline static
PxReal calculatePCMConvexMargin(const float4& extents_, const PxVec3& scale, const PxReal toleranceLength)
{
using namespace physx;
const PxVec3 extents = PxVec3(extents_.x * scale.x,
extents_.y * scale.y,
extents_.z * scale.z);
const PxReal min = fminf(fminf(extents.x, extents.y), extents.z);
const PxReal toleranceMargin = toleranceLength * MESH_MANIFOLD_EPSILON;
//ML: 25% of the minimum extents of the internal AABB as this convex hull's margin
return fminf((min * BOX_MARGIN_RATIO), toleranceMargin);
}
__device__ inline static
PxReal calculatePCMConvexMargin(const PxVec3& extents, const PxReal toleranceLength)
{
using namespace physx;
const PxReal min = fminf(fminf(extents.x, extents.y), extents.z);
const PxReal toleranceMargin = toleranceLength * MESH_MANIFOLD_EPSILON;
//ML: 25% of the minimum extents of the internal AABB as this convex hull's margin
return fminf((min * BOX_MARGIN_RATIO), toleranceMargin);
}
__device__ inline static physx::PxReal maxTransformPositionDelta(const physx::PxVec3& curP, const physx::PxVec3& preP)
{
using namespace physx;
const PxVec3 deltaP = curP - preP;
return PxMax(PxAbs(deltaP.x), PxMax(PxAbs(deltaP.y), PxAbs(deltaP.z)));
}
__constant__ __device__ PxF32 local_invalidateThresholdsConvex[5] = { 0.5f, 0.125f, 0.25f, 0.375f, 0.375f };
__constant__ __device__ PxF32 local_invalidateQuatThresholdsConvex[5] = { 0.9998f, 0.9999f, 0.9999f, 0.9999f, 0.9999f };
__constant__ __device__ PxF32 local_invalidateThresholdsSphere[3] = { 0.5f, 0.1f, 0.75f };
__constant__ __device__ PxF32 local_invalidateQuatThresholdsSphere[3] = { 0.9995f, 0.9999f, 0.9997f };
__constant__ __device__ PxF32 local_invalidateQuatThresholdsConvexPlane[5] = { 0.99996f, 0.99996f, 0.99996f, 0.99996f, 0.99996f };
__device__ inline static
PxU32 invalidate_BoxConvex(const PxVec3& curRelPos, const PxQuat& curQuatA, const PxQuat& curQuatB,
const PxVec3& preRelPos, const PxQuat& preRelQuatA, const PxQuat& preRelQuatB,
const physx::PxReal minMargin, const physx::PxReal radiusA, const physx::PxReal radiusB,
const physx::PxU8 manifold_NumContacts, PxF32* local_invalidateThresholds, PxF32* local_invalidateQuatThresholds)
{
using namespace physx;
//This is the translational threshold used in invalidate_BoxConvexHull. 0.5 is 50% of the object margin. we use different threshold between
//0 and 4 points. This threashold is a scale that is multiplied by the objects' margins.
const PxReal ratio = local_invalidateThresholds[manifold_NumContacts];
const PxReal thresholdP = minMargin * ratio;
const PxReal deltaP = maxTransformPositionDelta(curRelPos, preRelPos);
//This is the rotational threshold used in invalidate_BoxConvexHull. 0.9998 is a threshold for quat difference
//between previous and current frame
const PxReal thresholdQ = local_invalidateQuatThresholds[manifold_NumContacts];
const PxReal deltaQA = curQuatA.dot(preRelQuatA);
const PxReal deltaQB = curQuatB.dot(preRelQuatB);
bool generateContacts = (deltaP > thresholdP) || (thresholdQ > deltaQA) || (thresholdQ > deltaQB);
if (!generateContacts)
{
const PxReal aRadian = deltaQA < 1.0f ? acosf(deltaQA) : 0.f;
const PxReal bRadian = deltaQB < 1.0f ? acosf(deltaQB) : 0.f;
const PxReal travelDistA = aRadian * radiusA;
const PxReal travelDistB = bRadian * radiusB;
generateContacts = (travelDistA > thresholdP) || (travelDistB > thresholdP);
}
return generateContacts;
}
#endif
#endif