feat(physics): wire physx sdk into build
This commit is contained in:
623
engine/third_party/physx/source/geomutils/src/gjk/GuEPA.cpp
vendored
Normal file
623
engine/third_party/physx/source/geomutils/src/gjk/GuEPA.cpp
vendored
Normal file
@@ -0,0 +1,623 @@
|
||||
// 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.
|
||||
|
||||
#include "GuEPA.h"
|
||||
#include "GuEPAFacet.h"
|
||||
#include "GuGJKSimplex.h"
|
||||
#include "CmPriorityQueue.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
class ConvexV;
|
||||
|
||||
struct FacetDistanceComparator
|
||||
{
|
||||
bool operator()(const Facet* left, const Facet* right) const
|
||||
{
|
||||
return *left < *right;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#if PX_VC
|
||||
#pragma warning(push)
|
||||
#pragma warning( disable : 4324 ) // Padding was added at the end of a structure because of a __declspec(align) value.
|
||||
#endif
|
||||
|
||||
class EPA
|
||||
{
|
||||
public:
|
||||
EPA(){}
|
||||
GjkStatus PenetrationDepth(const GjkConvex& a, const GjkConvex& b, const aos::Vec3V* PX_RESTRICT A, const aos::Vec3V* PX_RESTRICT B, const PxU8 size, const bool takeCoreShape,
|
||||
const FloatV tolerenceLength, GjkOutput& output);
|
||||
bool expandPoint(const GjkConvex& a, const GjkConvex& b, PxI32& numVerts, const FloatVArg upperBound);
|
||||
bool expandSegment(const GjkConvex& a, const GjkConvex& b, PxI32& numVerts, const FloatVArg upperBound);
|
||||
bool expandTriangle(PxI32& numVerts, const FloatVArg upperBound);
|
||||
|
||||
Facet* addFacet(const PxU32 i0, const PxU32 i1, const PxU32 i2, const aos::FloatVArg upper);
|
||||
|
||||
bool originInTetrahedron(const aos::Vec3VArg p1, const aos::Vec3VArg p2, const aos::Vec3VArg p3, const aos::Vec3VArg p4);
|
||||
|
||||
Cm::InlinePriorityQueue<Facet*, MaxFacets, FacetDistanceComparator> heap;
|
||||
aos::Vec3V aBuf[MaxSupportPoints];
|
||||
aos::Vec3V bBuf[MaxSupportPoints];
|
||||
Facet facetBuf[MaxFacets];
|
||||
EdgeBuffer edgeBuffer;
|
||||
EPAFacetManager facetManager;
|
||||
|
||||
private:
|
||||
PX_NOCOPY(EPA)
|
||||
};
|
||||
#if PX_VC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
PX_FORCE_INLINE bool EPA::originInTetrahedron(const aos::Vec3VArg p1, const aos::Vec3VArg p2, const aos::Vec3VArg p3, const aos::Vec3VArg p4)
|
||||
{
|
||||
using namespace aos;
|
||||
return BAllEqFFFF(PointOutsideOfPlane4(p1, p2, p3, p4)) == 1;
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void doSupport(const GjkConvex& a, const GjkConvex& b, const aos::Vec3VArg dir, aos::Vec3V& supportA, aos::Vec3V& supportB, aos::Vec3V& support)
|
||||
{
|
||||
const Vec3V tSupportA = a.support(V3Neg(dir));
|
||||
const Vec3V tSupportB = b.support(dir);
|
||||
//avoid LHS
|
||||
supportA = tSupportA;
|
||||
supportB = tSupportB;
|
||||
support = V3Sub(tSupportA, tSupportB);
|
||||
}
|
||||
|
||||
GjkStatus epaPenetration(const GjkConvex& a, const GjkConvex& b, const PxU8* PX_RESTRICT aInd, const PxU8* PX_RESTRICT bInd, const PxU8 size,
|
||||
const bool takeCoreShape, const FloatV tolerenceLength, GjkOutput& output)
|
||||
{
|
||||
|
||||
PX_ASSERT(size > 0 && size <=4);
|
||||
|
||||
Vec3V A[4];
|
||||
Vec3V B[4];
|
||||
|
||||
//ML: we construct a simplex based on the gjk simplex indices
|
||||
for(PxU32 i=0; i<size; ++i)
|
||||
{
|
||||
A[i] = a.supportPoint(aInd[i]);
|
||||
B[i] = b.supportPoint(bInd[i]);
|
||||
}
|
||||
|
||||
EPA epa;
|
||||
|
||||
return epa.PenetrationDepth(a, b, A, B, size, takeCoreShape, tolerenceLength, output);
|
||||
}
|
||||
|
||||
GjkStatus epaPenetration(const GjkConvex& a, const GjkConvex& b, const aos::Vec3V* PX_RESTRICT aPnt, const aos::Vec3V* PX_RESTRICT bPnt, const PxU8 size,
|
||||
const bool takeCoreShape, const FloatV tolerenceLength, GjkOutput& output)
|
||||
{
|
||||
|
||||
PX_ASSERT(size > 0 && size <=4);
|
||||
|
||||
const Vec3V* A = aPnt;
|
||||
const Vec3V* B = bPnt;
|
||||
|
||||
EPA epa;
|
||||
|
||||
return epa.PenetrationDepth(a, b, A, B, size, takeCoreShape, tolerenceLength, output);
|
||||
}
|
||||
|
||||
//ML: this function returns the signed distance of a point to a plane
|
||||
PX_FORCE_INLINE aos::FloatV Facet::getPlaneDist(const aos::Vec3VArg p, const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf) const
|
||||
{
|
||||
const Vec3V pa0(aBuf[m_indices[0]]);
|
||||
const Vec3V pb0(bBuf[m_indices[0]]);
|
||||
const Vec3V p0 = V3Sub(pa0, pb0);
|
||||
|
||||
return V3Dot(m_planeNormal, V3Sub(p, p0));
|
||||
}
|
||||
|
||||
//ML: This function:
|
||||
// (1)calculates the distance from orign((0, 0, 0)) to a triangle plane
|
||||
// (2) rejects triangle if the triangle is degenerate (two points are identical)
|
||||
// (3) rejects triangle to be added into the heap if the plane distance is large than upper
|
||||
aos::BoolV Facet::isValid2(const PxU32 i0, const PxU32 i1, const PxU32 i2, const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf,
|
||||
const aos::FloatVArg upper)
|
||||
{
|
||||
using namespace aos;
|
||||
const FloatV eps = FEps();
|
||||
|
||||
const Vec3V pa0(aBuf[i0]);
|
||||
const Vec3V pa1(aBuf[i1]);
|
||||
const Vec3V pa2(aBuf[i2]);
|
||||
|
||||
const Vec3V pb0(bBuf[i0]);
|
||||
const Vec3V pb1(bBuf[i1]);
|
||||
const Vec3V pb2(bBuf[i2]);
|
||||
|
||||
const Vec3V p0 = V3Sub(pa0, pb0);
|
||||
const Vec3V p1 = V3Sub(pa1, pb1);
|
||||
const Vec3V p2 = V3Sub(pa2, pb2);
|
||||
|
||||
const Vec3V v0 = V3Sub(p1, p0);
|
||||
const Vec3V v1 = V3Sub(p2, p0);
|
||||
|
||||
const Vec3V denormalizedNormal = V3Cross(v0, v1);
|
||||
FloatV norValue = V3Dot(denormalizedNormal, denormalizedNormal);
|
||||
//if norValue < eps, this triangle is degenerate
|
||||
const BoolV con = FIsGrtr(norValue, eps);
|
||||
norValue = FSel(con, norValue, FOne());
|
||||
|
||||
const Vec3V planeNormal = V3Scale(denormalizedNormal, FRsqrt(norValue));
|
||||
const FloatV planeDist = V3Dot(planeNormal, p0);
|
||||
|
||||
m_planeNormal = planeNormal;
|
||||
FStore(planeDist, &m_planeDist);
|
||||
|
||||
return BAnd(con, FIsGrtrOrEq(upper, planeDist));
|
||||
}
|
||||
|
||||
//ML: if the triangle is valid(not degenerate and within lower and upper bound), we need to add it into the heap. Otherwise, we just return
|
||||
//the triangle so that the facet can be linked to other facets in the expanded polytope.
|
||||
Facet* EPA::addFacet(const PxU32 i0, const PxU32 i1, const PxU32 i2, const aos::FloatVArg upper)
|
||||
{
|
||||
using namespace aos;
|
||||
PX_ASSERT(i0 != i1 && i0 != i2 && i1 != i2);
|
||||
//ML: we move the control in the calling code so we don't need to check weather we will run out of facets or not
|
||||
PX_ASSERT(facetManager.getNumUsedID() < MaxFacets);
|
||||
|
||||
const PxU32 facetId = facetManager.getNewID();
|
||||
PxPrefetchLine(&facetBuf[facetId], 128);
|
||||
|
||||
Facet * facet = PX_PLACEMENT_NEW(&facetBuf[facetId],Facet(i0, i1, i2));
|
||||
facet->m_FacetId = PxU8(facetId);
|
||||
|
||||
const BoolV validTriangle = facet->isValid2(i0, i1, i2, aBuf, bBuf, upper);
|
||||
|
||||
if(BAllEqTTTT(validTriangle))
|
||||
{
|
||||
heap.push(facet);
|
||||
facet->m_inHeap = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
facet->m_inHeap = false;
|
||||
}
|
||||
return facet;
|
||||
}
|
||||
|
||||
//ML: this function performs a flood fill over the boundary of the current polytope.
|
||||
void Facet::silhouette(const PxU32 _index, const aos::Vec3VArg w, const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf, EdgeBuffer& edgeBuffer, EPAFacetManager& manager)
|
||||
{
|
||||
using namespace aos;
|
||||
const FloatV zero = FZero();
|
||||
Edge stack[MaxFacets];
|
||||
stack[0] = Edge(this, _index);
|
||||
PxI32 size = 1;
|
||||
while(size--)
|
||||
{
|
||||
Facet* const PX_RESTRICT f = stack[size].m_facet;
|
||||
const PxU32 index = stack[size].m_index;
|
||||
PX_ASSERT(f->Valid());
|
||||
|
||||
if(!f->m_obsolete)
|
||||
{
|
||||
//ML: if the point is above the facet, the facet has an reflex edge, which will make the polytope concave. Therefore, we need to
|
||||
//remove this facet and make sure the expanded polytope is convex.
|
||||
const FloatV pointPlaneDist = f->getPlaneDist(w, aBuf, bBuf);
|
||||
|
||||
if(FAllGrtr(zero, pointPlaneDist))
|
||||
{
|
||||
//ML: facet isn't visible from w (we don't have a reflex edge), this facet will be on the boundary and part of the new polytope so that
|
||||
//we will push it into our edgeBuffer
|
||||
if(!edgeBuffer.Insert(f, index))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//ML:facet is visible from w, therefore, we need to remove this facet from the heap and push its adjacent facets onto the stack
|
||||
f->m_obsolete = true; // Facet is visible from w
|
||||
const PxU32 next(incMod3(index));
|
||||
const PxU32 next2(incMod3(next));
|
||||
stack[size++] = Edge(f->m_adjFacets[next2],PxU32(f->m_adjEdges[next2]));
|
||||
stack[size++] = Edge(f->m_adjFacets[next], PxU32(f->m_adjEdges[next]));
|
||||
|
||||
PX_ASSERT(size <= MaxFacets);
|
||||
if(!f->m_inHeap)
|
||||
{
|
||||
//if the facet isn't in the heap, we can release that memory
|
||||
manager.deferredFreeID(f->m_FacetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ML: this function perform flood fill for the adjancent facet and store the boundary facet into the edgeBuffer
|
||||
void Facet::silhouette(const aos::Vec3VArg w, const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf, EdgeBuffer& edgeBuffer, EPAFacetManager& manager)
|
||||
{
|
||||
m_obsolete = true;
|
||||
for(PxU32 a = 0; a < 3; ++a)
|
||||
{
|
||||
m_adjFacets[a]->silhouette(PxU32(m_adjEdges[a]), w, aBuf, bBuf, edgeBuffer, manager);
|
||||
}
|
||||
}
|
||||
|
||||
bool EPA::expandPoint(const GjkConvex& a, const GjkConvex& b, PxI32& numVerts, const FloatVArg upperBound)
|
||||
{
|
||||
const Vec3V x = V3UnitX();
|
||||
Vec3V q0 = V3Sub(aBuf[0], bBuf[0]);
|
||||
Vec3V q1;
|
||||
doSupport(a, b, x, aBuf[1], bBuf[1], q1);
|
||||
if (V3AllEq(q0, q1))
|
||||
return false;
|
||||
return expandSegment(a, b, numVerts, upperBound);
|
||||
}
|
||||
|
||||
//ML: this function use the segement to create a triangle
|
||||
bool EPA::expandSegment(const GjkConvex& a, const GjkConvex& b, PxI32& numVerts, const FloatVArg upperBound)
|
||||
{
|
||||
const Vec3V q0 = V3Sub(aBuf[0], bBuf[0]);
|
||||
const Vec3V q1 = V3Sub(aBuf[1], bBuf[1]);
|
||||
const Vec3V v = V3Sub(q1, q0);
|
||||
const Vec3V absV = V3Abs(v);
|
||||
|
||||
const FloatV x = V3GetX(absV);
|
||||
const FloatV y = V3GetY(absV);
|
||||
const FloatV z = V3GetZ(absV);
|
||||
|
||||
Vec3V axis = V3UnitX();
|
||||
const BoolV con0 = BAnd(FIsGrtr(x, y), FIsGrtr(z, y));
|
||||
if (BAllEqTTTT(con0))
|
||||
{
|
||||
axis = V3UnitY();
|
||||
}
|
||||
else if(FAllGrtr(x, z))
|
||||
{
|
||||
axis = V3UnitZ();
|
||||
}
|
||||
|
||||
const Vec3V n = V3Normalize(V3Cross(axis, v));
|
||||
Vec3V q2;
|
||||
doSupport(a, b, n, aBuf[2], bBuf[2], q2);
|
||||
|
||||
return expandTriangle(numVerts, upperBound);
|
||||
}
|
||||
|
||||
bool EPA::expandTriangle(PxI32& numVerts, const FloatVArg upperBound)
|
||||
{
|
||||
numVerts = 3;
|
||||
|
||||
Facet * PX_RESTRICT f0 = addFacet(0, 1, 2, upperBound);
|
||||
Facet * PX_RESTRICT f1 = addFacet(1, 0, 2, upperBound);
|
||||
|
||||
if(heap.empty())
|
||||
return false;
|
||||
|
||||
f0->link(0, f1, 0);
|
||||
f0->link(1, f1, 2);
|
||||
f0->link(2, f1, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//ML: this function calculates contact information. If takeCoreShape flag is true, this means the two closest points will be on the core shape used in the support functions.
|
||||
//For example, we treat sphere/capsule as a point/segment in the support function for GJK/EPA, so that the core shape for sphere/capsule is a point/segment. For PCM, we need
|
||||
//to take the point from the core shape because this will allows us recycle the contacts more stably. For SQ sweeps, we need to take the point on the surface of the sphere/capsule
|
||||
//when we calculate MTD because this is what will be reported to the user. Therefore, the takeCoreShape flag will be set to be false in SQ.
|
||||
static void calculateContactInformation(const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf, Facet* facet, const GjkConvex& a, const GjkConvex& b, const bool takeCoreShape, GjkOutput& output)
|
||||
{
|
||||
const FloatV zero = FZero();
|
||||
Vec3V _pa, _pb;
|
||||
facet->getClosestPoint(aBuf, bBuf, _pa, _pb);
|
||||
|
||||
//dist > 0 means two shapes are penetrated. If dist < 0(when origin isn't inside the polytope), two shapes status are unknown
|
||||
const FloatV dist = FAbs(facet->getPlaneDist());
|
||||
|
||||
const Vec3V planeNormal = V3Neg(facet->getPlaneNormal());
|
||||
|
||||
if(takeCoreShape)
|
||||
{
|
||||
output.closestA = _pa;
|
||||
output.closestB = _pb;
|
||||
output.normal = planeNormal;
|
||||
output.penDep = FNeg(dist);
|
||||
}
|
||||
else
|
||||
{
|
||||
//for sphere/capusule to take the surface point
|
||||
const BoolV aQuadratic = a.isMarginEqRadius();
|
||||
const BoolV bQuadratic = b.isMarginEqRadius();
|
||||
|
||||
const FloatV marginA = FSel(aQuadratic, a.getMargin(), zero);
|
||||
const FloatV marginB = FSel(bQuadratic, b.getMargin(), zero);
|
||||
const FloatV sumMargin = FAdd(marginA, marginB);
|
||||
output.closestA = V3NegScaleSub(planeNormal, marginA, _pa);
|
||||
output.closestB = V3ScaleAdd(planeNormal, marginB, _pb);
|
||||
output.normal = planeNormal;
|
||||
output.penDep = FNeg(FAdd(dist, sumMargin));
|
||||
}
|
||||
}
|
||||
|
||||
//ML: This function returns one of three status codes:
|
||||
//(1)EPA_FAIL: the algorithm failed to create a valid polytope(the origin wasn't inside the polytope) from the input simplex
|
||||
//(2)EPA_CONTACT : the algorithm found the MTD and converged successfully.
|
||||
//(3)EPA_DEGENERATE: the algorithm cannot make further progress and the result is unknown.
|
||||
GjkStatus EPA::PenetrationDepth(const GjkConvex& a, const GjkConvex& b, const aos::Vec3V* PX_RESTRICT A, const aos::Vec3V* PX_RESTRICT B, const PxU8 size, const bool takeCoreShape,
|
||||
const FloatV tolerenceLength, GjkOutput& output)
|
||||
{
|
||||
|
||||
using namespace aos;
|
||||
|
||||
PX_UNUSED(tolerenceLength);
|
||||
|
||||
PxPrefetchLine(&facetBuf[0]);
|
||||
PxPrefetchLine(&facetBuf[0], 128);
|
||||
|
||||
const FloatV zero = FZero();
|
||||
|
||||
const FloatV _max = FMax();
|
||||
FloatV upper_bound(_max);
|
||||
|
||||
aBuf[0]=A[0]; aBuf[1]=A[1]; aBuf[2]=A[2]; aBuf[3]=A[3];
|
||||
bBuf[0]=B[0]; bBuf[1]=B[1]; bBuf[2]=B[2]; bBuf[3]=B[3];
|
||||
|
||||
PxI32 numVertsLocal = 0;
|
||||
|
||||
heap.clear();
|
||||
|
||||
//if the simplex isn't a tetrahedron, we need to construct one before we can expand it
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
// Touching contact. Yes, we have a collision and the penetration will be zero
|
||||
if(!expandPoint(a, b, numVertsLocal, upper_bound))
|
||||
return EPA_FAIL;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
// We have a line segment inside the Minkowski sum containing the
|
||||
// origin. we need to construct two back to back triangles which link to each other
|
||||
if(!expandSegment(a, b, numVertsLocal, upper_bound))
|
||||
return EPA_FAIL;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
// We have a triangle inside the Minkowski sum containing
|
||||
// the origin. We need to construct two back to back triangles which link to each other
|
||||
if(!expandTriangle(numVertsLocal, upper_bound))
|
||||
return EPA_FAIL;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
//check for input face normal. All face normals in this tetrahedron should be all pointing either inwards or outwards. If all face normals are pointing outward, we are good to go. Otherwise, we need to
|
||||
//shuffle the input vertexes and make sure all face normals are pointing outward
|
||||
const Vec3V pa0(aBuf[0]);
|
||||
const Vec3V pa1(aBuf[1]);
|
||||
const Vec3V pa2(aBuf[2]);
|
||||
const Vec3V pa3(aBuf[3]);
|
||||
|
||||
const Vec3V pb0(bBuf[0]);
|
||||
const Vec3V pb1(bBuf[1]);
|
||||
const Vec3V pb2(bBuf[2]);
|
||||
const Vec3V pb3(bBuf[3]);
|
||||
|
||||
const Vec3V p0 = V3Sub(pa0, pb0);
|
||||
const Vec3V p1 = V3Sub(pa1, pb1);
|
||||
const Vec3V p2 = V3Sub(pa2, pb2);
|
||||
const Vec3V p3 = V3Sub(pa3, pb3);
|
||||
|
||||
const Vec3V v1 = V3Sub(p1, p0);
|
||||
const Vec3V v2 = V3Sub(p2, p0);
|
||||
|
||||
const Vec3V planeNormal = V3Normalize(V3Cross(v1, v2));
|
||||
|
||||
const FloatV signDist = V3Dot(planeNormal, V3Sub(p3, p0));
|
||||
|
||||
if (FAllGrtr(signDist, zero))
|
||||
{
|
||||
//shuffle the input vertexes
|
||||
const Vec3V tempA0 = aBuf[2];
|
||||
const Vec3V tempB0 = bBuf[2];
|
||||
aBuf[2] = aBuf[1];
|
||||
bBuf[2] = bBuf[1];
|
||||
aBuf[1] = tempA0;
|
||||
bBuf[1] = tempB0;
|
||||
}
|
||||
|
||||
Facet * PX_RESTRICT f0 = addFacet(0, 1, 2, upper_bound);
|
||||
Facet * PX_RESTRICT f1 = addFacet(0, 3, 1, upper_bound);
|
||||
Facet * PX_RESTRICT f2 = addFacet(0, 2, 3, upper_bound);
|
||||
Facet * PX_RESTRICT f3 = addFacet(1, 3, 2, upper_bound);
|
||||
|
||||
if (heap.empty())
|
||||
return EPA_FAIL;
|
||||
|
||||
#if EPA_DEBUG
|
||||
PX_ASSERT(f0->m_planeDist >= -1e-2f);
|
||||
PX_ASSERT(f1->m_planeDist >= -1e-2f);
|
||||
PX_ASSERT(f2->m_planeDist >= -1e-2f);
|
||||
PX_ASSERT(f3->m_planeDist >= -1e-2f);
|
||||
#endif
|
||||
|
||||
f0->link(0, f1, 2);
|
||||
f0->link(1, f3, 2);
|
||||
f0->link(2, f2, 0);
|
||||
f1->link(0, f2, 2);
|
||||
f1->link(1, f3, 0);
|
||||
f2->link(1, f3, 1);
|
||||
numVertsLocal = 4;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const FloatV minMargin = FMin(a.getMinMargin(), b.getMinMargin());
|
||||
const FloatV eps = FMul(minMargin, FLoad(0.1f));
|
||||
|
||||
Facet* PX_RESTRICT facet = NULL;
|
||||
|
||||
Vec3V tempa, tempb, q;
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
facetManager.processDeferredIds();
|
||||
facet = heap.pop(); //get the shortest distance triangle of origin from the list
|
||||
facet->m_inHeap = false;
|
||||
|
||||
if (!facet->isObsolete())
|
||||
{
|
||||
PxPrefetchLine(edgeBuffer.m_pEdges);
|
||||
PxPrefetchLine(edgeBuffer.m_pEdges,128);
|
||||
PxPrefetchLine(edgeBuffer.m_pEdges,256);
|
||||
|
||||
const Vec3V planeNormal = facet->getPlaneNormal();
|
||||
const FloatV planeDist = facet->getPlaneDist();
|
||||
|
||||
tempa = a.support(planeNormal);
|
||||
tempb = b.support(V3Neg(planeNormal));
|
||||
|
||||
q = V3Sub(tempa, tempb);
|
||||
|
||||
PxPrefetchLine(&aBuf[numVertsLocal],128);
|
||||
PxPrefetchLine(&bBuf[numVertsLocal],128);
|
||||
|
||||
//calculate the distance from support point to the origin along the plane normal. Because the support point is search along
|
||||
//the plane normal, which means the distance should be positive. However, if the origin isn't contained in the polytope, dist
|
||||
//might be negative
|
||||
const FloatV dist = V3Dot(q, planeNormal);
|
||||
|
||||
const BoolV con0 = FIsGrtrOrEq(eps, FAbs(FSub(dist, planeDist)));
|
||||
|
||||
if (BAllEqTTTT(con0))
|
||||
{
|
||||
calculateContactInformation(aBuf, bBuf, facet, a, b, takeCoreShape, output);
|
||||
|
||||
if (takeCoreShape)
|
||||
{
|
||||
const FloatV toleranceEps = FMul(FLoad(1e-3f), tolerenceLength);
|
||||
const Vec3V dif = V3Sub(output.closestA, output.closestB);
|
||||
const FloatV pen = FAdd(FAbs(output.penDep), toleranceEps);
|
||||
const FloatV sqDif = V3Dot(dif, dif);
|
||||
const FloatV length = FSel(FIsGrtr(sqDif, zero), FSqrt(sqDif), zero);
|
||||
if (FAllGrtr(length, pen))
|
||||
return EPA_DEGENERATE;
|
||||
}
|
||||
return EPA_CONTACT;
|
||||
|
||||
}
|
||||
|
||||
//update the upper bound to the minimum between existing upper bound and the distance
|
||||
upper_bound = FMin(upper_bound, dist);
|
||||
|
||||
aBuf[numVertsLocal]=tempa;
|
||||
bBuf[numVertsLocal]=tempb;
|
||||
|
||||
const PxU32 index = PxU32(numVertsLocal++);
|
||||
|
||||
// Compute the silhouette cast by the new vertex
|
||||
// Note that the new vertex is on the positive side
|
||||
// of the current facet, so the current facet will
|
||||
// not be in the polytope. Start local search
|
||||
// from this facet.
|
||||
|
||||
edgeBuffer.MakeEmpty();
|
||||
|
||||
facet->silhouette(q, aBuf, bBuf, edgeBuffer, facetManager);
|
||||
|
||||
if (!edgeBuffer.IsValid())
|
||||
{
|
||||
calculateContactInformation(aBuf, bBuf, facet, a, b, takeCoreShape, output);
|
||||
return EPA_DEGENERATE;
|
||||
}
|
||||
|
||||
Edge* PX_RESTRICT edge=edgeBuffer.Get(0);
|
||||
|
||||
PxU32 bufferSize=edgeBuffer.Size();
|
||||
|
||||
//check to see whether we have enough space in the facet manager to create new facets
|
||||
if(bufferSize > facetManager.getNumRemainingIDs())
|
||||
{
|
||||
calculateContactInformation(aBuf, bBuf, facet, a, b, takeCoreShape, output);
|
||||
return EPA_DEGENERATE;
|
||||
}
|
||||
|
||||
Facet *firstFacet = addFacet(edge->getTarget(), edge->getSource(),index, upper_bound);
|
||||
PX_ASSERT(firstFacet);
|
||||
firstFacet->link(0, edge->getFacet(), edge->getIndex());
|
||||
|
||||
Facet * PX_RESTRICT lastFacet = firstFacet;
|
||||
|
||||
#if EPA_DEBUG
|
||||
bool degenerate = false;
|
||||
for(PxU32 i=1; (i<bufferSize) && (!degenerate); ++i)
|
||||
{
|
||||
edge=edgeBuffer.Get(i);
|
||||
Facet* PX_RESTRICT newFacet = addFacet(edge->getTarget(), edge->getSource(),index, upper_bound);
|
||||
PX_ASSERT(newFacet);
|
||||
const bool b0 = newFacet->link(0, edge->getFacet(), edge->getIndex());
|
||||
const bool b1 = newFacet->link(2, lastFacet, 1);
|
||||
degenerate = degenerate || !b0 || !b1;
|
||||
lastFacet = newFacet;
|
||||
}
|
||||
|
||||
if (degenerate)
|
||||
PxDebugBreak();
|
||||
#else
|
||||
for (PxU32 i = 1; i<bufferSize; ++i)
|
||||
{
|
||||
edge = edgeBuffer.Get(i);
|
||||
Facet* PX_RESTRICT newFacet = addFacet(edge->getTarget(), edge->getSource(), index, upper_bound);
|
||||
newFacet->link(0, edge->getFacet(), edge->getIndex());
|
||||
newFacet->link(2, lastFacet, 1);
|
||||
lastFacet = newFacet;
|
||||
}
|
||||
#endif
|
||||
|
||||
firstFacet->link(2, lastFacet, 1);
|
||||
}
|
||||
facetManager.freeID(facet->m_FacetId);
|
||||
|
||||
}
|
||||
while((heap.size() > 0) && FAllGrtr(upper_bound, heap.top()->getPlaneDist()) && numVertsLocal != MaxSupportPoints);
|
||||
|
||||
calculateContactInformation(aBuf, bBuf, facet, a, b, takeCoreShape, output);
|
||||
return EPA_DEGENERATE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
68
engine/third_party/physx/source/geomutils/src/gjk/GuEPA.h
vendored
Normal file
68
engine/third_party/physx/source/geomutils/src/gjk/GuEPA.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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_EPA_H
|
||||
#define GU_EPA_H
|
||||
|
||||
#include "GuGJKUtil.h"
|
||||
#include "GuGJKType.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
//ML: The main entry point for EPA.
|
||||
//
|
||||
//This function returns one of three status codes:
|
||||
//(1)EPA_FAIL: the algorithm failed to create a valid polytope(the origin wasn't inside the polytope) from the input simplex.
|
||||
//(2)EPA_CONTACT : the algorithm found the MTD and converged successfully.
|
||||
//(3)EPA_DEGENERATE: the algorithm cannot make further progress and the result is unknown.
|
||||
|
||||
GjkStatus epaPenetration( const GjkConvex& a, //convex a in the space of convex b
|
||||
const GjkConvex& b, //convex b
|
||||
const PxU8* PX_RESTRICT aInd, //warm start index for convex a to create an initial simplex
|
||||
const PxU8* PX_RESTRICT bInd, //warm start index for convex b to create an initial simplex
|
||||
const PxU8 size, //number of warm-start indices
|
||||
const bool takeCoreShape, //indicates whether we take support point from the core shape or surface of capsule/sphere
|
||||
const aos::FloatV tolerenceLength, //the length of meter
|
||||
GjkOutput& output); //result
|
||||
|
||||
GjkStatus epaPenetration( const GjkConvex& a, //convex a in the space of convex b
|
||||
const GjkConvex& b, //convex b
|
||||
const aos::Vec3V* PX_RESTRICT aPnt, //warm start point for convex a to create an initial simplex
|
||||
const aos::Vec3V* PX_RESTRICT bPnt, //warm start point for convex b to create an initial simplex
|
||||
const PxU8 size, //number of warm-start indices
|
||||
const bool takeCoreShape, //indicates whether we take support point from the core shape or surface of capsule/sphere
|
||||
const aos::FloatV tolerenceLength, //the length of meter
|
||||
GjkOutput& output); //result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
304
engine/third_party/physx/source/geomutils/src/gjk/GuEPAFacet.h
vendored
Normal file
304
engine/third_party/physx/source/geomutils/src/gjk/GuEPAFacet.h
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
// 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_EPA_FACET_H
|
||||
#define GU_EPA_FACET_H
|
||||
|
||||
#include "foundation/PxVecMath.h"
|
||||
#include "foundation/PxFPU.h"
|
||||
#include "foundation/PxUtilities.h"
|
||||
#include "CmIDPool.h"
|
||||
|
||||
#if (defined __GNUC__ && defined _DEBUG)
|
||||
#define PX_EPA_FORCE_INLINE
|
||||
#else
|
||||
#define PX_EPA_FORCE_INLINE PX_FORCE_INLINE
|
||||
#endif
|
||||
|
||||
#define EPA_DEBUG 0
|
||||
|
||||
namespace physx
|
||||
{
|
||||
#define MaxEdges 32
|
||||
#define MaxFacets 64
|
||||
#define MaxSupportPoints 64
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
const PxU32 lookUp[3] = {1, 2, 0};
|
||||
|
||||
PX_FORCE_INLINE PxU32 incMod3(PxU32 i) { return lookUp[i]; }
|
||||
|
||||
class EdgeBuffer;
|
||||
class Edge;
|
||||
typedef Cm::InlineDeferredIDPool<MaxFacets> EPAFacetManager;
|
||||
|
||||
class Facet
|
||||
{
|
||||
public:
|
||||
|
||||
Facet()
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE Facet(const PxU32 _i0, const PxU32 _i1, const PxU32 _i2)
|
||||
: m_obsolete(false), m_inHeap(false)
|
||||
{
|
||||
m_indices[0]= PxToI8(_i0);
|
||||
m_indices[1]= PxToI8(_i1);
|
||||
m_indices[2]= PxToI8(_i2);
|
||||
|
||||
m_adjFacets[0] = m_adjFacets[1] = m_adjFacets[2] = NULL;
|
||||
m_adjEdges[0] = m_adjEdges[1] = m_adjEdges[2] = -1;
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void invalidate()
|
||||
{
|
||||
m_adjFacets[0] = m_adjFacets[1] = m_adjFacets[2] = NULL;
|
||||
m_adjEdges[0] = m_adjEdges[1] = m_adjEdges[2] = -1;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool Valid()
|
||||
{
|
||||
return (m_adjFacets[0] != NULL) & (m_adjFacets[1] != NULL) & (m_adjFacets[2] != NULL);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU32 operator[](const PxU32 i) const
|
||||
{
|
||||
return PxU32(m_indices[i]);
|
||||
}
|
||||
|
||||
//create ajacency information
|
||||
bool link(const PxU32 edge0, Facet* PX_RESTRICT facet, const PxU32 edge1);
|
||||
|
||||
PX_FORCE_INLINE bool isObsolete() const { return m_obsolete; }
|
||||
|
||||
//calculate the signed distance from a point to a plane
|
||||
PX_FORCE_INLINE aos::FloatV getPlaneDist(const aos::Vec3VArg p, const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf) const;
|
||||
|
||||
//check to see whether the triangle is a valid triangle, calculate plane normal and plane distance at the same time
|
||||
aos::BoolV isValid2(const PxU32 i0, const PxU32 i1, const PxU32 i2, const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf,
|
||||
const aos::FloatVArg upper);
|
||||
|
||||
//return the absolute value for the plane distance from origin
|
||||
PX_FORCE_INLINE aos::FloatV getPlaneDist() const
|
||||
{
|
||||
return aos::FLoad(m_planeDist);
|
||||
}
|
||||
|
||||
//return the plane normal
|
||||
PX_FORCE_INLINE aos::Vec3V getPlaneNormal()const
|
||||
{
|
||||
return m_planeNormal;
|
||||
}
|
||||
|
||||
//calculate the closest points for a shape pair
|
||||
void getClosestPoint(const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf, aos::Vec3V& closestA,
|
||||
aos::Vec3V& closestB);
|
||||
|
||||
//calculate the closest points for a shape pair
|
||||
//void getClosestPoint(const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf, aos::FloatV& v, aos::FloatV& w);
|
||||
|
||||
//performs a flood fill over the boundary of the current polytope.
|
||||
void silhouette(const aos::Vec3VArg w, const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf, EdgeBuffer& edgeBuffer, EPAFacetManager& manager);
|
||||
|
||||
|
||||
//m_planeDist is positive
|
||||
bool operator <(const Facet& b) const
|
||||
{
|
||||
return m_planeDist < b.m_planeDist;
|
||||
}
|
||||
|
||||
//store all the boundary facets for the new polytope in the edgeBuffer and free indices when an old facet isn't part of the boundary anymore
|
||||
PX_FORCE_INLINE void silhouette(const PxU32 index, const aos::Vec3VArg w, const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf, EdgeBuffer& edgeBuffer,
|
||||
EPAFacetManager& manager);
|
||||
|
||||
aos::Vec3V m_planeNormal; //16
|
||||
PxF32 m_planeDist;
|
||||
#if EPA_DEBUG
|
||||
PxF32 m_lambda1;
|
||||
PxF32 m_lambda2;
|
||||
#endif
|
||||
|
||||
Facet* PX_RESTRICT m_adjFacets[3]; //the triangle adjacent to edge i in this triangle //32
|
||||
PxI8 m_adjEdges[3]; //the edge connected with the corresponding triangle //35
|
||||
PxI8 m_indices[3]; //the index of vertices of the triangle //38
|
||||
bool m_obsolete; //a flag to denote whether the triangle are still part of the bundeary of the new polytope //39
|
||||
bool m_inHeap; //a flag to indicate whether the triangle is in the heap //40
|
||||
PxU8 m_FacetId; //41 //73
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Edge
|
||||
{
|
||||
public:
|
||||
PX_FORCE_INLINE Edge() {}
|
||||
PX_FORCE_INLINE Edge(Facet * PX_RESTRICT facet, const PxU32 index) : m_facet(facet), m_index(index) {}
|
||||
PX_FORCE_INLINE Edge(const Edge& other) : m_facet(other.m_facet), m_index(other.m_index){}
|
||||
|
||||
PX_FORCE_INLINE Edge& operator = (const Edge& other)
|
||||
{
|
||||
m_facet = other.m_facet;
|
||||
m_index = other.m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE Facet *getFacet() const { return m_facet; }
|
||||
PX_FORCE_INLINE PxU32 getIndex() const { return m_index; }
|
||||
|
||||
//get out the associated start vertex index in this edge from the facet
|
||||
PX_FORCE_INLINE PxU32 getSource() const
|
||||
{
|
||||
PX_ASSERT(m_index < 3);
|
||||
return (*m_facet)[m_index];
|
||||
}
|
||||
|
||||
//get out the associated end vertex index in this edge from the facet
|
||||
PX_FORCE_INLINE PxU32 getTarget() const
|
||||
{
|
||||
PX_ASSERT(m_index < 3);
|
||||
return (*m_facet)[incMod3(m_index)];
|
||||
}
|
||||
|
||||
Facet* PX_RESTRICT m_facet;
|
||||
PxU32 m_index;
|
||||
};
|
||||
|
||||
|
||||
class EdgeBuffer
|
||||
{
|
||||
public:
|
||||
EdgeBuffer() : m_Size(0), m_OverFlow(false)
|
||||
{
|
||||
}
|
||||
|
||||
Edge* Insert(Facet* PX_RESTRICT facet, const PxU32 index)
|
||||
{
|
||||
if (m_Size < MaxEdges)
|
||||
{
|
||||
Edge* pEdge = &m_pEdges[m_Size++];
|
||||
pEdge->m_facet = facet;
|
||||
pEdge->m_index = index;
|
||||
return pEdge;
|
||||
}
|
||||
m_OverFlow = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Edge* Get(const PxU32 index)
|
||||
{
|
||||
PX_ASSERT(index < m_Size);
|
||||
return &m_pEdges[index];
|
||||
}
|
||||
|
||||
PxU32 Size()
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
|
||||
bool IsValid()
|
||||
{
|
||||
return m_Size > 0 && !m_OverFlow;
|
||||
}
|
||||
|
||||
void MakeEmpty()
|
||||
{
|
||||
m_Size = 0;
|
||||
m_OverFlow = false;
|
||||
}
|
||||
|
||||
Edge m_pEdges[MaxEdges];
|
||||
PxU32 m_Size;
|
||||
bool m_OverFlow;
|
||||
};
|
||||
|
||||
//ML: calculate MTD points for a shape pair
|
||||
PX_FORCE_INLINE void Facet::getClosestPoint(const aos::Vec3V* PX_RESTRICT aBuf, const aos::Vec3V* PX_RESTRICT bBuf, aos::Vec3V& closestA,
|
||||
aos::Vec3V& closestB)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const Vec3V pa0(aBuf[m_indices[0]]);
|
||||
const Vec3V pa1(aBuf[m_indices[1]]);
|
||||
const Vec3V pa2(aBuf[m_indices[2]]);
|
||||
|
||||
const Vec3V pb0(bBuf[m_indices[0]]);
|
||||
const Vec3V pb1(bBuf[m_indices[1]]);
|
||||
const Vec3V pb2(bBuf[m_indices[2]]);
|
||||
|
||||
const Vec3V p0 = V3Sub(pa0, pb0);
|
||||
const Vec3V p1 = V3Sub(pa1, pb1);
|
||||
const Vec3V p2 = V3Sub(pa2, pb2);
|
||||
|
||||
const Vec3V v0 = V3Sub(p1, p0);
|
||||
const Vec3V v1 = V3Sub(p2, p0);
|
||||
|
||||
const Vec3V closestP = V3Scale(m_planeNormal, FLoad(m_planeDist));
|
||||
const Vec3V v2 = V3Sub(closestP, p0);
|
||||
//calculate barycentric coordinates
|
||||
const FloatV d00 = V3Dot(v0, v0);
|
||||
const FloatV d01 = V3Dot(v0, v1);
|
||||
const FloatV d11 = V3Dot(v1, v1);
|
||||
|
||||
const FloatV d20 = V3Dot(v2, v0);
|
||||
const FloatV d21 = V3Dot(v2, v1);
|
||||
|
||||
const FloatV det = FNegScaleSub(d01, d01, FMul(d00, d11));//FSub( FMul(v1dv1, v2dv2), FMul(v1dv2, v1dv2) ); // non-negative
|
||||
const FloatV recip = FSel(FIsGrtr(det, FEps()), FRecip(det), FZero());
|
||||
|
||||
const FloatV lambda1 = FMul(FNegScaleSub(d01, d21, FMul(d11, d20)), recip);
|
||||
const FloatV lambda2 = FMul(FNegScaleSub(d01, d20, FMul(d00, d21)), recip);
|
||||
|
||||
#if EPA_DEBUG
|
||||
FStore(lambda1, &m_lambda1);
|
||||
FStore(lambda2, &m_lambda2);
|
||||
#endif
|
||||
|
||||
const FloatV u = FSub(FOne(), FAdd(lambda1, lambda2));
|
||||
closestA = V3ScaleAdd(pa0, u, V3ScaleAdd(pa1, lambda1, V3Scale(pa2, lambda2)));
|
||||
closestB = V3ScaleAdd(pb0, u, V3ScaleAdd(pb1, lambda1, V3Scale(pb2, lambda2)));
|
||||
}
|
||||
|
||||
//ML: create adjacency informations for both facets
|
||||
PX_FORCE_INLINE bool Facet::link(const PxU32 edge0, Facet * PX_RESTRICT facet, const PxU32 edge1)
|
||||
{
|
||||
m_adjFacets[edge0] = facet;
|
||||
m_adjEdges[edge0] = PxToI8(edge1);
|
||||
facet->m_adjFacets[edge1] = this;
|
||||
facet->m_adjEdges[edge1] = PxToI8(edge0);
|
||||
|
||||
return (m_indices[edge0] == facet->m_indices[incMod3(edge1)]) && (m_indices[incMod3(edge0)] == facet->m_indices[edge1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
218
engine/third_party/physx/source/geomutils/src/gjk/GuGJK.h
vendored
Normal file
218
engine/third_party/physx/source/geomutils/src/gjk/GuGJK.h
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
// 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_GJK_H
|
||||
#define GU_GJK_H
|
||||
|
||||
|
||||
#include "GuGJKType.h"
|
||||
#include "GuGJKUtil.h"
|
||||
#include "GuConvexSupportTable.h"
|
||||
#include "GuGJKSimplex.h"
|
||||
#include "foundation/PxFPU.h"
|
||||
|
||||
#define GJK_SEPERATING_AXIS_VALIDATE 0
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
|
||||
class ConvexV;
|
||||
|
||||
#if GJK_SEPERATING_AXIS_VALIDATE
|
||||
template<typename ConvexA, typename ConvexB>
|
||||
static void validateSeparatingAxis(const ConvexA& a, const ConvexB& b, const aos::Vec3VArg separatingAxis)
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V minV0 = a.ConvexA::support(V3Neg(separatingAxis));
|
||||
const Vec3V maxV0 = a.ConvexA::support(separatingAxis);
|
||||
|
||||
const Vec3V minV1 = b.ConvexB::support(V3Neg(separatingAxis));
|
||||
const Vec3V maxV1 = b.ConvexB::support(separatingAxis);
|
||||
|
||||
const FloatV min0 = V3Dot(minV0, separatingAxis);
|
||||
const FloatV max0 = V3Dot(maxV0, separatingAxis);
|
||||
|
||||
const FloatV min1 = V3Dot(minV1, separatingAxis);
|
||||
const FloatV max1 = V3Dot(maxV1, separatingAxis);
|
||||
|
||||
PX_ASSERT(FAllGrtr(min1, max0) || FAllGrtr(min0, max1));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
initialSearchDir :initial search direction in the mincowsky sum, it should be in the local space of ConvexB
|
||||
closestA :it is the closest point in ConvexA in the local space of ConvexB if acceptance threshold is sufficent large. Otherwise, it will be garbage
|
||||
closestB :it is the closest point in ConvexB in the local space of ConvexB if acceptance threshold is sufficent large. Otherwise, it will be garbage
|
||||
normal :normal pointing from ConvexA to ConvexB in the local space of ConvexB if acceptance threshold is sufficent large. Otherwise, it will be garbage
|
||||
distance :the distance of the closest points between ConvexA and ConvexB if acceptance threshold is sufficent large. Otherwise, it will be garbage
|
||||
contactDist :the distance which we will generate contact information if ConvexA and ConvexB are both separated within contactDist
|
||||
*/
|
||||
|
||||
//*Each convex has
|
||||
//* a support function
|
||||
//* a margin - the amount by which we shrunk the shape for a convex or box. If the shape are sphere/capsule, margin is the radius
|
||||
//* a minMargin - some percentage of margin, which is used to determine the termination condition for gjk
|
||||
|
||||
//*We'll report:
|
||||
//* GJK_NON_INTERSECT if the sign distance between the shapes is greater than the sum of the margins and the the contactDistance
|
||||
//* GJK_CLOSE if the minimum distance between the shapes is less than the sum of the margins and the the contactDistance
|
||||
//* GJK_CONTACT if the two shapes are overlapped with each other
|
||||
template<typename ConvexA, typename ConvexB>
|
||||
GjkStatus gjk(const ConvexA& a, const ConvexB& b, const aos::Vec3V& initialSearchDir, const aos::FloatV& contactDist, aos::Vec3V& closestA, aos::Vec3V& closestB, aos::Vec3V& normal,
|
||||
aos::FloatV& distance)
|
||||
{
|
||||
using namespace aos;
|
||||
Vec3V Q[4];
|
||||
Vec3V A[4];
|
||||
Vec3V B[4];
|
||||
|
||||
const FloatV zero = FZero();
|
||||
PxU32 size=0;
|
||||
|
||||
//const Vec3V _initialSearchDir = aToB.p;
|
||||
Vec3V closest = V3Sel(FIsGrtr(V3Dot(initialSearchDir, initialSearchDir), zero), initialSearchDir, V3UnitX());
|
||||
Vec3V v = V3Normalize(closest);
|
||||
|
||||
// ML: eps2 is the square value of an epsilon value which applied in the termination condition for two shapes overlap.
|
||||
// GJK will terminate based on sq(v) < eps and indicate that two shapes are overlapping.
|
||||
// we calculate the eps based on 10% of the minimum margin of two shapes
|
||||
const FloatV tenPerc = FLoad(0.1f);
|
||||
const FloatV minMargin = FMin(a.getMinMargin(), b.getMinMargin());
|
||||
const FloatV eps = FMax(FLoad(1e-6f), FMul(minMargin, tenPerc));
|
||||
|
||||
// ML:epsRel is square value of 1.5% which applied to the distance of a closest point(v) to the origin.
|
||||
// If |v|- v/|v|.dot(w) < epsRel*|v|,
|
||||
// two shapes are clearly separated, GJK terminate and return non intersect.
|
||||
// This adjusts the termination condition based on the length of v
|
||||
// which avoids ill-conditioned terminations.
|
||||
const FloatV epsRel = FLoad(0.000225f);//1.5%.
|
||||
|
||||
FloatV dist = FMax();
|
||||
FloatV prevDist;
|
||||
Vec3V prevClos, prevDir;
|
||||
|
||||
const BoolV bTrue = BTTTT();
|
||||
BoolV bNotTerminated = bTrue;
|
||||
BoolV bNotDegenerated = bTrue;
|
||||
|
||||
//ML: we treate sphere as a point and capsule as segment in the support function, so that we need to add on radius
|
||||
const BoolV aQuadratic = a.isMarginEqRadius();
|
||||
const BoolV bQuadratic = b.isMarginEqRadius();
|
||||
|
||||
const FloatV sumMargin = FAdd(FSel(aQuadratic, a.getMargin(), zero), FSel(bQuadratic, b.getMargin(), zero));
|
||||
const FloatV separatingDist = FAdd(sumMargin, contactDist);
|
||||
const FloatV relDif = FSub(FOne(), epsRel);
|
||||
|
||||
do
|
||||
{
|
||||
prevDist = dist;
|
||||
prevClos = closest;
|
||||
prevDir = v;
|
||||
|
||||
//de-virtualize, we don't need to use a normalize direction to get the support point
|
||||
//this will allow the cpu better pipeline the normalize calculation while it does the
|
||||
//support map
|
||||
const Vec3V supportA=a.ConvexA::support(V3Neg(closest));
|
||||
const Vec3V supportB=b.ConvexB::support(closest);
|
||||
|
||||
//calculate the support point
|
||||
const Vec3V support = V3Sub(supportA, supportB);
|
||||
|
||||
const FloatV signDist = V3Dot(v, support);
|
||||
|
||||
if(FAllGrtr(signDist, separatingDist))
|
||||
{
|
||||
//ML:gjk found a separating axis for these two objects and the distance is large than the seperating distance, gjk might not converge so that
|
||||
//we won't generate contact information
|
||||
#if GJK_SEPERATING_AXIS_VALIDATE
|
||||
validateSeparatingAxis(a, b, v);
|
||||
#endif
|
||||
return GJK_NON_INTERSECT;
|
||||
}
|
||||
|
||||
const BoolV con = BAnd(FIsGrtr(signDist, sumMargin), FIsGrtr(signDist, FMul(relDif, dist)));
|
||||
|
||||
if(BAllEqTTTT(con))
|
||||
{
|
||||
//ML:: gjk converge and we get the closest point information
|
||||
Vec3V closA, closB;
|
||||
//normal point from A to B
|
||||
const Vec3V n = V3Neg(v);
|
||||
getClosestPoint(Q, A, B, closest, closA, closB, size);
|
||||
closestA = V3Sel(aQuadratic, V3ScaleAdd(n, a.getMargin(), closA), closA);
|
||||
closestB = V3Sel(bQuadratic, V3NegScaleSub(n, b.getMargin(), closB), closB);
|
||||
distance = FMax(zero, FSub(dist, sumMargin));
|
||||
normal = n;//V3Normalize(V3Neg(closest));
|
||||
return GJK_CLOSE;
|
||||
}
|
||||
|
||||
PX_ASSERT(size < 4);
|
||||
A[size]=supportA;
|
||||
B[size]=supportB;
|
||||
Q[size++]=support;
|
||||
|
||||
//calculate the closest point between two convex hull
|
||||
closest = GJKCPairDoSimplex(Q, A, B, support, size);
|
||||
|
||||
dist = V3Length(closest);
|
||||
v = V3ScaleInv(closest, FMax(dist, FEps()));
|
||||
bNotDegenerated = FIsGrtr(prevDist, dist);
|
||||
bNotTerminated = BAnd(FIsGrtr(dist, eps), bNotDegenerated);
|
||||
}while(BAllEqTTTT(bNotTerminated));
|
||||
|
||||
if(BAllEqTTTT(bNotDegenerated))
|
||||
{
|
||||
//GJK_CONTACT
|
||||
distance = zero;
|
||||
return GJK_CONTACT;
|
||||
}
|
||||
|
||||
//GJK degenerated, use the previous closest point
|
||||
const FloatV acceptancePerc = FLoad(0.2f);
|
||||
const FloatV acceptanceMargin = FMul(acceptancePerc, FMin(a.getMargin(), b.getMargin()));
|
||||
const FloatV acceptanceDist = FSel(FIsGrtr(sumMargin, zero), sumMargin, acceptanceMargin);
|
||||
Vec3V closA, closB;
|
||||
const Vec3V n = V3Neg(prevDir);//V3Normalize(V3Neg(prevClos));
|
||||
getClosestPoint(Q, A, B, prevClos, closA, closB, size);
|
||||
closestA = V3Sel(aQuadratic, V3ScaleAdd(n, a.getMargin(), closA), closA);
|
||||
closestB = V3Sel(bQuadratic, V3NegScaleSub(n, b.getMargin(), closB), closB);
|
||||
normal = n;
|
||||
dist = FMax(zero, FSub(prevDist, sumMargin));
|
||||
distance = dist;
|
||||
|
||||
return FAllGrtr(dist, acceptanceDist) ? GJK_CLOSE: GJK_CONTACT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
329
engine/third_party/physx/source/geomutils/src/gjk/GuGJKPenetration.h
vendored
Normal file
329
engine/third_party/physx/source/geomutils/src/gjk/GuGJKPenetration.h
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
// 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_GJK_PENETRATION_H
|
||||
#define GU_GJK_PENETRATION_H
|
||||
|
||||
|
||||
#include "GuConvexSupportTable.h"
|
||||
#include "GuGJKSimplex.h"
|
||||
#include "GuVecConvexHullNoScale.h"
|
||||
#include "GuGJKUtil.h"
|
||||
#include "foundation/PxUtilities.h"
|
||||
#include "GuGJKType.h"
|
||||
|
||||
#define GJK_VALIDATE 0
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
class ConvexV;
|
||||
|
||||
PX_FORCE_INLINE void assignWarmStartValue(PxU8* PX_RESTRICT aIndices, PxU8* PX_RESTRICT bIndices, PxU8& size_, PxI32* PX_RESTRICT aInd, PxI32* PX_RESTRICT bInd, PxU32 size )
|
||||
{
|
||||
if(aIndices)
|
||||
{
|
||||
PX_ASSERT(bIndices);
|
||||
size_ = PxTo8(size);
|
||||
for(PxU32 i=0; i<size; ++i)
|
||||
{
|
||||
aIndices[i] = PxTo8(aInd[i]);
|
||||
bIndices[i] = PxTo8(bInd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void validateDuplicateVertex(const aos::Vec3V* Q, const aos::Vec3VArg support, const PxU32 size)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const FloatV eps = FEps();
|
||||
//Get rid of the duplicate point
|
||||
BoolV match = BFFFF();
|
||||
for(PxU32 na = 0; na < size; ++na)
|
||||
{
|
||||
Vec3V dif = V3Sub(Q[na], support);
|
||||
match = BOr(match, FIsGrtr(eps, V3Dot(dif, dif)));
|
||||
}
|
||||
|
||||
//we have duplicate code
|
||||
if(BAllEqTTTT(match))
|
||||
{
|
||||
PX_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
//*Each convex has
|
||||
//* a support function
|
||||
//* a margin - if the shape is sphere/capsule, margin is the radius
|
||||
//* a minMargin - some percentage of margin, which is used to determine the termination condition for gjk
|
||||
|
||||
//*We'll report:
|
||||
//* GJK_NON_INTERSECT if the minimum distance between the shapes is greater than the sum of the margins and the the contactDistance
|
||||
//* EPA_CONTACT if shapes overlap. We treat sphere/capsule as a point/a segment and we shrunk other shapes by 10% of margin
|
||||
//* GJK_CONTACT if the algorithm converges, and the distance between the shapes is less than the sum of the margins plus the contactDistance. In this case we return the closest points found
|
||||
//* GJK_DEGENERATE if the algorithm doesn't converge, we return this flag to indicate the normal and closest point we return might not be accurated
|
||||
template<typename ConvexA, typename ConvexB >
|
||||
PX_NOINLINE GjkStatus gjkPenetration(const ConvexA& a, const ConvexB& b, const aos::Vec3VArg initialSearchDir, const aos::FloatVArg contactDist, const bool takeCoreShape,
|
||||
PxU8* PX_RESTRICT aIndices, PxU8* PX_RESTRICT bIndices, aos::Vec3V* PX_RESTRICT aPoints, aos::Vec3V* PX_RESTRICT bPoints, PxU8& warmStartSize,
|
||||
GjkOutput& output)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
//ML: eps is the threshold that uses to determine whether two (shrunk) shapes overlap. We calculate eps2 based on 10% of the minimum margin of two shapes
|
||||
const FloatV minMargin = FMin(a.ConvexA::getMinMargin(), b.ConvexB::getMinMargin());
|
||||
const FloatV eps = FMul(minMargin, FLoad(0.1f));
|
||||
|
||||
//const FloatV eps2 = FMul(_eps2, _eps2);
|
||||
//ML: epsRel2 is the square of 0.01. This is used to scale the square distance of a closest point to origin to determine whether two shrunk shapes overlap in the margin, but
|
||||
//they don't overlap.
|
||||
//const FloatV epsRel2 = FMax(FLoad(0.0001), eps2);
|
||||
|
||||
// ML:epsRel is square value of 1.5% which applied to the distance of a closest point(v) to the origin.
|
||||
// If |v|- v/|v|.dot(w) < epsRel*|v|=>(|v|*(1-epsRel) < v/|v|.dot(w)),
|
||||
// two shapes are clearly separated, GJK terminate and return non intersect.
|
||||
// This adjusts the termination condition based on the length of v
|
||||
// which avoids ill-conditioned terminations.
|
||||
const FloatV epsRel = FLoad(0.000225f);//1.5%.
|
||||
const FloatV relDif = FSub(FOne(), epsRel);
|
||||
|
||||
const FloatV zero = FZero();
|
||||
|
||||
//capsule/sphere will have margin which is its radius
|
||||
const FloatV marginA = a.getMargin();
|
||||
const FloatV marginB = b.getMargin();
|
||||
|
||||
const BoolV aQuadratic = a.isMarginEqRadius();
|
||||
const BoolV bQuadratic = b.isMarginEqRadius();
|
||||
const FloatV tMarginA = FSel(aQuadratic, marginA, zero);
|
||||
const FloatV tMarginB = FSel(bQuadratic, marginB, zero);
|
||||
|
||||
const FloatV sumMargin = FAdd(tMarginA, tMarginB);
|
||||
const FloatV sumExpandedMargin = FAdd(sumMargin, contactDist);
|
||||
|
||||
FloatV dist = FMax();
|
||||
FloatV prevDist = dist;
|
||||
const Vec3V zeroV = V3Zero();
|
||||
Vec3V prevClos = zeroV;
|
||||
|
||||
const BoolV bTrue = BTTTT();
|
||||
BoolV bNotTerminated = bTrue;
|
||||
BoolV bNotDegenerated = bTrue;
|
||||
Vec3V closest;
|
||||
|
||||
Vec3V Q[4];
|
||||
Vec3V* A = aPoints;
|
||||
Vec3V* B = bPoints;
|
||||
PxI32 aInd[4];
|
||||
PxI32 bInd[4];
|
||||
Vec3V supportA = zeroV, supportB = zeroV, support=zeroV;
|
||||
Vec3V v;
|
||||
|
||||
PxU32 size = 0;//_size;
|
||||
|
||||
|
||||
//ML: if _size!=0, which means we pass in the previous frame simplex so that we can warm-start the simplex.
|
||||
//In this case, GJK will normally terminate in one iteration
|
||||
if(warmStartSize != 0)
|
||||
{
|
||||
for(PxU32 i=0; i<warmStartSize; ++i)
|
||||
{
|
||||
aInd[i] = aIndices[i];
|
||||
bInd[i] = bIndices[i];
|
||||
|
||||
//de-virtualize
|
||||
supportA = a.ConvexA::supportPoint(aIndices[i]);
|
||||
supportB = b.ConvexB::supportPoint(bIndices[i]);
|
||||
|
||||
support = V3Sub(supportA, supportB);
|
||||
|
||||
#if GJK_VALIDATE
|
||||
//ML: this is used to varify whether we will have duplicate vertices in the warm-start value. If this function get triggered,
|
||||
//this means something isn't right and we need to investigate
|
||||
validateDuplicateVertex(Q, support, size);
|
||||
#endif
|
||||
A[size] = supportA;
|
||||
B[size] = supportB;
|
||||
Q[size++] = support;
|
||||
}
|
||||
|
||||
//run simplex solver to determine whether the point is closest enough so that gjk can terminate
|
||||
closest = GJKCPairDoSimplex(Q, A, B, aInd, bInd, support, size);
|
||||
dist = V3Length(closest);
|
||||
//sDist = V3Dot(closest, closest);
|
||||
v = V3ScaleInv(closest, dist);
|
||||
prevDist = dist;
|
||||
prevClos = closest;
|
||||
|
||||
bNotTerminated = FIsGrtr(dist, eps);
|
||||
}
|
||||
else
|
||||
{
|
||||
//const Vec3V _initialSearchDir = V3Sub(a.getCenter(), b.getCenter());
|
||||
closest = V3Sel(FIsGrtr(V3Dot(initialSearchDir, initialSearchDir), zero), initialSearchDir, V3UnitX());
|
||||
v = V3Normalize(closest);
|
||||
}
|
||||
|
||||
|
||||
// ML : termination condition
|
||||
//(1)two shapes overlap. GJK will terminate based on sq(v) < eps2 and indicate that two shapes are overlapping.
|
||||
//(2)two shapes are separated. If sq(vw) > sqMargin * sq(v), which means the original objects do not intesect, GJK terminate with GJK_NON_INTERSECT.
|
||||
//(3)two shapes don't overlap. However, they interect within margin distance. if sq(v)- vw < epsRel2*sq(v), this means the shrunk shapes interect in the margin,
|
||||
// GJK terminate with GJK_CONTACT.
|
||||
while(BAllEqTTTT(bNotTerminated))
|
||||
{
|
||||
//prevDist, prevClos are used to store the previous iteration's closest point and the square distance from the closest point
|
||||
//to origin in Mincowski space
|
||||
prevDist = dist;
|
||||
prevClos = closest;
|
||||
|
||||
//de-virtualize
|
||||
supportA = a.ConvexA::support(V3Neg(closest), aInd[size]);
|
||||
supportB = b.ConvexB::support(closest, bInd[size]);
|
||||
|
||||
//calculate the support point
|
||||
support = V3Sub(supportA, supportB);
|
||||
|
||||
const FloatV vw = V3Dot(v, support);
|
||||
if(FAllGrtr(vw, sumExpandedMargin))
|
||||
{
|
||||
assignWarmStartValue(aIndices, bIndices, warmStartSize, aInd, bInd, size);
|
||||
return GJK_NON_INTERSECT;
|
||||
}
|
||||
|
||||
//if(FAllGrtr(FMul(epsRel, dist), FSub(dist, vw)))
|
||||
if(FAllGrtr(vw, FMul(dist, relDif)))
|
||||
{
|
||||
assignWarmStartValue(aIndices, bIndices, warmStartSize, aInd, bInd, size);
|
||||
PX_ASSERT(FAllGrtr(dist, FEps()));
|
||||
//const Vec3V n = V3ScaleInv(closest, dist);//normalise
|
||||
output.normal = v;
|
||||
Vec3V closA, closB;
|
||||
getClosestPoint(Q, A, B, closest, closA, closB, size);
|
||||
//ML: if one of the shape is sphere/capsule and the takeCoreShape flag is true, the contact point for sphere/capsule will be the sphere center or a point in the
|
||||
//capsule segment. This will increase the stability for the manifold recycling code. Otherwise, we will return a contact point on the surface for sphere/capsule
|
||||
//while the takeCoreShape flag is set to be false
|
||||
if(takeCoreShape)
|
||||
{
|
||||
output.closestA = closA;
|
||||
output.closestB = closB;
|
||||
output.penDep = dist;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//This is for capsule/sphere want to take the surface point. For box/convex,
|
||||
//we need to get rid of margin
|
||||
output.closestA = V3NegScaleSub(v, tMarginA, closA);
|
||||
output.closestB = V3ScaleAdd(v, tMarginB, closB);
|
||||
output.penDep = FSub(dist, sumMargin);
|
||||
}
|
||||
|
||||
return GJK_CONTACT;
|
||||
}
|
||||
|
||||
A[size] = supportA;
|
||||
B[size] = supportB;
|
||||
Q[size++]=support;
|
||||
PX_ASSERT(size <= 4);
|
||||
|
||||
//calculate the closest point between two convex hull
|
||||
closest = GJKCPairDoSimplex(Q, A, B, aInd, bInd, support, size);
|
||||
|
||||
dist = V3Length(closest);
|
||||
v = V3ScaleInv(closest, dist);
|
||||
|
||||
bNotDegenerated = FIsGrtr(prevDist, dist);
|
||||
bNotTerminated = BAnd(FIsGrtr(dist, eps), bNotDegenerated);
|
||||
}
|
||||
|
||||
if(BAllEqFFFF(bNotDegenerated))
|
||||
{
|
||||
assignWarmStartValue(aIndices, bIndices, warmStartSize, aInd, bInd, size-1);
|
||||
|
||||
//Reset back to older closest point
|
||||
dist = prevDist;
|
||||
closest = prevClos;//V3Sub(closA, closB);
|
||||
Vec3V closA, closB;
|
||||
getClosestPoint(Q, A, B, closest, closA, closB, size);
|
||||
|
||||
//PX_ASSERT(FAllGrtr(dist, FEps()));
|
||||
const Vec3V n = V3ScaleInv(prevClos, prevDist);//normalise
|
||||
output.normal = n;
|
||||
|
||||
output.searchDir = v;
|
||||
|
||||
if(takeCoreShape)
|
||||
{
|
||||
output.closestA = closA;
|
||||
output.closestB = closB;
|
||||
output.penDep = dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
//This is for capsule/sphere want to take the surface point. For box/convex,
|
||||
//we need to get rid of margin
|
||||
output.closestA = V3NegScaleSub(n, tMarginA, closA);
|
||||
output.closestB = V3ScaleAdd(n, tMarginB, closB);
|
||||
output.penDep = FSub(dist, sumMargin);
|
||||
if (FAllGrtrOrEq(sumMargin, dist))
|
||||
return GJK_CONTACT;
|
||||
}
|
||||
|
||||
return GJK_DEGENERATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//this two shapes are deeply intersected with each other, we need to use EPA algorithm to calculate MTD
|
||||
assignWarmStartValue(aIndices, bIndices, warmStartSize, aInd, bInd, size);
|
||||
return EPA_CONTACT;
|
||||
|
||||
}
|
||||
}
|
||||
template<typename ConvexA, typename ConvexB >
|
||||
PX_NOINLINE GjkStatus gjkPenetration(const ConvexA& a, const ConvexB& b, const aos::Vec3VArg initialSearchDir, const aos::FloatVArg contactDist, const bool takeCoreShape,
|
||||
PxU8* PX_RESTRICT aIndices, PxU8* PX_RESTRICT bIndices, PxU8& warmStartSize,
|
||||
GjkOutput& output)
|
||||
{
|
||||
aos::Vec3V aPoints[4], bPoints[4];
|
||||
return gjkPenetration(a, b, initialSearchDir, contactDist, takeCoreShape, aIndices, bIndices, aPoints, bPoints, warmStartSize, output);
|
||||
}
|
||||
template<typename ConvexA, typename ConvexB >
|
||||
PX_NOINLINE GjkStatus gjkPenetration(const ConvexA& a, const ConvexB& b, const aos::Vec3VArg initialSearchDir, const aos::FloatVArg contactDist, const bool takeCoreShape,
|
||||
aos::Vec3V* PX_RESTRICT aPoints, aos::Vec3V* PX_RESTRICT bPoints, PxU8& warmStartSize,
|
||||
GjkOutput& output)
|
||||
{
|
||||
PxU8 aIndices[4], bIndices[4];
|
||||
return gjkPenetration(a, b, initialSearchDir, contactDist, takeCoreShape, aIndices, bIndices, aPoints, bPoints, warmStartSize, output);
|
||||
}
|
||||
}//Gu
|
||||
|
||||
}//physx
|
||||
|
||||
#endif
|
||||
288
engine/third_party/physx/source/geomutils/src/gjk/GuGJKRaycast.h
vendored
Normal file
288
engine/third_party/physx/source/geomutils/src/gjk/GuGJKRaycast.h
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
// 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_GJKRAYCAST_H
|
||||
#define GU_GJKRAYCAST_H
|
||||
|
||||
#include "GuGJKType.h"
|
||||
#include "GuGJKSimplex.h"
|
||||
#include "GuConvexSupportTable.h"
|
||||
#include "GuGJKPenetration.h"
|
||||
#include "GuEPA.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
/*
|
||||
ConvexA is in the local space of ConvexB
|
||||
lambda : the time of impact(TOI)
|
||||
initialLambda : the start time of impact value (disable)
|
||||
s : the sweep ray origin
|
||||
r : the normalized sweep ray direction scaled by the sweep distance. r should be in ConvexB's space
|
||||
normal : the contact normal
|
||||
inflation : the amount by which we inflate the swept shape. If the inflated shapes aren't initially-touching,
|
||||
the TOI will return the time at which both shapes are at a distance equal to inflation separated. If inflation is 0
|
||||
the TOI will return the time at which both shapes are touching.
|
||||
*/
|
||||
template<class ConvexA, class ConvexB>
|
||||
bool gjkRaycast(const ConvexA& a, const ConvexB& b, const aos::Vec3VArg initialDir, const aos::FloatVArg initialLambda, const aos::Vec3VArg s, const aos::Vec3VArg r, aos::FloatV& lambda, aos::Vec3V& normal, aos::Vec3V& closestA, const PxReal _inflation)
|
||||
{
|
||||
PX_UNUSED(initialLambda);
|
||||
|
||||
using namespace aos;
|
||||
|
||||
const FloatV inflation = FLoad(_inflation);
|
||||
const Vec3V zeroV = V3Zero();
|
||||
const FloatV zero = FZero();
|
||||
const FloatV one = FOne();
|
||||
const BoolV bTrue = BTTTT();
|
||||
|
||||
const FloatV maxDist = FLoad(PX_MAX_REAL);
|
||||
|
||||
FloatV _lambda = zero;//initialLambda;
|
||||
Vec3V x = V3ScaleAdd(r, _lambda, s);
|
||||
PxU32 size=1;
|
||||
|
||||
//const Vec3V dir = V3Sub(a.getCenter(), b.getCenter());
|
||||
const Vec3V _initialSearchDir = V3Sel(FIsGrtr(V3Dot(initialDir, initialDir), FEps()), initialDir, V3UnitX());
|
||||
const Vec3V initialSearchDir = V3Normalize(_initialSearchDir);
|
||||
|
||||
const Vec3V initialSupportA(a.ConvexA::support(V3Neg(initialSearchDir)));
|
||||
const Vec3V initialSupportB( b.ConvexB::support(initialSearchDir));
|
||||
|
||||
Vec3V Q[4] = {V3Sub(initialSupportA, initialSupportB), zeroV, zeroV, zeroV}; //simplex set
|
||||
Vec3V A[4] = {initialSupportA, zeroV, zeroV, zeroV}; //ConvexHull a simplex set
|
||||
Vec3V B[4] = {initialSupportB, zeroV, zeroV, zeroV}; //ConvexHull b simplex set
|
||||
|
||||
Vec3V v = V3Neg(Q[0]);
|
||||
Vec3V supportA = initialSupportA;
|
||||
Vec3V supportB = initialSupportB;
|
||||
Vec3V support = Q[0];
|
||||
|
||||
const FloatV minMargin = FMin(a.ConvexA::getSweepMargin(), b.ConvexB::getSweepMargin());
|
||||
const FloatV eps1 = FMul(minMargin, FLoad(0.1f));
|
||||
const FloatV inflationPlusEps(FAdd(eps1, inflation));
|
||||
const FloatV eps2 = FMul(eps1, eps1);
|
||||
|
||||
const FloatV inflation2 = FMul(inflationPlusEps, inflationPlusEps);
|
||||
|
||||
Vec3V clos(Q[0]);
|
||||
Vec3V preClos = clos;
|
||||
//Vec3V closA(initialSupportA);
|
||||
FloatV sDist = V3Dot(v, v);
|
||||
FloatV minDist = sDist;
|
||||
//Vec3V closAA = initialSupportA;
|
||||
//Vec3V closBB = initialSupportB;
|
||||
|
||||
BoolV bNotTerminated = FIsGrtr(sDist, eps2);
|
||||
BoolV bNotDegenerated = bTrue;
|
||||
|
||||
Vec3V nor = v;
|
||||
|
||||
while(BAllEqTTTT(bNotTerminated))
|
||||
{
|
||||
minDist = sDist;
|
||||
preClos = clos;
|
||||
|
||||
const Vec3V vNorm = V3Normalize(v);
|
||||
const Vec3V nvNorm = V3Neg(vNorm);
|
||||
|
||||
supportA=a.ConvexA::support(vNorm);
|
||||
supportB=V3Add(x, b.ConvexB::support(nvNorm));
|
||||
|
||||
//calculate the support point
|
||||
support = V3Sub(supportA, supportB);
|
||||
const Vec3V w = V3Neg(support);
|
||||
const FloatV vw = FSub(V3Dot(vNorm, w), inflationPlusEps);
|
||||
if(FAllGrtr(vw, zero))
|
||||
{
|
||||
const FloatV vr = V3Dot(vNorm, r);
|
||||
if(FAllGrtrOrEq(vr, zero))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const FloatV _oldLambda = _lambda;
|
||||
_lambda = FSub(_lambda, FDiv(vw, vr));
|
||||
if(FAllGrtr(_lambda, _oldLambda))
|
||||
{
|
||||
if(FAllGrtr(_lambda, one))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const Vec3V bPreCenter = x;
|
||||
x = V3ScaleAdd(r, _lambda, s);
|
||||
|
||||
const Vec3V offSet = V3Sub(x, bPreCenter);
|
||||
const Vec3V b0 = V3Add(B[0], offSet);
|
||||
const Vec3V b1 = V3Add(B[1], offSet);
|
||||
const Vec3V b2 = V3Add(B[2], offSet);
|
||||
|
||||
B[0] = b0;
|
||||
B[1] = b1;
|
||||
B[2] = b2;
|
||||
|
||||
Q[0]=V3Sub(A[0], b0);
|
||||
Q[1]=V3Sub(A[1], b1);
|
||||
Q[2]=V3Sub(A[2], b2);
|
||||
|
||||
supportB = V3Add(x, b.ConvexB::support(nvNorm));
|
||||
support = V3Sub(supportA, supportB);
|
||||
minDist = maxDist;
|
||||
nor = v;
|
||||
//size=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PX_ASSERT(size < 4);
|
||||
A[size]=supportA;
|
||||
B[size]=supportB;
|
||||
Q[size++]=support;
|
||||
|
||||
//calculate the closest point between two convex hull
|
||||
clos = GJKCPairDoSimplex(Q, A, B, support, size);
|
||||
v = V3Neg(clos);
|
||||
sDist = V3Dot(clos, clos);
|
||||
|
||||
bNotDegenerated = FIsGrtr(minDist, sDist);
|
||||
bNotTerminated = BAnd(FIsGrtr(sDist, inflation2), bNotDegenerated);
|
||||
}
|
||||
|
||||
const BoolV aQuadratic = a.isMarginEqRadius();
|
||||
//ML:if the Minkowski sum of two objects are too close to the original(eps2 > sDist), we can't take v because we will lose lots of precision. Therefore, we will take
|
||||
//previous configuration's normal which should give us a reasonable approximation. This effectively means that, when we do a sweep with inflation, we always keep v because
|
||||
//the shapes converge separated. If we do a sweep without inflation, we will usually use the previous configuration's normal.
|
||||
nor = V3Sel(BAnd(FIsGrtr(sDist, eps2), bNotDegenerated), v, nor);
|
||||
nor = V3Neg(V3NormalizeSafe(nor, V3Zero()));
|
||||
normal = nor;
|
||||
lambda = _lambda;
|
||||
|
||||
const Vec3V closestP = V3Sel(bNotDegenerated, clos, preClos);
|
||||
Vec3V closA = zeroV, closB = zeroV;
|
||||
getClosestPoint(Q, A, B, closestP, closA, closB, size);
|
||||
closestA = V3Sel(aQuadratic, V3NegScaleSub(nor, a.getMargin(), closA), closA);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ConvexA is in the local space of ConvexB
|
||||
lambda : the time of impact(TOI)
|
||||
initialLambda : the start time of impact value (disable)
|
||||
s : the sweep ray origin in ConvexB's space
|
||||
r : the normalized sweep ray direction scaled by the sweep distance. r should be in ConvexB's space
|
||||
normal : the contact normal in ConvexB's space
|
||||
closestA : the tounching contact in ConvexB's space
|
||||
inflation : the amount by which we inflate the swept shape. If the inflated shapes aren't initially-touching,
|
||||
the TOI will return the time at which both shapes are at a distance equal to inflation separated. If inflation is 0
|
||||
the TOI will return the time at which both shapes are touching.
|
||||
*/
|
||||
template<class ConvexA, class ConvexB>
|
||||
bool gjkRaycastPenetration(const ConvexA& a, const ConvexB& b, const aos::Vec3VArg initialDir, const aos::FloatVArg initialLambda, const aos::Vec3VArg s, const aos::Vec3VArg r, aos::FloatV& lambda,
|
||||
aos::Vec3V& normal, aos::Vec3V& closestA, const PxReal _inflation, const bool initialOverlap)
|
||||
{
|
||||
using namespace aos;
|
||||
Vec3V closA;
|
||||
Vec3V norm;
|
||||
FloatV _lambda;
|
||||
if(gjkRaycast(a, b, initialDir, initialLambda, s, r, _lambda, norm, closA, _inflation))
|
||||
{
|
||||
const FloatV zero = FZero();
|
||||
lambda = _lambda;
|
||||
if(FAllEq(_lambda, zero) && initialOverlap)
|
||||
{
|
||||
//time of impact is zero, the sweep shape is intesect, use epa to get the normal and contact point
|
||||
const FloatV contactDist = getSweepContactEps(a.getMargin(), b.getMargin());
|
||||
|
||||
FloatV sDist(zero);
|
||||
PxU8 aIndices[4];
|
||||
PxU8 bIndices[4];
|
||||
PxU8 size=0;
|
||||
GjkOutput output;
|
||||
|
||||
//PX_COMPILE_TIME_ASSERT(typename Shrink<ConvexB>::Type != Gu::BoxV);
|
||||
|
||||
#ifdef USE_VIRTUAL_GJK
|
||||
GjkStatus status = gjkPenetration<ConvexA, ConvexB>(a, b,
|
||||
#else
|
||||
typename ConvexA::ConvexGeomType convexA = a.getGjkConvex();
|
||||
typename ConvexB::ConvexGeomType convexB = b.getGjkConvex();
|
||||
|
||||
GjkStatus status = gjkPenetration<typename ConvexA::ConvexGeomType, typename ConvexB::ConvexGeomType>(convexA, convexB,
|
||||
#endif
|
||||
initialDir, contactDist, false, aIndices, bIndices, size, output);
|
||||
//norm = V3Neg(norm);
|
||||
if(status == GJK_CONTACT)
|
||||
{
|
||||
closA = output.closestA;
|
||||
sDist = output.penDep;
|
||||
norm = output.normal;
|
||||
}
|
||||
else if(status == EPA_CONTACT)
|
||||
{
|
||||
status = epaPenetration(a, b, aIndices, bIndices, size, false, FLoad(1.f), output);
|
||||
|
||||
if (status == EPA_CONTACT || status == EPA_DEGENERATE)
|
||||
{
|
||||
closA = output.closestA;
|
||||
sDist = output.penDep;
|
||||
norm = output.normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
//ML: if EPA fail, we will use the ray direction as the normal and set pentration to be zero
|
||||
closA = V3Zero();
|
||||
sDist = zero;
|
||||
norm = V3Normalize(V3Neg(r));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//ML:: this will be gjk degenerate case. However, we can still
|
||||
//reply on the previous iteration's closest feature information
|
||||
closA = output.closestA;
|
||||
sDist = output.penDep;
|
||||
norm = output.normal;
|
||||
}
|
||||
lambda = FMin(zero, sDist);
|
||||
}
|
||||
closestA = closA;
|
||||
normal = norm;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
215
engine/third_party/physx/source/geomutils/src/gjk/GuGJKSimplex.cpp
vendored
Normal file
215
engine/third_party/physx/source/geomutils/src/gjk/GuGJKSimplex.cpp
vendored
Normal 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.
|
||||
|
||||
#include "GuGJKSimplex.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
|
||||
using namespace aos;
|
||||
|
||||
static Vec3V getClosestPtPointTriangle(Vec3V* PX_RESTRICT Q, const BoolVArg bIsOutside4, PxU32* indices, PxU32& size)
|
||||
{
|
||||
FloatV bestSqDist = FMax();
|
||||
|
||||
PxU32 _indices[3] = {0, 1, 2};
|
||||
|
||||
Vec3V closestPt = V3Zero();
|
||||
|
||||
if(BAllEqTTTT(BGetX(bIsOutside4)))
|
||||
{
|
||||
//use the original indices, size, v and w
|
||||
bestSqDist = closestPtPointTriangleBaryCentric(Q[0], Q[1], Q[2], indices, size, closestPt);
|
||||
}
|
||||
|
||||
if(BAllEqTTTT(BGetY(bIsOutside4)))
|
||||
{
|
||||
|
||||
PxU32 _size = 3;
|
||||
_indices[0] = 0; _indices[1] = 2; _indices[2] = 3;
|
||||
Vec3V tClosestPt;
|
||||
const FloatV sqDist = closestPtPointTriangleBaryCentric(Q[0], Q[2], Q[3], _indices, _size, tClosestPt);
|
||||
|
||||
const BoolV con = FIsGrtr(bestSqDist, sqDist);
|
||||
if(BAllEqTTTT(con))
|
||||
{
|
||||
closestPt = tClosestPt;
|
||||
bestSqDist = sqDist;
|
||||
|
||||
indices[0] = _indices[0];
|
||||
indices[1] = _indices[1];
|
||||
indices[2] = _indices[2];
|
||||
|
||||
size = _size;
|
||||
}
|
||||
}
|
||||
|
||||
if(BAllEqTTTT(BGetZ(bIsOutside4)))
|
||||
{
|
||||
PxU32 _size = 3;
|
||||
|
||||
_indices[0] = 0; _indices[1] = 3; _indices[2] = 1;
|
||||
|
||||
Vec3V tClosestPt;
|
||||
const FloatV sqDist = closestPtPointTriangleBaryCentric(Q[0], Q[3], Q[1], _indices, _size, tClosestPt);
|
||||
|
||||
const BoolV con = FIsGrtr(bestSqDist, sqDist);
|
||||
if(BAllEqTTTT(con))
|
||||
{
|
||||
closestPt = tClosestPt;
|
||||
bestSqDist = sqDist;
|
||||
|
||||
indices[0] = _indices[0];
|
||||
indices[1] = _indices[1];
|
||||
indices[2] = _indices[2];
|
||||
|
||||
size = _size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(BAllEqTTTT(BGetW(bIsOutside4)))
|
||||
{
|
||||
|
||||
|
||||
PxU32 _size = 3;
|
||||
_indices[0] = 1; _indices[1] = 3; _indices[2] = 2;
|
||||
Vec3V tClosestPt;
|
||||
const FloatV sqDist = closestPtPointTriangleBaryCentric(Q[1], Q[3], Q[2], _indices, _size, tClosestPt);
|
||||
|
||||
const BoolV con = FIsGrtr(bestSqDist, sqDist);
|
||||
|
||||
if(BAllEqTTTT(con))
|
||||
{
|
||||
closestPt = tClosestPt;
|
||||
bestSqDist = sqDist;
|
||||
|
||||
indices[0] = _indices[0];
|
||||
indices[1] = _indices[1];
|
||||
indices[2] = _indices[2];
|
||||
|
||||
size = _size;
|
||||
}
|
||||
}
|
||||
|
||||
return closestPt;
|
||||
}
|
||||
|
||||
PX_NOALIAS Vec3V closestPtPointTetrahedron(Vec3V* PX_RESTRICT Q, Vec3V* PX_RESTRICT A, Vec3V* PX_RESTRICT B, PxU32& size)
|
||||
{
|
||||
|
||||
const FloatV eps = FLoad(1e-4f);
|
||||
const Vec3V a = Q[0];
|
||||
const Vec3V b = Q[1];
|
||||
const Vec3V c = Q[2];
|
||||
const Vec3V d = Q[3];
|
||||
|
||||
//degenerated
|
||||
const Vec3V ab = V3Sub(b, a);
|
||||
const Vec3V ac = V3Sub(c, a);
|
||||
const Vec3V n = V3Normalize(V3Cross(ab, ac));
|
||||
const FloatV signDist = V3Dot(n, V3Sub(d, a));
|
||||
if(FAllGrtr(eps, FAbs(signDist)))
|
||||
{
|
||||
size = 3;
|
||||
return closestPtPointTriangle(Q, A, B, size);
|
||||
}
|
||||
|
||||
const BoolV bIsOutside4 = PointOutsideOfPlane4(a, b, c, d);
|
||||
|
||||
if(BAllEqFFFF(bIsOutside4))
|
||||
{
|
||||
//All inside
|
||||
return V3Zero();
|
||||
}
|
||||
|
||||
PxU32 indices[3] = {0, 1, 2};
|
||||
|
||||
const Vec3V closest = getClosestPtPointTriangle(Q, bIsOutside4, indices, size);
|
||||
|
||||
const Vec3V q0 = Q[indices[0]]; const Vec3V q1 = Q[indices[1]]; const Vec3V q2 = Q[indices[2]];
|
||||
const Vec3V a0 = A[indices[0]]; const Vec3V a1 = A[indices[1]]; const Vec3V a2 = A[indices[2]];
|
||||
const Vec3V b0 = B[indices[0]]; const Vec3V b1 = B[indices[1]]; const Vec3V b2 = B[indices[2]];
|
||||
Q[0] = q0; Q[1] = q1; Q[2] = q2;
|
||||
A[0] = a0; A[1] = a1; A[2] = a2;
|
||||
B[0] = b0; B[1] = b1; B[2] = b2;
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
PX_NOALIAS Vec3V closestPtPointTetrahedron(Vec3V* PX_RESTRICT Q, Vec3V* PX_RESTRICT A, Vec3V* PX_RESTRICT B, PxI32* PX_RESTRICT aInd, PxI32* PX_RESTRICT bInd, PxU32& size)
|
||||
{
|
||||
|
||||
const FloatV eps = FLoad(1e-4f);
|
||||
const Vec3V zeroV = V3Zero();
|
||||
|
||||
const Vec3V a = Q[0];
|
||||
const Vec3V b = Q[1];
|
||||
const Vec3V c = Q[2];
|
||||
const Vec3V d = Q[3];
|
||||
|
||||
//degenerated
|
||||
const Vec3V ab = V3Sub(b, a);
|
||||
const Vec3V ac = V3Sub(c, a);
|
||||
const Vec3V n = V3Normalize(V3Cross(ab, ac));
|
||||
const FloatV signDist = V3Dot(n, V3Sub(d, a));
|
||||
if(FAllGrtr(eps, FAbs(signDist)))
|
||||
{
|
||||
size = 3;
|
||||
return closestPtPointTriangle(Q, A, B, aInd, bInd, size);
|
||||
}
|
||||
|
||||
const BoolV bIsOutside4 = PointOutsideOfPlane4(a, b, c, d);
|
||||
|
||||
if(BAllEqFFFF(bIsOutside4))
|
||||
{
|
||||
//All inside
|
||||
return zeroV;
|
||||
}
|
||||
|
||||
PxU32 indices[3] = {0, 1, 2};
|
||||
const Vec3V closest = getClosestPtPointTriangle(Q, bIsOutside4, indices, size);
|
||||
|
||||
const Vec3V q0 = Q[indices[0]]; const Vec3V q1 = Q[indices[1]]; const Vec3V q2 = Q[indices[2]];
|
||||
const Vec3V a0 = A[indices[0]]; const Vec3V a1 = A[indices[1]]; const Vec3V a2 = A[indices[2]];
|
||||
const Vec3V b0 = B[indices[0]]; const Vec3V b1 = B[indices[1]]; const Vec3V b2 = B[indices[2]];
|
||||
const PxI32 _aInd0 = aInd[indices[0]]; const PxI32 _aInd1 = aInd[indices[1]]; const PxI32 _aInd2 = aInd[indices[2]];
|
||||
const PxI32 _bInd0 = bInd[indices[0]]; const PxI32 _bInd1 = bInd[indices[1]]; const PxI32 _bInd2 = bInd[indices[2]];
|
||||
Q[0] = q0; Q[1] = q1; Q[2] = q2;
|
||||
A[0] = a0; A[1] = a1; A[2] = a2;
|
||||
B[0] = b0; B[1] = b1; B[2] = b2;
|
||||
aInd[0] = _aInd0; aInd[1] = _aInd1; aInd[2] = _aInd2;
|
||||
bInd[0] = _bInd0; bInd[1] = _bInd1; bInd[2] = _bInd2;
|
||||
|
||||
return closest;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
448
engine/third_party/physx/source/geomutils/src/gjk/GuGJKSimplex.h
vendored
Normal file
448
engine/third_party/physx/source/geomutils/src/gjk/GuGJKSimplex.h
vendored
Normal file
@@ -0,0 +1,448 @@
|
||||
// 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_GJKSIMPLEX_H
|
||||
#define GU_GJKSIMPLEX_H
|
||||
|
||||
#include "foundation/PxVecMath.h"
|
||||
#include "GuBarycentricCoordinates.h"
|
||||
|
||||
#if (defined __GNUC__ && defined _DEBUG)
|
||||
#define PX_GJK_INLINE PX_INLINE
|
||||
#define PX_GJK_FORCE_INLINE PX_INLINE
|
||||
#else
|
||||
#define PX_GJK_INLINE PX_INLINE
|
||||
#define PX_GJK_FORCE_INLINE PX_FORCE_INLINE
|
||||
#endif
|
||||
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
PX_NOALIAS aos::Vec3V closestPtPointTetrahedron(aos::Vec3V* PX_RESTRICT Q, aos::Vec3V* PX_RESTRICT A, aos::Vec3V* PX_RESTRICT B, PxU32& size);
|
||||
|
||||
PX_NOALIAS aos::Vec3V closestPtPointTetrahedron(aos::Vec3V* PX_RESTRICT Q, aos::Vec3V* PX_RESTRICT A, aos::Vec3V* PX_RESTRICT B, PxI32* PX_RESTRICT aInd, PxI32* PX_RESTRICT bInd,
|
||||
PxU32& size);
|
||||
|
||||
PX_NOALIAS PX_FORCE_INLINE aos::BoolV PointOutsideOfPlane4(const aos::Vec3VArg _a, const aos::Vec3VArg _b, const aos::Vec3VArg _c, const aos::Vec3VArg _d)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const Vec4V zero = V4Load(0.f);
|
||||
|
||||
const Vec3V ab = V3Sub(_b, _a);
|
||||
const Vec3V ac = V3Sub(_c, _a);
|
||||
const Vec3V ad = V3Sub(_d, _a);
|
||||
const Vec3V bd = V3Sub(_d, _b);
|
||||
const Vec3V bc = V3Sub(_c, _b);
|
||||
|
||||
const Vec3V v0 = V3Cross(ab, ac);
|
||||
const Vec3V v1 = V3Cross(ac, ad);
|
||||
const Vec3V v2 = V3Cross(ad, ab);
|
||||
const Vec3V v3 = V3Cross(bd, bc);
|
||||
|
||||
const FloatV signa0 = V3Dot(v0, _a);
|
||||
const FloatV signa1 = V3Dot(v1, _a);
|
||||
const FloatV signa2 = V3Dot(v2, _a);
|
||||
const FloatV signd3 = V3Dot(v3, _a);
|
||||
|
||||
const FloatV signd0 = V3Dot(v0, _d);
|
||||
const FloatV signd1 = V3Dot(v1, _b);
|
||||
const FloatV signd2 = V3Dot(v2, _c);
|
||||
const FloatV signa3 = V3Dot(v3, _b);
|
||||
|
||||
const Vec4V signa = V4Merge(signa0, signa1, signa2, signa3);
|
||||
const Vec4V signd = V4Merge(signd0, signd1, signd2, signd3);
|
||||
return V4IsGrtrOrEq(V4Mul(signa, signd), zero);//same side, outside of the plane
|
||||
}
|
||||
|
||||
PX_NOALIAS PX_FORCE_INLINE aos::Vec3V closestPtPointSegment(aos::Vec3V* PX_RESTRICT Q, PxU32& size)
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V a = Q[0];
|
||||
const Vec3V b = Q[1];
|
||||
|
||||
//const Vec3V origin = V3Zero();
|
||||
const FloatV zero = FZero();
|
||||
const FloatV one = FOne();
|
||||
|
||||
//Test degenerated case
|
||||
const Vec3V ab = V3Sub(b, a);
|
||||
const FloatV denom = V3Dot(ab, ab);
|
||||
const Vec3V ap = V3Neg(a);//V3Sub(origin, a);
|
||||
const FloatV nom = V3Dot(ap, ab);
|
||||
const BoolV con = FIsGrtrOrEq(FEps(), denom);//FIsEq(denom, zero);
|
||||
//TODO - can we get rid of this branch? The problem is size, which isn't a vector!
|
||||
if(BAllEqTTTT(con))
|
||||
{
|
||||
size = 1;
|
||||
return Q[0];
|
||||
}
|
||||
|
||||
/* const PxU32 count = BAllEq(con, bTrue);
|
||||
size = 2 - count;*/
|
||||
|
||||
const FloatV tValue = FClamp(FDiv(nom, denom), zero, one);
|
||||
return V3ScaleAdd(ab, tValue, a);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void getClosestPoint(const aos::Vec3V* PX_RESTRICT Q, const aos::Vec3V* PX_RESTRICT A, const aos::Vec3V* PX_RESTRICT B, const aos::Vec3VArg closest, aos::Vec3V& closestA, aos::Vec3V& closestB, const PxU32 size)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
switch(size)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
closestA = A[0];
|
||||
closestB = B[0];
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
FloatV v;
|
||||
barycentricCoordinates(closest, Q[0], Q[1], v);
|
||||
const Vec3V av = V3Sub(A[1], A[0]);
|
||||
const Vec3V bv = V3Sub(B[1], B[0]);
|
||||
closestA = V3ScaleAdd(av, v, A[0]);
|
||||
closestB = V3ScaleAdd(bv, v, B[0]);
|
||||
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
//calculate the Barycentric of closest point p in the mincowsky sum
|
||||
FloatV v, w;
|
||||
barycentricCoordinates(closest, Q[0], Q[1], Q[2], v, w);
|
||||
|
||||
const Vec3V av0 = V3Sub(A[1], A[0]);
|
||||
const Vec3V av1 = V3Sub(A[2], A[0]);
|
||||
const Vec3V bv0 = V3Sub(B[1], B[0]);
|
||||
const Vec3V bv1 = V3Sub(B[2], B[0]);
|
||||
|
||||
closestA = V3Add(A[0], V3Add(V3Scale(av0, v), V3Scale(av1, w)));
|
||||
closestB = V3Add(B[0], V3Add(V3Scale(bv0, v), V3Scale(bv1, w)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
PX_NOALIAS PX_GJK_FORCE_INLINE aos::FloatV closestPtPointTriangleBaryCentric(const aos::Vec3VArg a, const aos::Vec3VArg b, const aos::Vec3VArg c,
|
||||
PxU32* PX_RESTRICT indices, PxU32& size, aos::Vec3V& closestPt)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
size = 3;
|
||||
const FloatV zero = FZero();
|
||||
const FloatV eps = FEps();
|
||||
|
||||
const Vec3V ab = V3Sub(b, a);
|
||||
const Vec3V ac = V3Sub(c, a);
|
||||
|
||||
const Vec3V n = V3Cross(ab, ac);
|
||||
//ML: if the shape is oblong, the degeneracy test sometime can't catch the degeneracy in the tetraheron. Therefore, we need to make sure we still can ternimate with the previous
|
||||
//triangle by returning the maxinum distance.
|
||||
const FloatV nn = V3Dot(n, n);
|
||||
if (FAllEq(nn, zero))
|
||||
return FMax();
|
||||
|
||||
//const FloatV va = FNegScaleSub(d5, d4, FMul(d3, d6));//edge region of BC
|
||||
//const FloatV vb = FNegScaleSub(d1, d6, FMul(d5, d2));//edge region of AC
|
||||
//const FloatV vc = FNegScaleSub(d3, d2, FMul(d1, d4));//edge region of AB
|
||||
|
||||
//const FloatV va = V3Dot(n, V3Cross(b, c));//edge region of BC, signed area rbc, u = S(rbc)/S(abc) for a
|
||||
//const FloatV vb = V3Dot(n, V3Cross(c, a));//edge region of AC, signed area rac, v = S(rca)/S(abc) for b
|
||||
//const FloatV vc = V3Dot(n, V3Cross(a, b));//edge region of AB, signed area rab, w = S(rab)/S(abc) for c
|
||||
|
||||
const VecCrossV crossA = V3PrepareCross(a);
|
||||
const VecCrossV crossB = V3PrepareCross(b);
|
||||
const VecCrossV crossC = V3PrepareCross(c);
|
||||
const Vec3V bCrossC = V3Cross(crossB, crossC);
|
||||
const Vec3V cCrossA = V3Cross(crossC, crossA);
|
||||
const Vec3V aCrossB = V3Cross(crossA, crossB);
|
||||
|
||||
const FloatV va = V3Dot(n, bCrossC);//edge region of BC, signed area rbc, u = S(rbc)/S(abc) for a
|
||||
const FloatV vb = V3Dot(n, cCrossA);//edge region of AC, signed area rac, v = S(rca)/S(abc) for b
|
||||
const FloatV vc = V3Dot(n, aCrossB);//edge region of AB, signed area rab, w = S(rab)/S(abc) for c
|
||||
|
||||
const BoolV isFacePoints = BAnd(FIsGrtrOrEq(va, zero), BAnd(FIsGrtrOrEq(vb, zero), FIsGrtrOrEq(vc, zero)));
|
||||
|
||||
//face region
|
||||
if(BAllEqTTTT(isFacePoints))
|
||||
{
|
||||
const FloatV t = FDiv(V3Dot(n, a), nn);
|
||||
const Vec3V q = V3Scale(n, t);
|
||||
closestPt = q;
|
||||
return V3Dot(q, q);
|
||||
}
|
||||
|
||||
const Vec3V ap = V3Neg(a);
|
||||
const Vec3V bp = V3Neg(b);
|
||||
const Vec3V cp = V3Neg(c);
|
||||
|
||||
const FloatV d1 = V3Dot(ab, ap); // snom
|
||||
const FloatV d2 = V3Dot(ac, ap); // tnom
|
||||
const FloatV d3 = V3Dot(ab, bp); // -sdenom
|
||||
const FloatV d4 = V3Dot(ac, bp); // unom = d4 - d3
|
||||
const FloatV d5 = V3Dot(ab, cp); // udenom = d5 - d6
|
||||
const FloatV d6 = V3Dot(ac, cp); // -tdenom
|
||||
|
||||
const FloatV unom = FSub(d4, d3);
|
||||
const FloatV udenom = FSub(d5, d6);
|
||||
|
||||
size = 2;
|
||||
//check if p in edge region of AB
|
||||
const BoolV con30 = FIsGrtrOrEq(zero, vc);
|
||||
const BoolV con31 = FIsGrtrOrEq(d1, zero);
|
||||
const BoolV con32 = FIsGrtrOrEq(zero, d3);
|
||||
const BoolV con3 = BAnd(con30, BAnd(con31, con32));//edge AB region
|
||||
if(BAllEqTTTT(con3))
|
||||
{
|
||||
const FloatV toRecipAB = FSub(d1, d3);
|
||||
const FloatV recipAB = FSel(FIsGrtr(FAbs(toRecipAB), eps), FRecip(toRecipAB), zero);
|
||||
const FloatV t = FMul(d1, recipAB);
|
||||
const Vec3V q = V3ScaleAdd(ab, t, a);
|
||||
closestPt = q;
|
||||
return V3Dot(q, q);
|
||||
}
|
||||
|
||||
//check if p in edge region of BC
|
||||
const BoolV con40 = FIsGrtrOrEq(zero, va);
|
||||
const BoolV con41 = FIsGrtrOrEq(d4, d3);
|
||||
const BoolV con42 = FIsGrtrOrEq(d5, d6);
|
||||
const BoolV con4 = BAnd(con40, BAnd(con41, con42)); //edge BC region
|
||||
if(BAllEqTTTT(con4))
|
||||
{
|
||||
const Vec3V bc = V3Sub(c, b);
|
||||
const FloatV toRecipBC = FAdd(unom, udenom);
|
||||
const FloatV recipBC = FSel(FIsGrtr(FAbs(toRecipBC), eps), FRecip(toRecipBC), zero);
|
||||
const FloatV t = FMul(unom, recipBC);
|
||||
indices[0] = indices[1];
|
||||
indices[1] = indices[2];
|
||||
const Vec3V q = V3ScaleAdd(bc, t, b);
|
||||
closestPt = q;
|
||||
return V3Dot(q, q);
|
||||
}
|
||||
|
||||
//check if p in edge region of AC
|
||||
const BoolV con50 = FIsGrtrOrEq(zero, vb);
|
||||
const BoolV con51 = FIsGrtrOrEq(d2, zero);
|
||||
const BoolV con52 = FIsGrtrOrEq(zero, d6);
|
||||
|
||||
const BoolV con5 = BAnd(con50, BAnd(con51, con52));//edge AC region
|
||||
if(BAllEqTTTT(con5))
|
||||
{
|
||||
const FloatV toRecipAC = FSub(d2, d6);
|
||||
const FloatV recipAC = FSel(FIsGrtr(FAbs(toRecipAC), eps), FRecip(toRecipAC), zero);
|
||||
const FloatV t = FMul(d2, recipAC);
|
||||
indices[1]=indices[2];
|
||||
const Vec3V q = V3ScaleAdd(ac, t, a);
|
||||
closestPt = q;
|
||||
return V3Dot(q, q);
|
||||
}
|
||||
|
||||
size = 1;
|
||||
//check if p in vertex region outside a
|
||||
const BoolV con00 = FIsGrtrOrEq(zero, d1); // snom <= 0
|
||||
const BoolV con01 = FIsGrtrOrEq(zero, d2); // tnom <= 0
|
||||
const BoolV con0 = BAnd(con00, con01); // vertex region a
|
||||
if(BAllEqTTTT(con0))
|
||||
{
|
||||
closestPt = a;
|
||||
return V3Dot(a, a);
|
||||
}
|
||||
|
||||
//check if p in vertex region outside b
|
||||
const BoolV con10 = FIsGrtrOrEq(d3, zero);
|
||||
const BoolV con11 = FIsGrtrOrEq(d3, d4);
|
||||
const BoolV con1 = BAnd(con10, con11); // vertex region b
|
||||
if(BAllEqTTTT(con1))
|
||||
{
|
||||
indices[0] = indices[1];
|
||||
closestPt = b;
|
||||
return V3Dot(b, b);
|
||||
}
|
||||
|
||||
//p is in vertex region outside c
|
||||
indices[0] = indices[2];
|
||||
closestPt = c;
|
||||
return V3Dot(c, c);
|
||||
}
|
||||
|
||||
PX_NOALIAS PX_GJK_FORCE_INLINE aos::Vec3V closestPtPointTriangle(aos::Vec3V* PX_RESTRICT Q, aos::Vec3V* A, aos::Vec3V* B, PxU32& size)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
size = 3;
|
||||
|
||||
const FloatV eps2 = FLoad(PX_EPS_REAL * PX_EPS_REAL);
|
||||
const Vec3V a = Q[0];
|
||||
const Vec3V b = Q[1];
|
||||
const Vec3V c = Q[2];
|
||||
const Vec3V ab = V3Sub(b, a);
|
||||
const Vec3V ac = V3Sub(c, a);
|
||||
const Vec3V signArea = V3Cross(ab, ac);//0.5*(abXac)
|
||||
const FloatV area = V3Dot(signArea, signArea);
|
||||
if(FAllGrtrOrEq(eps2, area))
|
||||
{
|
||||
//degenerate
|
||||
size = 2;
|
||||
return closestPtPointSegment(Q, size);
|
||||
}
|
||||
|
||||
PxU32 _size;
|
||||
PxU32 indices[3]={0, 1, 2};
|
||||
Vec3V closestPt;
|
||||
closestPtPointTriangleBaryCentric(a, b, c, indices, _size, closestPt);
|
||||
|
||||
if(_size != 3)
|
||||
{
|
||||
const Vec3V q0 = Q[indices[0]]; const Vec3V q1 = Q[indices[1]];
|
||||
const Vec3V a0 = A[indices[0]]; const Vec3V a1 = A[indices[1]];
|
||||
const Vec3V b0 = B[indices[0]]; const Vec3V b1 = B[indices[1]];
|
||||
|
||||
Q[0] = q0; Q[1] = q1;
|
||||
A[0] = a0; A[1] = a1;
|
||||
B[0] = b0; B[1] = b1;
|
||||
|
||||
size = _size;
|
||||
}
|
||||
|
||||
return closestPt;
|
||||
}
|
||||
|
||||
PX_NOALIAS PX_GJK_FORCE_INLINE aos::Vec3V closestPtPointTriangle(aos::Vec3V* PX_RESTRICT Q, aos::Vec3V* A, aos::Vec3V* B, PxI32* PX_RESTRICT aInd, PxI32* PX_RESTRICT bInd,
|
||||
PxU32& size)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
size = 3;
|
||||
|
||||
const FloatV eps2 = FLoad(PX_EPS_REAL * PX_EPS_REAL);
|
||||
|
||||
const Vec3V a = Q[0];
|
||||
const Vec3V b = Q[1];
|
||||
const Vec3V c = Q[2];
|
||||
const Vec3V ab = V3Sub(b, a);
|
||||
const Vec3V ac = V3Sub(c, a);
|
||||
const Vec3V signArea = V3Cross(ab, ac);//0.5*(abXac)
|
||||
const FloatV area = V3Dot(signArea, signArea);
|
||||
if(FAllGrtrOrEq(eps2, area))
|
||||
{
|
||||
//degenerate
|
||||
size = 2;
|
||||
return closestPtPointSegment(Q, size);
|
||||
}
|
||||
|
||||
PxU32 _size;
|
||||
PxU32 indices[3]={0, 1, 2};
|
||||
Vec3V closestPt;
|
||||
closestPtPointTriangleBaryCentric(a, b, c, indices, _size, closestPt);
|
||||
|
||||
if(_size != 3)
|
||||
{
|
||||
const Vec3V q0 = Q[indices[0]]; const Vec3V q1 = Q[indices[1]];
|
||||
const Vec3V a0 = A[indices[0]]; const Vec3V a1 = A[indices[1]];
|
||||
const Vec3V b0 = B[indices[0]]; const Vec3V b1 = B[indices[1]];
|
||||
const PxI32 aInd0 = aInd[indices[0]]; const PxI32 aInd1 = aInd[indices[1]];
|
||||
const PxI32 bInd0 = bInd[indices[0]]; const PxI32 bInd1 = bInd[indices[1]];
|
||||
|
||||
Q[0] = q0; Q[1] = q1;
|
||||
A[0] = a0; A[1] = a1;
|
||||
B[0] = b0; B[1] = b1;
|
||||
aInd[0] = aInd0; aInd[1] = aInd1;
|
||||
bInd[0] = bInd0; bInd[1] = bInd1;
|
||||
|
||||
size = _size;
|
||||
}
|
||||
|
||||
return closestPt;
|
||||
}
|
||||
|
||||
PX_NOALIAS PX_FORCE_INLINE aos::Vec3V GJKCPairDoSimplex(aos::Vec3V* PX_RESTRICT Q, aos::Vec3V* PX_RESTRICT A, aos::Vec3V* PX_RESTRICT B, const aos::Vec3VArg support,
|
||||
PxU32& size)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
//const PxU32 tempSize = size;
|
||||
//calculate a closest from origin to the simplex
|
||||
switch(size)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
return support;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
return closestPtPointSegment(Q, size);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
return closestPtPointTriangle(Q, A, B, size);
|
||||
}
|
||||
case 4:
|
||||
return closestPtPointTetrahedron(Q, A, B, size);
|
||||
default:
|
||||
PX_ASSERT(0);
|
||||
}
|
||||
return support;
|
||||
}
|
||||
|
||||
PX_NOALIAS PX_FORCE_INLINE aos::Vec3V GJKCPairDoSimplex(aos::Vec3V* PX_RESTRICT Q, aos::Vec3V* PX_RESTRICT A, aos::Vec3V* PX_RESTRICT B, PxI32* PX_RESTRICT aInd, PxI32* PX_RESTRICT bInd,
|
||||
const aos::Vec3VArg support, PxU32& size)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
//const PxU32 tempSize = size;
|
||||
//calculate a closest from origin to the simplex
|
||||
switch(size)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
return support;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
return closestPtPointSegment(Q, size);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
return closestPtPointTriangle(Q, A, B, aInd, bInd, size);
|
||||
}
|
||||
case 4:
|
||||
return closestPtPointTetrahedron(Q, A, B, aInd, bInd, size);
|
||||
default:
|
||||
PX_ASSERT(0);
|
||||
}
|
||||
return support;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
65
engine/third_party/physx/source/geomutils/src/gjk/GuGJKTest.cpp
vendored
Normal file
65
engine/third_party/physx/source/geomutils/src/gjk/GuGJKTest.cpp
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// 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.
|
||||
|
||||
#include "GuGJK.h"
|
||||
#include "GuGJKRaycast.h"
|
||||
#include "GuGJKPenetration.h"
|
||||
#include "GuGJKTest.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
GjkStatus testGjk(const GjkConvex& a, const GjkConvex& b, const Vec3VArg initialSearchDir, const FloatVArg contactDist, Vec3V& closestA, Vec3V& closestB, Vec3V& normal, FloatV& dist)
|
||||
{
|
||||
return gjk<GjkConvex, GjkConvex>(a, b, initialSearchDir, contactDist, closestA, closestB, normal, dist);
|
||||
}
|
||||
|
||||
bool testGjkRaycast(const GjkConvex& a, const GjkConvex& b, const Vec3VArg initialSearchDir, const aos::FloatVArg initialLambda, const aos::Vec3VArg s, const aos::Vec3VArg r, aos::FloatV& lambda,
|
||||
aos::Vec3V& normal, aos::Vec3V& closestA, PxReal inflation)
|
||||
{
|
||||
return gjkRaycast(a, b, initialSearchDir, initialLambda, s, r, lambda, normal, closestA, inflation);
|
||||
}
|
||||
|
||||
GjkStatus testGjkPenetration(const GjkConvex& a, const GjkConvex& b, const Vec3VArg initialSearchDir, const FloatVArg contactDist,
|
||||
PxU8* aIndices, PxU8* bIndices, PxU8& size, GjkOutput& output)
|
||||
{
|
||||
return gjkPenetration<GjkConvex, GjkConvex>(a, b, initialSearchDir, contactDist, true,
|
||||
aIndices, bIndices, size, output);
|
||||
}
|
||||
|
||||
GjkStatus testEpaPenetration(const GjkConvex& a, const GjkConvex& b, const PxU8* aIndices, const PxU8* bIndices, PxU8 size, GjkOutput& output)
|
||||
{
|
||||
return epaPenetration(a, b, aIndices, bIndices, size, true, aos::FLoad(1.f), output);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
54
engine/third_party/physx/source/geomutils/src/gjk/GuGJKTest.h
vendored
Normal file
54
engine/third_party/physx/source/geomutils/src/gjk/GuGJKTest.h
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// 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_GJK_TEST_H
|
||||
#define GU_GJK_TEST_H
|
||||
|
||||
#include "common/PxPhysXCommonConfig.h"
|
||||
#include "GuGJKUtil.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
struct GjkConvex;
|
||||
|
||||
PX_PHYSX_COMMON_API GjkStatus testGjk(const GjkConvex& a, const GjkConvex& b, const aos::Vec3VArg initialSearchDir, const aos::FloatVArg contactDist, aos::Vec3V& closestA, aos::Vec3V& closestB,
|
||||
aos::Vec3V& normal, aos::FloatV& dist);
|
||||
|
||||
PX_PHYSX_COMMON_API bool testGjkRaycast(const GjkConvex& a, const GjkConvex& b, const aos::Vec3VArg initialSearchDir, const aos::FloatVArg initialLambda, const aos::Vec3VArg s, const aos::Vec3VArg r,
|
||||
aos::FloatV& lambda, aos::Vec3V& normal, aos::Vec3V& closestA, PxReal inflation);
|
||||
|
||||
PX_PHYSX_COMMON_API GjkStatus testGjkPenetration(const GjkConvex& a, const GjkConvex& b, const aos::Vec3VArg initialSearchDir, const aos::FloatVArg contactDist,
|
||||
PxU8* aIndices, PxU8* bIndices, PxU8& size, GjkOutput& output);
|
||||
|
||||
PX_PHYSX_COMMON_API GjkStatus testEpaPenetration(const GjkConvex& a, const GjkConvex& b, const PxU8* aIndices, const PxU8* bIndices, PxU8 size, GjkOutput& output);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
154
engine/third_party/physx/source/geomutils/src/gjk/GuGJKType.h
vendored
Normal file
154
engine/third_party/physx/source/geomutils/src/gjk/GuGJKType.h
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
// 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_GJKTYPE_H
|
||||
#define GU_GJKTYPE_H
|
||||
|
||||
#include "GuVecConvex.h"
|
||||
#include "foundation/PxVecTransform.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
class ConvexHullV;
|
||||
class ConvexHullNoScaleV;
|
||||
class BoxV;
|
||||
|
||||
template <typename Convex> struct ConvexGeom { typedef Convex Type; };
|
||||
template <> struct ConvexGeom<ConvexHullV> { typedef ConvexHullV Type; };
|
||||
template <> struct ConvexGeom<ConvexHullNoScaleV> { typedef ConvexHullNoScaleV Type; };
|
||||
template <> struct ConvexGeom<BoxV> { typedef BoxV Type; };
|
||||
|
||||
struct GjkConvex
|
||||
{
|
||||
GjkConvex(const ConvexV& convex) : mConvex(convex) {}
|
||||
virtual ~GjkConvex() {}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getMinMargin() const { return mConvex.getMinMargin(); }
|
||||
PX_FORCE_INLINE aos::BoolV isMarginEqRadius() const { return mConvex.isMarginEqRadius(); }
|
||||
PX_FORCE_INLINE bool getMarginIsRadius() const { return mConvex.getMarginIsRadius(); }
|
||||
PX_FORCE_INLINE aos::FloatV getMargin() const { return mConvex.getMargin(); }
|
||||
|
||||
template <typename Convex>
|
||||
PX_FORCE_INLINE const Convex& getConvex() const { return static_cast<const Convex&>(mConvex); }
|
||||
|
||||
virtual aos::Vec3V supportPoint(const PxI32 index) const { return doVirtualSupportPoint(index); }
|
||||
virtual aos::Vec3V support(const aos::Vec3VArg v) const { return doVirtualSupport(v); }
|
||||
virtual aos::Vec3V support(const aos::Vec3VArg dir, PxI32& index) const { return doVirtualSupport(dir, index); }
|
||||
virtual aos::FloatV getSweepMargin() const { return doVirtualGetSweepMargin(); }
|
||||
virtual aos::Vec3V getCenter() const = 0;
|
||||
|
||||
protected:
|
||||
const ConvexV& mConvex;
|
||||
|
||||
private:
|
||||
// PT: following functions call the v-table. I think this curious pattern is needed for the de-virtualization
|
||||
// approach used in the GJK code, combined with the GuGJKTest file that is only used externally.
|
||||
aos::Vec3V doVirtualSupportPoint(const PxI32 index) const { return supportPoint(index); }
|
||||
aos::Vec3V doVirtualSupport(const aos::Vec3VArg v) const { return support(v); }
|
||||
aos::Vec3V doVirtualSupport(const aos::Vec3VArg dir, PxI32& index) const { return support(dir, index); }
|
||||
aos::FloatV doVirtualGetSweepMargin() const { return getSweepMargin(); }
|
||||
|
||||
//PX_NOCOPY(GjkConvex)
|
||||
GjkConvex& operator = (const GjkConvex&);
|
||||
};
|
||||
|
||||
template <typename Convex>
|
||||
struct LocalConvex : public GjkConvex
|
||||
{
|
||||
LocalConvex(const Convex& convex) : GjkConvex(convex){}
|
||||
|
||||
// PT: I think we omit the virtual on purpose here, for the de-virtualization approach, i.e. the code calls these
|
||||
// functions directly (bypassing the v-table). In fact I think we don't need virtuals at all here, it's probably
|
||||
// only for external cases and/or cases where we want to reduce code size.
|
||||
// The mix of virtual/force-inline/inline below is confusing/unclear.
|
||||
|
||||
// GjkConvex
|
||||
PX_FORCE_INLINE aos::Vec3V supportPoint(const PxI32 index) const { return getConvex<Convex>().supportPoint(index); }
|
||||
aos::Vec3V support(const aos::Vec3VArg v) const { return getConvex<Convex>().supportLocal(v); }
|
||||
aos::Vec3V support(const aos::Vec3VArg dir, PxI32& index) const { return getConvex<Convex>().supportLocal(dir, index); }
|
||||
PX_INLINE aos::FloatV getSweepMargin() const { return getConvex<Convex>().getSweepMargin(); }
|
||||
virtual aos::Vec3V getCenter() const { return getConvex<Convex>().getCenter(); }
|
||||
//~GjkConvex
|
||||
|
||||
//ML: we can't force inline function, otherwise win modern will throw compiler error
|
||||
PX_INLINE LocalConvex<typename ConvexGeom<Convex>::Type > getGjkConvex() const
|
||||
{
|
||||
return LocalConvex<typename ConvexGeom<Convex>::Type >(static_cast<const typename ConvexGeom<Convex>::Type&>(GjkConvex::mConvex));
|
||||
}
|
||||
|
||||
typedef LocalConvex<typename ConvexGeom<Convex>::Type > ConvexGeomType;
|
||||
|
||||
typedef Convex Type;
|
||||
|
||||
private:
|
||||
//PX_NOCOPY(LocalConvex<Convex>)
|
||||
LocalConvex<Convex>& operator = (const LocalConvex<Convex>&);
|
||||
};
|
||||
|
||||
template <typename Convex>
|
||||
struct RelativeConvex : public GjkConvex
|
||||
{
|
||||
RelativeConvex(const Convex& convex, const aos::PxMatTransformV& aToB) : GjkConvex(convex), mAToB(aToB), mAToBTransposed(aToB)
|
||||
{
|
||||
aos::V3Transpose(mAToBTransposed.rot.col0, mAToBTransposed.rot.col1, mAToBTransposed.rot.col2);
|
||||
}
|
||||
|
||||
// GjkConvex
|
||||
PX_FORCE_INLINE aos::Vec3V supportPoint(const PxI32 index) const { return mAToB.transform(getConvex<Convex>().supportPoint(index)); }
|
||||
aos::Vec3V support(const aos::Vec3VArg v) const { return getConvex<Convex>().supportRelative(v, mAToB, mAToBTransposed); }
|
||||
aos::Vec3V support(const aos::Vec3VArg dir, PxI32& index) const { return getConvex<Convex>().supportRelative(dir, mAToB, mAToBTransposed, index); }
|
||||
PX_INLINE aos::FloatV getSweepMargin() const { return getConvex<Convex>().getSweepMargin(); }
|
||||
virtual aos::Vec3V getCenter() const { return mAToB.transform(getConvex<Convex>().getCenter()); }
|
||||
//~GjkConvex
|
||||
|
||||
PX_FORCE_INLINE const aos::PxMatTransformV& getRelativeTransform() const { return mAToB; }
|
||||
|
||||
//ML: we can't force inline function, otherwise win modern will throw compiler error
|
||||
PX_INLINE RelativeConvex<typename ConvexGeom<Convex>::Type > getGjkConvex() const
|
||||
{
|
||||
return RelativeConvex<typename ConvexGeom<Convex>::Type >(static_cast<const typename ConvexGeom<Convex>::Type&>(GjkConvex::mConvex), mAToB);
|
||||
}
|
||||
|
||||
typedef RelativeConvex<typename ConvexGeom<Convex>::Type > ConvexGeomType;
|
||||
|
||||
typedef Convex Type;
|
||||
|
||||
private:
|
||||
//PX_NOCOPY(RelativeConvex<Convex>)
|
||||
RelativeConvex<Convex>& operator = (const RelativeConvex<Convex>&);
|
||||
|
||||
const aos::PxMatTransformV& mAToB;
|
||||
aos::PxMatTransformV mAToBTransposed; // PT: precomputed mAToB transpose (because 'rotate' is faster than 'rotateInv')
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
74
engine/third_party/physx/source/geomutils/src/gjk/GuGJKUtil.h
vendored
Normal file
74
engine/third_party/physx/source/geomutils/src/gjk/GuGJKUtil.h
vendored
Normal 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_GJKUTIL_H
|
||||
#define GU_GJKUTIL_H
|
||||
|
||||
#include "foundation/PxVecMath.h"
|
||||
|
||||
/*
|
||||
This file is used to avoid the inner loop cross DLL calls
|
||||
*/
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
|
||||
enum GjkStatus
|
||||
{
|
||||
GJK_NON_INTERSECT, // two shapes doesn't intersect
|
||||
GJK_CLOSE, // two shapes doesn't intersect and gjk algorithm will return closest point information
|
||||
GJK_CONTACT, // two shapes overlap within margin
|
||||
GJK_UNDEFINED, // undefined status
|
||||
GJK_DEGENERATE, // gjk can't converge
|
||||
|
||||
EPA_CONTACT, // two shapes intersect
|
||||
EPA_DEGENERATE, // epa can't converge
|
||||
EPA_FAIL // epa fail to construct an initial polygon to work with
|
||||
};
|
||||
|
||||
struct GjkOutput
|
||||
{
|
||||
public:
|
||||
GjkOutput()
|
||||
{
|
||||
using namespace aos;
|
||||
closestA = closestB = normal = V3Zero();
|
||||
penDep = FZero();
|
||||
}
|
||||
aos::Vec3V closestA;
|
||||
aos::Vec3V closestB;
|
||||
aos::Vec3V normal;
|
||||
aos::Vec3V searchDir;
|
||||
aos::FloatV penDep;
|
||||
};
|
||||
|
||||
}//Gu
|
||||
}//physx
|
||||
|
||||
#endif
|
||||
221
engine/third_party/physx/source/geomutils/src/gjk/GuVecBox.h
vendored
Normal file
221
engine/third_party/physx/source/geomutils/src/gjk/GuVecBox.h
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
// 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_VEC_BOX_H
|
||||
#define GU_VEC_BOX_H
|
||||
|
||||
#include "foundation/PxTransform.h"
|
||||
#include "common/PxPhysXCommonConfig.h"
|
||||
#include "geometry/PxBoxGeometry.h"
|
||||
#include "foundation/PxVecTransform.h"
|
||||
#include "GuVecConvex.h"
|
||||
#include "GuConvexSupportTable.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
PX_PHYSX_COMMON_API extern const aos::BoolV boxVertexTable[8];
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
|
||||
#define BOX_MARGIN_RATIO 0.15f
|
||||
#define BOX_MIN_MARGIN_RATIO 0.05f
|
||||
#define BOX_SWEEP_MARGIN_RATIO 0.05f
|
||||
|
||||
#define BOX_MARGIN_CCD_RATIO 0.01f
|
||||
#define BOX_MIN_MARGIN_CCD_RATIO 0.005f
|
||||
|
||||
|
||||
class CapsuleV;
|
||||
|
||||
|
||||
PX_FORCE_INLINE void CalculateBoxMargin(const aos::Vec3VArg extent, PxReal& margin, PxReal& minMargin, PxReal& sweepMargin,
|
||||
const PxReal marginR = BOX_MARGIN_RATIO, const PxReal minMarginR = BOX_MIN_MARGIN_RATIO)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
PxReal minExtent;
|
||||
const FloatV min = V3ExtractMin(extent);
|
||||
FStore(min, &minExtent);
|
||||
|
||||
margin = minExtent * marginR;
|
||||
minMargin = minExtent * minMarginR;
|
||||
sweepMargin = minExtent * BOX_SWEEP_MARGIN_RATIO;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV CalculateBoxTolerance(const aos::Vec3VArg extent)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const FloatV r0 = FLoad(0.01f);
|
||||
const FloatV min = V3ExtractMin(extent);//FMin(V3GetX(extent), FMin(V3GetY(extent), V3GetZ(extent)));
|
||||
return FMul(min, r0);
|
||||
}
|
||||
|
||||
//This method is called in the PCM contact gen for the refreshing contacts
|
||||
PX_FORCE_INLINE aos::FloatV CalculatePCMBoxMargin(const aos::Vec3VArg extent, const PxReal toleranceLength, const PxReal toleranceMarginRatio = BOX_MARGIN_RATIO)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const FloatV min = V3ExtractMin(extent);//FMin(V3GetX(extent), FMin(V3GetY(extent), V3GetZ(extent)));
|
||||
const FloatV toleranceMargin = FLoad(toleranceLength * toleranceMarginRatio);
|
||||
return FMin(FMul(min, FLoad(BOX_MARGIN_RATIO)), toleranceMargin);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV CalculateMTDBoxMargin(const aos::Vec3VArg extent)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const FloatV min = V3ExtractMin(extent);//FMin(V3GetX(extent), FMin(V3GetY(extent), V3GetZ(extent)));
|
||||
return FMul(min, FLoad(BOX_MARGIN_RATIO));
|
||||
}
|
||||
|
||||
class BoxV : public ConvexV
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
\brief Constructor
|
||||
*/
|
||||
PX_INLINE BoxV() : ConvexV(ConvexType::eBOX)
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE BoxV(const aos::Vec3VArg origin, const aos::Vec3VArg extent) :
|
||||
ConvexV(ConvexType::eBOX, origin), extents(extent)
|
||||
{
|
||||
CalculateBoxMargin(extent, margin, minMargin, sweepMargin);
|
||||
}
|
||||
|
||||
//this constructor is used by the CCD system
|
||||
PX_FORCE_INLINE BoxV(const PxGeometry& geom) : ConvexV(ConvexType::eBOX, aos::V3Zero())
|
||||
{
|
||||
using namespace aos;
|
||||
const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom);
|
||||
const Vec3V extent = aos::V3LoadU(boxGeom.halfExtents);
|
||||
extents = extent;
|
||||
CalculateBoxMargin(extent, margin, minMargin, sweepMargin, BOX_MARGIN_CCD_RATIO, BOX_MIN_MARGIN_CCD_RATIO);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Destructor
|
||||
*/
|
||||
PX_INLINE ~BoxV()
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void resetMargin(const PxReal toleranceLength)
|
||||
{
|
||||
minMargin = PxMin(toleranceLength * BOX_MIN_MARGIN_RATIO, minMargin);
|
||||
}
|
||||
|
||||
//! Assignment operator
|
||||
PX_FORCE_INLINE const BoxV& operator=(const BoxV& other)
|
||||
{
|
||||
center = other.center;
|
||||
extents = other.extents;
|
||||
margin = other.margin;
|
||||
minMargin = other.minMargin;
|
||||
sweepMargin = other.sweepMargin;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void populateVerts(const PxU8* inds, PxU32 numInds, const PxVec3* originalVerts, aos::Vec3V* verts)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
for(PxU32 i=0; i<numInds; ++i)
|
||||
verts[i] = V3LoadU_SafeReadW(originalVerts[inds[i]]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'populateVerts' is always called with polyData.mVerts)
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportPoint(const PxI32 index)const
|
||||
{
|
||||
using namespace aos;
|
||||
const BoolV con = boxVertexTable[index];
|
||||
return V3Sel(con, extents, V3Neg(extents));
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void getIndex(const aos::BoolV con, PxI32& index)const
|
||||
{
|
||||
using namespace aos;
|
||||
index = PxI32(BGetBitMask(con) & 0x7);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir)const
|
||||
{
|
||||
using namespace aos;
|
||||
return V3Sel(V3IsGrtr(dir, V3Zero()), extents, V3Neg(extents));
|
||||
}
|
||||
|
||||
//this is used in the sat test for the full contact gen
|
||||
PX_SUPPORT_INLINE void supportLocal(const aos::Vec3VArg dir, aos::FloatV& min, aos::FloatV& max)const
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V point = V3Sel(V3IsGrtr(dir, V3Zero()), extents, V3Neg(extents));
|
||||
max = V3Dot(dir, point);
|
||||
min = FNeg(max);
|
||||
}
|
||||
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportRelative(const aos::Vec3VArg dir, const aos::PxMatTransformV& aTob, const aos::PxMatTransformV& aTobT) const
|
||||
{
|
||||
//a is the current object, b is the other object, dir is in the local space of b
|
||||
using namespace aos;
|
||||
// const Vec3V _dir = aTob.rotateInv(dir);//relTra.rotateInv(dir);//from b to a
|
||||
const Vec3V _dir = aTobT.rotate(dir);//relTra.rotateInv(dir);//from b to a
|
||||
const Vec3V p = supportLocal(_dir);
|
||||
//transfer p into the b space
|
||||
return aTob.transform(p);//relTra.transform(p);
|
||||
}
|
||||
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir, PxI32& index)const
|
||||
{
|
||||
using namespace aos;
|
||||
const BoolV comp = V3IsGrtr(dir, V3Zero());
|
||||
getIndex(comp, index);
|
||||
return V3Sel(comp, extents, V3Neg(extents));
|
||||
}
|
||||
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportRelative( const aos::Vec3VArg dir, const aos::PxMatTransformV& aTob,
|
||||
const aos::PxMatTransformV& aTobT, PxI32& index)const
|
||||
{
|
||||
//a is the current object, b is the other object, dir is in the local space of b
|
||||
using namespace aos;
|
||||
// const Vec3V _dir = aTob.rotateInv(dir);//relTra.rotateInv(dir);//from b to a
|
||||
const Vec3V _dir = aTobT.rotate(dir);//relTra.rotateInv(dir);//from b to a
|
||||
const Vec3V p = supportLocal(_dir, index);
|
||||
//transfer p into the b space
|
||||
return aTob.transform(p);//relTra.transform(p);
|
||||
}
|
||||
|
||||
aos::Vec3V extents;
|
||||
};
|
||||
} //PX_COMPILE_TIME_ASSERT(sizeof(Gu::BoxV) == 96);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
233
engine/third_party/physx/source/geomutils/src/gjk/GuVecCapsule.h
vendored
Normal file
233
engine/third_party/physx/source/geomutils/src/gjk/GuVecCapsule.h
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
// 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_VEC_CAPSULE_H
|
||||
#define GU_VEC_CAPSULE_H
|
||||
|
||||
|
||||
#include "geometry/PxCapsuleGeometry.h"
|
||||
#include "GuVecConvex.h"
|
||||
#include "GuConvexSupportTable.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV CalculateCapsuleMinMargin(const aos::FloatVArg radius)
|
||||
{
|
||||
using namespace aos;
|
||||
const FloatV ratio = aos::FLoad(0.05f);
|
||||
return FMul(radius, ratio);
|
||||
}
|
||||
|
||||
class CapsuleV : public ConvexV
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief Constructor
|
||||
*/
|
||||
|
||||
PX_INLINE CapsuleV():ConvexV(ConvexType::eCAPSULE)
|
||||
{
|
||||
bMarginIsRadius = true;
|
||||
}
|
||||
|
||||
//constructor for sphere
|
||||
PX_INLINE CapsuleV(const aos::Vec3VArg p, const aos::FloatVArg radius_) : ConvexV(ConvexType::eCAPSULE)
|
||||
{
|
||||
using namespace aos;
|
||||
center = p;
|
||||
radius = radius_;
|
||||
p0 = p;
|
||||
p1 = p;
|
||||
FStore(radius, &margin);
|
||||
FStore(radius, &minMargin);
|
||||
FStore(radius, &sweepMargin);
|
||||
bMarginIsRadius = true;
|
||||
}
|
||||
|
||||
PX_INLINE CapsuleV(const aos::Vec3VArg center_, const aos::Vec3VArg v_, const aos::FloatVArg radius_) :
|
||||
ConvexV(ConvexType::eCAPSULE, center_)
|
||||
{
|
||||
using namespace aos;
|
||||
radius = radius_;
|
||||
p0 = V3Add(center_, v_);
|
||||
p1 = V3Sub(center_, v_);
|
||||
FStore(radius, &margin);
|
||||
FStore(radius, &minMargin);
|
||||
FStore(radius, &sweepMargin);
|
||||
bMarginIsRadius = true;
|
||||
}
|
||||
|
||||
PX_INLINE CapsuleV(const PxGeometry& geom) : ConvexV(ConvexType::eCAPSULE, aos::V3Zero())
|
||||
{
|
||||
using namespace aos;
|
||||
const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom);
|
||||
|
||||
const Vec3V axis = V3Scale(V3UnitX(), FLoad(capsuleGeom.halfHeight));
|
||||
const FloatV r = FLoad(capsuleGeom.radius);
|
||||
p0 = axis;
|
||||
p1 = V3Neg(axis);
|
||||
radius = r;
|
||||
FStore(radius, &margin);
|
||||
FStore(radius, &minMargin);
|
||||
FStore(radius, &sweepMargin);
|
||||
bMarginIsRadius = true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Constructor
|
||||
|
||||
\param _radius Radius of the capsule.
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Destructor
|
||||
*/
|
||||
PX_INLINE ~CapsuleV()
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void initialize(const aos::Vec3VArg _p0, const aos::Vec3VArg _p1, const aos::FloatVArg _radius)
|
||||
{
|
||||
using namespace aos;
|
||||
radius = _radius;
|
||||
p0 = _p0;
|
||||
p1 = _p1;
|
||||
FStore(radius, &margin);
|
||||
FStore(radius, &minMargin);
|
||||
FStore(radius, &sweepMargin);
|
||||
center = V3Scale(V3Add(_p0, _p1), FHalf());
|
||||
}
|
||||
|
||||
PX_INLINE aos::Vec3V computeDirection() const
|
||||
{
|
||||
return aos::V3Sub(p1, p0);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getRadius() const
|
||||
{
|
||||
return radius;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportPoint(const PxI32 index)const
|
||||
{
|
||||
return (&p0)[1-index];
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void getIndex(const aos::BoolV con, PxI32& index)const
|
||||
{
|
||||
using namespace aos;
|
||||
const VecI32V v = VecI32V_From_BoolV(con);
|
||||
const VecI32V t = VecI32V_And(v, VecI32V_One());
|
||||
PxI32_From_VecI32V(t, &index);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setCenter(const aos::Vec3VArg _center)
|
||||
{
|
||||
using namespace aos;
|
||||
Vec3V offset = V3Sub(_center, center);
|
||||
center = _center;
|
||||
|
||||
p0 = V3Add(p0, offset);
|
||||
p1 = V3Add(p1, offset);
|
||||
}
|
||||
|
||||
//dir, p0 and p1 are in the local space of dir
|
||||
PX_FORCE_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir)const
|
||||
{
|
||||
using namespace aos;
|
||||
//const Vec3V _dir = V3Normalize(dir);
|
||||
const FloatV dist0 = V3Dot(p0, dir);
|
||||
const FloatV dist1 = V3Dot(p1, dir);
|
||||
return V3Sel(FIsGrtr(dist0, dist1), p0, p1);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportRelative(const aos::Vec3VArg dir, const aos::PxMatTransformV& aToB, const aos::PxMatTransformV& aTobT) const
|
||||
{
|
||||
using namespace aos;
|
||||
//transform dir into the local space of a
|
||||
// const Vec3V _dir = aToB.rotateInv(dir);
|
||||
const Vec3V _dir = aTobT.rotate(dir);
|
||||
const Vec3V p = supportLocal(_dir);
|
||||
//transform p back to the local space of b
|
||||
return aToB.transform(p);
|
||||
}
|
||||
|
||||
//dir, p0 and p1 are in the local space of dir
|
||||
PX_FORCE_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir, PxI32& index)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const FloatV dist0 = V3Dot(p0, dir);
|
||||
const FloatV dist1 = V3Dot(p1, dir);
|
||||
const BoolV comp = FIsGrtr(dist0, dist1);
|
||||
getIndex(comp, index);
|
||||
return V3Sel(comp, p0, p1);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportRelative( const aos::Vec3VArg dir, const aos::PxMatTransformV& aToB,
|
||||
const aos::PxMatTransformV& aTobT, PxI32& index)const
|
||||
{
|
||||
using namespace aos;
|
||||
//transform dir into the local space of a
|
||||
// const Vec3V _dir = aToB.rotateInv(dir);
|
||||
const Vec3V _dir = aTobT.rotate(dir);
|
||||
|
||||
const Vec3V p = supportLocal(_dir, index);
|
||||
//transform p back to the local space of b
|
||||
return aToB.transform(p);
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportLocal(aos::Vec3V& support, const PxI32& index, const aos::BoolV comp)const
|
||||
{
|
||||
PX_UNUSED(index);
|
||||
|
||||
using namespace aos;
|
||||
const Vec3V p = V3Sel(comp, p0, p1);
|
||||
support = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getSweepMargin() const
|
||||
{
|
||||
return aos::FZero();
|
||||
}
|
||||
|
||||
//don't change the order of p0 and p1, the getPoint function depend on the order
|
||||
aos::Vec3V p0; //!< Start of segment
|
||||
aos::Vec3V p1; //!< End of segment
|
||||
aos::FloatV radius;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
179
engine/third_party/physx/source/geomutils/src/gjk/GuVecConvex.h
vendored
Normal file
179
engine/third_party/physx/source/geomutils/src/gjk/GuVecConvex.h
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
// 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_VEC_CONVEX_H
|
||||
#define GU_VEC_CONVEX_H
|
||||
|
||||
#include "foundation/PxVecMath.h"
|
||||
|
||||
#define PX_SUPPORT_INLINE PX_FORCE_INLINE
|
||||
#define PX_SUPPORT_FORCE_INLINE PX_FORCE_INLINE
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
|
||||
struct ConvexType
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
eCONVEXHULL,
|
||||
eCONVEXHULLNOSCALE,
|
||||
eSPHERE,
|
||||
eBOX,
|
||||
eCAPSULE,
|
||||
eTRIANGLE,
|
||||
eTETRAHEDRON,
|
||||
eCUSTOM
|
||||
};
|
||||
};
|
||||
|
||||
class ConvexV
|
||||
{
|
||||
public:
|
||||
|
||||
PX_FORCE_INLINE ConvexV(const ConvexType::Type type_) : type(type_), bMarginIsRadius(false)
|
||||
{
|
||||
margin = 0.f;
|
||||
minMargin = 0.f;
|
||||
sweepMargin = 0.f;
|
||||
center = aos::V3Zero();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE ConvexV(const ConvexType::Type type_, const aos::Vec3VArg center_) : type(type_), bMarginIsRadius(false)
|
||||
{
|
||||
using namespace aos;
|
||||
center = center_;
|
||||
margin = 0.f;
|
||||
minMargin = 0.f;
|
||||
sweepMargin = 0.f;
|
||||
}
|
||||
|
||||
//everytime when someone transform the object, they need to up
|
||||
PX_FORCE_INLINE void setCenter(const aos::Vec3VArg _center)
|
||||
{
|
||||
center = _center;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setMargin(const aos::FloatVArg margin_)
|
||||
{
|
||||
aos::FStore(margin_, &margin);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setMargin(const PxReal margin_)
|
||||
{
|
||||
margin = margin_;
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void setMinMargin(const aos::FloatVArg minMargin_)
|
||||
{
|
||||
aos::FStore(minMargin_, & minMargin);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setSweepMargin(const aos::FloatVArg sweepMargin_)
|
||||
{
|
||||
aos::FStore(sweepMargin_, &sweepMargin);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V getCenter()const
|
||||
{
|
||||
return center;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getMargin() const
|
||||
{
|
||||
return aos::FLoad(margin);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getMinMargin() const
|
||||
{
|
||||
return aos::FLoad(minMargin);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getSweepMargin() const
|
||||
{
|
||||
return aos::FLoad(sweepMargin);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE ConvexType::Type getType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::BoolV isMarginEqRadius()const
|
||||
{
|
||||
return aos::BLoad(bMarginIsRadius);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool getMarginIsRadius() const
|
||||
{
|
||||
return bMarginIsRadius;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxReal getMarginF() const
|
||||
{
|
||||
return margin;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
~ConvexV(){}
|
||||
aos::Vec3V center;
|
||||
PxReal margin; //margin is the amount by which we shrunk the shape for a convex or box. If the shape are sphere/capsule, margin is the radius
|
||||
PxReal minMargin; //minMargin is some percentage of marginBase, which is used to determine the termination condition for gjk
|
||||
PxReal sweepMargin; //sweepMargin minMargin is some percentage of marginBase, which is used to determine the termination condition for gjkRaycast
|
||||
ConvexType::Type type;
|
||||
bool bMarginIsRadius;
|
||||
};
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getContactEps(const aos::FloatV& _marginA, const aos::FloatV& _marginB)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const FloatV ratio = FLoad(0.25f);
|
||||
const FloatV minMargin = FMin(_marginA, _marginB);
|
||||
|
||||
return FMul(minMargin, ratio);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getSweepContactEps(const aos::FloatV& _marginA, const aos::FloatV& _marginB)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const FloatV ratio = FLoad(100.f);
|
||||
const FloatV minMargin = FAdd(_marginA, _marginB);
|
||||
|
||||
return FMul(minMargin, ratio);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
538
engine/third_party/physx/source/geomutils/src/gjk/GuVecConvexHull.h
vendored
Normal file
538
engine/third_party/physx/source/geomutils/src/gjk/GuVecConvexHull.h
vendored
Normal file
@@ -0,0 +1,538 @@
|
||||
// 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_VEC_CONVEXHULL_H
|
||||
#define GU_VEC_CONVEXHULL_H
|
||||
|
||||
#include "common/PxPhysXCommonConfig.h"
|
||||
#include "geometry/PxMeshScale.h"
|
||||
#include "GuConvexMesh.h"
|
||||
#include "GuVecConvex.h"
|
||||
#include "GuConvexMeshData.h"
|
||||
#include "GuBigConvexData.h"
|
||||
#include "GuConvexSupportTable.h"
|
||||
#include "GuCubeIndex.h"
|
||||
#include "foundation/PxFPU.h"
|
||||
#include "foundation/PxVecQuat.h"
|
||||
#include "GuShapeConvex.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
#define CONVEX_MARGIN_RATIO 0.1f
|
||||
#define CONVEX_MIN_MARGIN_RATIO 0.05f
|
||||
#define CONVEX_SWEEP_MARGIN_RATIO 0.025f
|
||||
#define TOLERANCE_MARGIN_RATIO 0.08f
|
||||
#define TOLERANCE_MIN_MARGIN_RATIO 0.05f
|
||||
|
||||
//This margin is used in Persistent contact manifold
|
||||
PX_SUPPORT_FORCE_INLINE aos::FloatV CalculatePCMConvexMargin(const Gu::ConvexHullData* hullData, const aos::Vec3VArg scale,
|
||||
const PxReal toleranceLength, const PxReal toleranceRatio = TOLERANCE_MIN_MARGIN_RATIO)
|
||||
{
|
||||
|
||||
using namespace aos;
|
||||
const Vec3V extents = V3Mul(V3LoadU_SafeReadW(hullData->mInternal.mInternalExtents), scale);
|
||||
const FloatV min = V3ExtractMin(extents);
|
||||
const FloatV toleranceMargin = FLoad(toleranceLength * toleranceRatio);
|
||||
//ML: 25% of the minimum extents of the internal AABB as this convex hull's margin
|
||||
return FMin(FMul(min, FLoad(0.25f)), toleranceMargin);
|
||||
}
|
||||
|
||||
PX_SUPPORT_FORCE_INLINE aos::FloatV CalculateMTDConvexMargin(const Gu::ConvexHullData* hullData, const aos::Vec3VArg scale)
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V extents = V3Mul(V3LoadU_SafeReadW(hullData->mInternal.mInternalExtents), scale);
|
||||
const FloatV min = V3ExtractMin(extents);
|
||||
//ML: 25% of the minimum extents of the internal AABB as this convex hull's margin
|
||||
return FMul(min, FLoad(0.25f));
|
||||
}
|
||||
|
||||
//This minMargin is used in PCM contact gen
|
||||
PX_SUPPORT_FORCE_INLINE void CalculateConvexMargin(const InternalObjectsData& internalObject, PxReal& margin, PxReal& minMargin, PxReal& sweepMargin,
|
||||
const aos::Vec3VArg scale)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const Vec3V extents = V3Mul(V3LoadU_SafeReadW(internalObject.mInternalExtents), scale);
|
||||
const FloatV min_ = V3ExtractMin(extents);
|
||||
|
||||
PxReal minExtent;
|
||||
FStore(min_, &minExtent);
|
||||
|
||||
//margin is used as acceptanceTolerance for overlap.
|
||||
margin = minExtent * CONVEX_MARGIN_RATIO;
|
||||
//minMargin is used in the GJK termination condition
|
||||
minMargin = minExtent * CONVEX_MIN_MARGIN_RATIO;
|
||||
//this is used for sweep(gjkRaycast)
|
||||
sweepMargin = minExtent * CONVEX_SWEEP_MARGIN_RATIO;
|
||||
}
|
||||
|
||||
|
||||
PX_SUPPORT_FORCE_INLINE aos::Mat33V ConstructSkewMatrix(const aos::Vec3VArg scale, const aos::QuatVArg rotation)
|
||||
{
|
||||
using namespace aos;
|
||||
Mat33V rot;
|
||||
QuatGetMat33V(rotation, rot.col0, rot.col1, rot.col2);
|
||||
Mat33V trans = M33Trnsps(rot);
|
||||
trans.col0 = V3Scale(trans.col0, V3GetX(scale));
|
||||
trans.col1 = V3Scale(trans.col1, V3GetY(scale));
|
||||
trans.col2 = V3Scale(trans.col2, V3GetZ(scale));
|
||||
return M33MulM33(trans, rot);
|
||||
}
|
||||
|
||||
PX_SUPPORT_FORCE_INLINE void ConstructSkewMatrix(const aos::Vec3VArg scale, const aos::QuatVArg rotation, aos::Mat33V& vertex2Shape, aos::Mat33V& shape2Vertex, aos::Vec3V& center, const bool idtScale)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
PX_ASSERT(!V3AllEq(scale, V3Zero()));
|
||||
|
||||
if(idtScale)
|
||||
{
|
||||
//create identity buffer
|
||||
const Mat33V identity = M33Identity();
|
||||
vertex2Shape = identity;
|
||||
shape2Vertex = identity;
|
||||
}
|
||||
else
|
||||
{
|
||||
const FloatV scaleX = V3GetX(scale);
|
||||
const Vec3V invScale = V3Recip(scale);
|
||||
|
||||
//this is uniform scale
|
||||
if(V3AllEq(V3Splat(scaleX), scale))
|
||||
{
|
||||
vertex2Shape = M33Diagonal(scale);
|
||||
shape2Vertex = M33Diagonal(invScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat33V rot;
|
||||
QuatGetMat33V(rotation, rot.col0, rot.col1, rot.col2);
|
||||
const Mat33V trans = M33Trnsps(rot);
|
||||
/*
|
||||
vertex2shape
|
||||
skewMat = Inv(R)*Diagonal(scale)*R;
|
||||
*/
|
||||
|
||||
const Mat33V temp(V3Scale(trans.col0, scaleX), V3Scale(trans.col1, V3GetY(scale)), V3Scale(trans.col2, V3GetZ(scale)));
|
||||
vertex2Shape = M33MulM33(temp, rot);
|
||||
|
||||
//don't need it in the support function
|
||||
/*
|
||||
shape2Vertex
|
||||
invSkewMat =(invSkewMat)= Inv(R)*Diagonal(1/scale)*R;
|
||||
*/
|
||||
|
||||
shape2Vertex.col0 = V3Scale(trans.col0, V3GetX(invScale));
|
||||
shape2Vertex.col1 = V3Scale(trans.col1, V3GetY(invScale));
|
||||
shape2Vertex.col2 = V3Scale(trans.col2, V3GetZ(invScale));
|
||||
shape2Vertex = M33MulM33(shape2Vertex, rot);
|
||||
|
||||
//shape2Vertex = M33Inverse(vertex2Shape);
|
||||
}
|
||||
|
||||
//transform center to shape space
|
||||
center = M33MulV3(vertex2Shape, center);
|
||||
}
|
||||
}
|
||||
|
||||
PX_SUPPORT_FORCE_INLINE aos::Mat33V ConstructVertex2ShapeMatrix(const aos::Vec3VArg scale, const aos::QuatVArg rotation)
|
||||
{
|
||||
using namespace aos;
|
||||
Mat33V rot;
|
||||
QuatGetMat33V(rotation, rot.col0, rot.col1, rot.col2);
|
||||
const Mat33V trans = M33Trnsps(rot);
|
||||
/*
|
||||
vertex2shape
|
||||
skewMat = Inv(R)*Diagonal(scale)*R;
|
||||
*/
|
||||
|
||||
const Mat33V temp(V3Scale(trans.col0, V3GetX(scale)), V3Scale(trans.col1, V3GetY(scale)), V3Scale(trans.col2, V3GetZ(scale)));
|
||||
return M33MulM33(temp, rot);
|
||||
}
|
||||
|
||||
|
||||
class ConvexHullV : public ConvexV
|
||||
{
|
||||
|
||||
class TinyBitMap
|
||||
{
|
||||
public:
|
||||
PxU32 m[8];
|
||||
PX_FORCE_INLINE TinyBitMap() { m[0] = m[1] = m[2] = m[3] = m[4] = m[5] = m[6] = m[7] = 0; }
|
||||
PX_FORCE_INLINE void set(PxU8 v) { m[v >> 5] |= 1 << (v & 31); }
|
||||
PX_FORCE_INLINE bool get(PxU8 v) const { return (m[v >> 5] & 1 << (v & 31)) != 0; }
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
\brief Constructor
|
||||
*/
|
||||
PX_SUPPORT_INLINE ConvexHullV() : ConvexV(ConvexType::eCONVEXHULL)
|
||||
{
|
||||
}
|
||||
|
||||
PX_SUPPORT_INLINE ConvexHullV(const Gu::ConvexHullData* _hullData, const aos::Vec3VArg _center, const aos::Vec3VArg scale, const aos::QuatVArg scaleRot,
|
||||
const bool idtScale) :
|
||||
ConvexV(ConvexType::eCONVEXHULL, _center)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
hullData = _hullData;
|
||||
const PxVec3* PX_RESTRICT tempVerts = _hullData->getHullVertices();
|
||||
verts = tempVerts;
|
||||
numVerts = _hullData->mNbHullVertices;
|
||||
CalculateConvexMargin(_hullData->mInternal, margin, minMargin, sweepMargin, scale);
|
||||
ConstructSkewMatrix(scale, scaleRot, vertex2Shape, shape2Vertex, center, idtScale);
|
||||
data = _hullData->mBigConvexRawData;
|
||||
}
|
||||
|
||||
PX_SUPPORT_INLINE ConvexHullV(const Gu::ConvexHullData* _hullData, const aos::Vec3VArg _center) :
|
||||
ConvexV(ConvexType::eCONVEXHULL, _center)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
hullData = _hullData;
|
||||
verts = _hullData->getHullVertices();
|
||||
numVerts = _hullData->mNbHullVertices;
|
||||
data = _hullData->mBigConvexRawData;
|
||||
}
|
||||
|
||||
//this is used by CCD system
|
||||
PX_SUPPORT_INLINE ConvexHullV(const PxGeometry& geom) : ConvexV(ConvexType::eCONVEXHULL, aos::V3Zero())
|
||||
{
|
||||
using namespace aos;
|
||||
const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom);
|
||||
const Gu::ConvexHullData* hData = _getHullData(convexGeom);
|
||||
|
||||
const Vec3V vScale = V3LoadU_SafeReadW(convexGeom.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale
|
||||
const QuatV vRot = QuatVLoadU(&convexGeom.scale.rotation.x);
|
||||
const bool idtScale = convexGeom.scale.isIdentity();
|
||||
|
||||
hullData = hData;
|
||||
const PxVec3* PX_RESTRICT tempVerts = hData->getHullVertices();
|
||||
verts = tempVerts;
|
||||
numVerts = hData->mNbHullVertices;
|
||||
CalculateConvexMargin(hData->mInternal, margin, minMargin, sweepMargin, vScale);
|
||||
ConstructSkewMatrix(vScale, vRot, vertex2Shape, shape2Vertex, center, idtScale);
|
||||
|
||||
data = hData->mBigConvexRawData;
|
||||
}
|
||||
|
||||
//this is used by convex vs tetrahedron collision
|
||||
PX_SUPPORT_INLINE ConvexHullV(const Gu::PolygonalData& polyData, const Cm::FastVertex2ShapeScaling& convexScale) :
|
||||
ConvexV(ConvexType::eCONVEXHULL, aos::V3LoadU(polyData.mCenter))
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const Vec3V vScale = V3LoadU(polyData.mScale.scale);
|
||||
|
||||
verts = polyData.mVerts;
|
||||
numVerts = PxU8(polyData.mNbVerts);
|
||||
CalculateConvexMargin(polyData.mInternal, margin, minMargin, sweepMargin, vScale);
|
||||
|
||||
const PxMat33& v2s = convexScale.getVertex2ShapeSkew();
|
||||
const PxMat33& s2v = convexScale.getShape2VertexSkew();
|
||||
|
||||
vertex2Shape.col0 = V3LoadU(v2s.column0);
|
||||
vertex2Shape.col1 = V3LoadU(v2s.column1);
|
||||
vertex2Shape.col2 = V3LoadU(v2s.column2);
|
||||
|
||||
shape2Vertex.col0 = V3LoadU(s2v.column0);
|
||||
shape2Vertex.col1 = V3LoadU(s2v.column1);
|
||||
shape2Vertex.col2 = V3LoadU(s2v.column2);
|
||||
|
||||
data = polyData.mBigData;
|
||||
|
||||
}
|
||||
|
||||
PX_SUPPORT_INLINE void initialize(const Gu::ConvexHullData* _hullData, const aos::Vec3VArg _center, const aos::Vec3VArg scale,
|
||||
const aos::QuatVArg scaleRot, const bool idtScale)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const PxVec3* tempVerts = _hullData->getHullVertices();
|
||||
CalculateConvexMargin(_hullData->mInternal, margin, minMargin, sweepMargin, scale);
|
||||
ConstructSkewMatrix(scale, scaleRot, vertex2Shape, shape2Vertex, center, idtScale);
|
||||
|
||||
verts = tempVerts;
|
||||
numVerts = _hullData->mNbHullVertices;
|
||||
//rot = _rot;
|
||||
|
||||
center = _center;
|
||||
|
||||
// searchIndex = 0;
|
||||
data = _hullData->mBigConvexRawData;
|
||||
|
||||
hullData = _hullData;
|
||||
if (_hullData->mBigConvexRawData)
|
||||
{
|
||||
PxPrefetchLine(hullData->mBigConvexRawData->mValencies);
|
||||
PxPrefetchLine(hullData->mBigConvexRawData->mValencies, 128);
|
||||
PxPrefetchLine(hullData->mBigConvexRawData->mAdjacentVerts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PX_FORCE_INLINE void resetMargin(const PxReal toleranceLength)
|
||||
{
|
||||
const PxReal toleranceMinMargin = toleranceLength * TOLERANCE_MIN_MARGIN_RATIO;
|
||||
const PxReal toleranceMargin = toleranceLength * TOLERANCE_MARGIN_RATIO;
|
||||
|
||||
margin = PxMin(margin, toleranceMargin);
|
||||
minMargin = PxMin(minMargin, toleranceMinMargin);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportPoint(const PxI32 index)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
return M33MulV3(vertex2Shape, V3LoadU_SafeReadW(verts[index])); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
}
|
||||
|
||||
PX_NOINLINE PxU32 hillClimbing(const aos::Vec3VArg _dir)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const Gu::Valency* valency = data->mValencies;
|
||||
const PxU8* adjacentVerts = data->mAdjacentVerts;
|
||||
|
||||
//NotSoTinyBitMap visited;
|
||||
PxU32 smallBitMap[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
// PxU32 index = searchIndex;
|
||||
PxU32 index = 0;
|
||||
|
||||
{
|
||||
PxVec3 vertexSpaceDirection;
|
||||
V3StoreU(_dir, vertexSpaceDirection);
|
||||
const PxU32 offset = ComputeCubemapNearestOffset(vertexSpaceDirection, data->mSubdiv);
|
||||
//const PxU32 offset = ComputeCubemapOffset(vertexSpaceDirection, data->mSubdiv);
|
||||
index = data->mSamples[offset];
|
||||
}
|
||||
|
||||
Vec3V maxPoint = V3LoadU_SafeReadW(verts[index]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
FloatV max = V3Dot(maxPoint, _dir);
|
||||
|
||||
PxU32 initialIndex = index;
|
||||
|
||||
do
|
||||
{
|
||||
initialIndex = index;
|
||||
const PxU32 numNeighbours = valency[index].mCount;
|
||||
const PxU32 offset = valency[index].mOffset;
|
||||
|
||||
for(PxU32 a = 0; a < numNeighbours; ++a)
|
||||
{
|
||||
const PxU32 neighbourIndex = adjacentVerts[offset + a];
|
||||
|
||||
const Vec3V vertex = V3LoadU_SafeReadW(verts[neighbourIndex]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
const FloatV dist = V3Dot(vertex, _dir);
|
||||
if(FAllGrtr(dist, max))
|
||||
{
|
||||
const PxU32 ind = neighbourIndex>>5;
|
||||
const PxU32 mask = PxU32(1 << (neighbourIndex & 31));
|
||||
if((smallBitMap[ind] & mask) == 0)
|
||||
{
|
||||
smallBitMap[ind] |= mask;
|
||||
max = dist;
|
||||
index = neighbourIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}while(index != initialIndex);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
PX_SUPPORT_INLINE PxU32 bruteForceSearch(const aos::Vec3VArg _dir)const
|
||||
{
|
||||
using namespace aos;
|
||||
//brute force
|
||||
PxVec3 dir;
|
||||
V3StoreU(_dir, dir);
|
||||
|
||||
PxReal max = verts[0].dot(dir);
|
||||
PxU32 maxIndex = 0;
|
||||
|
||||
for (PxU32 i = 1; i < numVerts; ++i)
|
||||
{
|
||||
const PxReal dist = verts[i].dot(dir);
|
||||
if (dist > max)
|
||||
{
|
||||
max = dist;
|
||||
maxIndex = i;
|
||||
}
|
||||
}
|
||||
return maxIndex;
|
||||
}
|
||||
|
||||
//points are in vertex space, _dir in vertex space
|
||||
PX_NOINLINE PxU32 supportVertexIndex(const aos::Vec3VArg _dir)const
|
||||
{
|
||||
using namespace aos;
|
||||
if(data)
|
||||
return hillClimbing(_dir);
|
||||
else
|
||||
return bruteForceSearch(_dir);
|
||||
}
|
||||
|
||||
//dir is in the vertex space
|
||||
PX_SUPPORT_INLINE void bruteForceSearchMinMax(const aos::Vec3VArg _dir, aos::FloatV& min, aos::FloatV& max)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
//brute force
|
||||
PxVec3 dir;
|
||||
V3StoreU(_dir, dir);
|
||||
//get the support point from the orignal margin
|
||||
PxReal _max = verts[0].dot(dir);
|
||||
PxReal _min = _max;
|
||||
|
||||
for(PxU32 i = 1; i < numVerts; ++i)
|
||||
{
|
||||
const PxReal dist = verts[i].dot(dir);
|
||||
_max = PxMax(dist, _max);
|
||||
_min = PxMin(dist, _min);
|
||||
}
|
||||
min = FLoad(_min);
|
||||
max = FLoad(_max);
|
||||
}
|
||||
|
||||
//This function is used in the full contact manifold generation code, points are in vertex space.
|
||||
//This function support scaling, _dir is in the shape space
|
||||
PX_SUPPORT_INLINE void supportVertexMinMax(const aos::Vec3VArg _dir, aos::FloatV& min, aos::FloatV& max)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
//dir is in the vertex space
|
||||
const Vec3V dir = M33TrnspsMulV3(vertex2Shape, _dir);
|
||||
|
||||
if(data)
|
||||
{
|
||||
const PxU32 maxIndex = hillClimbing(dir);
|
||||
const PxU32 minIndex = hillClimbing(V3Neg(dir));
|
||||
const Vec3V maxPoint = M33MulV3(vertex2Shape, V3LoadU_SafeReadW(verts[maxIndex])); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
const Vec3V minPoint = M33MulV3(vertex2Shape, V3LoadU_SafeReadW(verts[minIndex])); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
min = V3Dot(_dir, minPoint);
|
||||
max = V3Dot(_dir, maxPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
//dir is in the vertex space
|
||||
bruteForceSearchMinMax(dir, min, max);
|
||||
}
|
||||
}
|
||||
|
||||
//This function is used in the full contact manifold generation code
|
||||
PX_SUPPORT_INLINE void populateVerts(const PxU8* inds, PxU32 numInds, const PxVec3* originalVerts, aos::Vec3V* _verts)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
for(PxU32 i=0; i<numInds; ++i)
|
||||
_verts[i] = M33MulV3(vertex2Shape, V3LoadU_SafeReadW(originalVerts[inds[i]])); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'populateVerts' is always called with polyData.mVerts)
|
||||
}
|
||||
|
||||
//This function is used in epa
|
||||
//dir is in the shape space
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir)const
|
||||
{
|
||||
using namespace aos;
|
||||
//scale dir and put it in the vertex space
|
||||
const Vec3V _dir = M33TrnspsMulV3(vertex2Shape, dir);
|
||||
const PxU32 maxIndex = supportVertexIndex(_dir);
|
||||
return M33MulV3(vertex2Shape, V3LoadU_SafeReadW(verts[maxIndex])); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
}
|
||||
|
||||
//this is used in the sat test for the full contact gen
|
||||
PX_SUPPORT_INLINE void supportLocal(const aos::Vec3VArg dir, aos::FloatV& min, aos::FloatV& max)const
|
||||
{
|
||||
using namespace aos;
|
||||
//dir is in the shape space
|
||||
supportVertexMinMax(dir, min, max);
|
||||
}
|
||||
|
||||
//This function is used in epa
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportRelative(const aos::Vec3VArg dir, const aos::PxMatTransformV& aTob, const aos::PxMatTransformV& aTobT) const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
//transform dir into the shape space
|
||||
// const Vec3V dir_ = aTob.rotateInv(dir);//relTra.rotateInv(dir);
|
||||
const Vec3V dir_ = aTobT.rotate(dir);//relTra.rotateInv(dir);
|
||||
const Vec3V maxPoint = supportLocal(dir_);
|
||||
//translate maxPoint from shape space of a back to the b space
|
||||
return aTob.transform(maxPoint);//relTra.transform(maxPoint);
|
||||
}
|
||||
|
||||
//dir in the shape space, this function is used in gjk
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir, PxI32& index)const
|
||||
{
|
||||
using namespace aos;
|
||||
//scale dir and put it in the vertex space, for non-uniform scale, we don't want the scale in the dir, therefore, we are using
|
||||
//the transpose of the inverse of shape2Vertex(which is vertex2shape). This will allow us igore the scale and keep the rotation
|
||||
const Vec3V dir_ = M33TrnspsMulV3(vertex2Shape, dir);
|
||||
//get the extreme point index
|
||||
const PxU32 maxIndex = supportVertexIndex(dir_);
|
||||
index = PxI32(maxIndex);
|
||||
//p is in the shape space
|
||||
return M33MulV3(vertex2Shape, V3LoadU_SafeReadW(verts[index])); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
}
|
||||
|
||||
//this function is used in gjk
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportRelative( const aos::Vec3VArg dir, const aos::PxMatTransformV& aTob,
|
||||
const aos::PxMatTransformV& aTobT, PxI32& index)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
//transform dir from b space to the shape space of a space
|
||||
// const Vec3V dir_ = aTob.rotateInv(dir);//relTra.rotateInv(dir);//M33MulV3(skewInvRot, dir);
|
||||
const Vec3V dir_ = aTobT.rotate(dir);//relTra.rotateInv(dir);//M33MulV3(skewInvRot, dir);
|
||||
const Vec3V p = supportLocal(dir_, index);
|
||||
//transfrom from a to b space
|
||||
return aTob.transform(p);
|
||||
}
|
||||
|
||||
aos::Mat33V vertex2Shape;//inv(R)*S*R
|
||||
aos::Mat33V shape2Vertex;//inv(vertex2Shape)
|
||||
|
||||
const Gu::ConvexHullData* hullData;
|
||||
const BigConvexRawData* data;
|
||||
const PxVec3* verts;
|
||||
PxU8 numVerts;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //
|
||||
165
engine/third_party/physx/source/geomutils/src/gjk/GuVecConvexHullNoScale.h
vendored
Normal file
165
engine/third_party/physx/source/geomutils/src/gjk/GuVecConvexHullNoScale.h
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
// 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_VEC_CONVEXHULL_NOSCALE_H
|
||||
#define GU_VEC_CONVEXHULL_NOSCALE_H
|
||||
|
||||
#include "foundation/PxUnionCast.h"
|
||||
#include "common/PxPhysXCommonConfig.h"
|
||||
#include "GuVecConvexHull.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
class ConvexHullNoScaleV : public ConvexHullV
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief Constructor
|
||||
*/
|
||||
PX_SUPPORT_INLINE ConvexHullNoScaleV(): ConvexHullV()
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportPoint(const PxI32 index)const
|
||||
{
|
||||
using namespace aos;
|
||||
return V3LoadU_SafeReadW(verts[index]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
}
|
||||
|
||||
//This funcation is just to load the PxVec3 to Vec3V. However, for GuVecConvexHul.h, this is used to transform all the verts from vertex space to shape space
|
||||
PX_SUPPORT_INLINE void populateVerts(const PxU8* inds, PxU32 numInds, const PxVec3* originalVerts, aos::Vec3V* verts_)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
for(PxU32 i=0; i<numInds; ++i)
|
||||
verts_[i] = V3LoadU_SafeReadW(originalVerts[inds[i]]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'populateVerts' is always called with polyData.mVerts)
|
||||
}
|
||||
|
||||
//This function is used in epa
|
||||
//dir is in the shape space
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir)const
|
||||
{
|
||||
using namespace aos;
|
||||
const PxU32 maxIndex = supportVertexIndex(dir);
|
||||
return V3LoadU_SafeReadW(verts[maxIndex]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
}
|
||||
|
||||
//this is used in the sat test for the full contact gen
|
||||
PX_SUPPORT_INLINE void supportLocal(const aos::Vec3VArg dir, aos::FloatV& min, aos::FloatV& max)const
|
||||
{
|
||||
supportVertexMinMax(dir, min, max);
|
||||
}
|
||||
|
||||
//This function is used in epa
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportRelative(const aos::Vec3VArg dir, const aos::PxMatTransformV& aTob, const aos::PxMatTransformV& aTobT) const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
//transform dir into the shape space
|
||||
const Vec3V _dir = aTobT.rotate(dir);//relTra.rotateInv(dir);
|
||||
const Vec3V maxPoint = supportLocal(_dir);
|
||||
//translate maxPoint from shape space of a back to the b space
|
||||
return aTob.transform(maxPoint);//relTra.transform(maxPoint);
|
||||
}
|
||||
|
||||
//dir in the shape space, this function is used in gjk
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir, PxI32& index)const
|
||||
{
|
||||
using namespace aos;
|
||||
//scale dir and put it in the vertex space, for non-uniform scale, we don't want the scale in the dir, therefore, we are using
|
||||
//the transpose of the inverse of shape2Vertex(which is vertex2shape). This will allow us igore the scale and keep the rotation
|
||||
//get the extreme point index
|
||||
const PxU32 maxIndex = supportVertexIndex(dir);
|
||||
index = PxI32(maxIndex);
|
||||
return V3LoadU_SafeReadW(verts[index]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
}
|
||||
|
||||
//this function is used in gjk
|
||||
PX_SUPPORT_INLINE aos::Vec3V supportRelative( const aos::Vec3VArg dir, const aos::PxMatTransformV& aTob,
|
||||
const aos::PxMatTransformV& aTobT, PxI32& index)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
//transform dir from b space to the shape space of a space
|
||||
const Vec3V _dir = aTobT.rotate(dir);//relTra.rotateInv(dir);//M33MulV3(skewInvRot, dir);
|
||||
const Vec3V p = supportLocal(_dir, index);
|
||||
//transfrom from a to b space
|
||||
return aTob.transform(p);
|
||||
}
|
||||
|
||||
PX_SUPPORT_INLINE void bruteForceSearchMinMax(const aos::Vec3VArg _dir, aos::FloatV& min, aos::FloatV& max)const
|
||||
{
|
||||
using namespace aos;
|
||||
//brute force
|
||||
//get the support point from the orignal margin
|
||||
FloatV _max = V3Dot(V3LoadU_SafeReadW(verts[0]), _dir); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
FloatV _min = _max;
|
||||
|
||||
for(PxU32 i = 1; i < numVerts; ++i)
|
||||
{
|
||||
PxPrefetchLine(&verts[i], 128);
|
||||
const Vec3V vertex = V3LoadU_SafeReadW(verts[i]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
const FloatV dist = V3Dot(vertex, _dir);
|
||||
|
||||
_max = FMax(dist, _max);
|
||||
_min = FMin(dist, _min);
|
||||
}
|
||||
|
||||
min = _min;
|
||||
max = _max;
|
||||
}
|
||||
|
||||
//This function support no scaling, dir is in the shape space(the same as vertex space)
|
||||
PX_SUPPORT_INLINE void supportVertexMinMax(const aos::Vec3VArg dir, aos::FloatV& min, aos::FloatV& max)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
if(data)
|
||||
{
|
||||
const PxU32 maxIndex = hillClimbing(dir);
|
||||
const PxU32 minIndex = hillClimbing(V3Neg(dir));
|
||||
const Vec3V maxPoint = V3LoadU_SafeReadW(verts[maxIndex]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
const Vec3V minPoint = V3LoadU_SafeReadW(verts[minIndex]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'verts' is initialized with ConvexHullData::getHullVertices())
|
||||
min = V3Dot(dir, minPoint);
|
||||
max = V3Dot(dir, maxPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
bruteForceSearchMinMax(dir, min, max);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define PX_CONVEX_TO_NOSCALECONVEX(x) (static_cast<const ConvexHullNoScaleV*>(x))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //
|
||||
218
engine/third_party/physx/source/geomutils/src/gjk/GuVecPlane.h
vendored
Normal file
218
engine/third_party/physx/source/geomutils/src/gjk/GuVecPlane.h
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
// 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_VEC_PLANE_H
|
||||
#define GU_VEC_PLANE_H
|
||||
|
||||
#include "foundation/PxVec3.h"
|
||||
#include "foundation/PxPlane.h"
|
||||
#include "foundation/PxVecMath.h"
|
||||
|
||||
/**
|
||||
\brief Representation of a plane.
|
||||
|
||||
Plane equation used: a*x + b*y + c*z + d = 0
|
||||
*/
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
|
||||
class PlaneV
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief Constructor
|
||||
*/
|
||||
PX_FORCE_INLINE PlaneV()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Constructor from a normal and a distance
|
||||
*/
|
||||
PX_FORCE_INLINE PlaneV(const aos::FloatVArg nx, const aos::FloatVArg ny, const aos::FloatVArg nz, const aos::FloatVArg _d)
|
||||
{
|
||||
set(nx, ny, nz, _d);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PlaneV(const PxPlane& plane)
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V _n = V3LoadU(plane.n);
|
||||
const FloatV _d = FLoad(plane.d);
|
||||
nd = V4SetW(Vec4V_From_Vec3V(_n), _d);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Constructor from three points
|
||||
*/
|
||||
PX_FORCE_INLINE PlaneV(const aos::Vec3VArg p0, const aos::Vec3VArg p1, const aos::Vec3VArg p2)
|
||||
{
|
||||
set(p0, p1, p2);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Constructor from a normal and a distance
|
||||
*/
|
||||
PX_FORCE_INLINE PlaneV(const aos::Vec3VArg _n, const aos::FloatVArg _d)
|
||||
{
|
||||
nd = aos::V4SetW(aos::Vec4V_From_Vec3V(_n), _d);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Copy constructor
|
||||
*/
|
||||
PX_FORCE_INLINE PlaneV(const PlaneV& plane) : nd(plane.nd)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Destructor
|
||||
*/
|
||||
PX_FORCE_INLINE ~PlaneV()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets plane to zero.
|
||||
*/
|
||||
PX_FORCE_INLINE PlaneV& setZero()
|
||||
{
|
||||
nd = aos::V4Zero();
|
||||
return *this;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PlaneV& set(const aos::FloatVArg nx, const aos::FloatVArg ny, const aos::FloatVArg nz, const aos::FloatVArg _d)
|
||||
{
|
||||
|
||||
using namespace aos;
|
||||
const Vec3V n = V3Merge(nx, ny, nz);
|
||||
nd = V4SetW(Vec4V_From_Vec3V(n), _d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PlaneV& set(const aos::Vec3VArg _normal, aos::FloatVArg _d)
|
||||
{
|
||||
nd = aos::V4SetW(aos::Vec4V_From_Vec3V(_normal), _d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Computes the plane equation from 3 points.
|
||||
*/
|
||||
PlaneV& set(const aos::Vec3VArg p0, const aos::Vec3VArg p1, const aos::Vec3VArg p2)
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V edge0 = V3Sub(p1, p0);
|
||||
const Vec3V edge1 = V3Sub(p2, p0);
|
||||
|
||||
const Vec3V n = V3Normalize(V3Cross(edge0, edge1));
|
||||
// See comments in set() for computation of d
|
||||
const FloatV d = FNeg(V3Dot(p0, n));
|
||||
nd = V4SetW(Vec4V_From_Vec3V(n), d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Computes distance, assuming plane is normalized
|
||||
\sa normalize
|
||||
*/
|
||||
PX_FORCE_INLINE aos::FloatV distance(const aos::Vec3VArg p) const
|
||||
{
|
||||
// Valid for plane equation a*x + b*y + c*z + d = 0
|
||||
using namespace aos;
|
||||
const Vec3V n = Vec3V_From_Vec4V(nd);
|
||||
return FAdd(V3Dot(p, n), V4GetW(nd));
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::BoolV belongs(const aos::Vec3VArg p) const
|
||||
{
|
||||
using namespace aos;
|
||||
const FloatV eps = FLoad(1.0e-7f);
|
||||
return FIsGrtr(eps, FAbs(distance(p)));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief projects p into the plane
|
||||
*/
|
||||
PX_FORCE_INLINE aos::Vec3V project(const aos::Vec3VArg p) const
|
||||
{
|
||||
// Pretend p is on positive side of plane, i.e. plane.distance(p)>0.
|
||||
// To project the point we have to go in a direction opposed to plane's normal, i.e.:
|
||||
using namespace aos;
|
||||
const Vec3V n = Vec3V_From_Vec4V(nd);
|
||||
return V3Sub(p, V3Scale(n, V4GetW(nd)));
|
||||
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV signedDistanceHessianNormalForm(const aos::Vec3VArg point) const
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V n = Vec3V_From_Vec4V(nd);
|
||||
return FAdd(V3Dot(n, point), V4GetW(nd));
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V getNormal() const
|
||||
{
|
||||
return aos::Vec3V_From_Vec4V(nd);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getSignDist() const
|
||||
{
|
||||
return aos::V4GetW(nd);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief find an arbitrary point in the plane
|
||||
*/
|
||||
PX_FORCE_INLINE aos::Vec3V pointInPlane() const
|
||||
{
|
||||
// Project origin (0,0,0) to plane:
|
||||
// (0) - normal * distance(0) = - normal * ((p|(0)) + d) = -normal*d
|
||||
using namespace aos;
|
||||
const Vec3V n = Vec3V_From_Vec4V(nd);
|
||||
return V3Neg(V3Scale(n, V4GetW(nd)));
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void normalize()
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V n = Vec3V_From_Vec4V(nd);
|
||||
const FloatV denom = FRecip(V3Length(n));
|
||||
V4Scale(nd, denom);
|
||||
}
|
||||
|
||||
aos::Vec4V nd; //!< The normal to the plan , w store the distance from the origin
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
239
engine/third_party/physx/source/geomutils/src/gjk/GuVecSphere.h
vendored
Normal file
239
engine/third_party/physx/source/geomutils/src/gjk/GuVecSphere.h
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
// 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_VEC_SPHERE_H
|
||||
#define GU_VEC_SPHERE_H
|
||||
|
||||
#include "geometry/PxSphereGeometry.h"
|
||||
#include "GuVecConvex.h"
|
||||
#include "GuConvexSupportTable.h"
|
||||
|
||||
/**
|
||||
\brief Represents a sphere defined by its center point and radius.
|
||||
*/
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
class SphereV : public ConvexV
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief Constructor
|
||||
*/
|
||||
PX_INLINE SphereV(): ConvexV(ConvexType::eSPHERE)
|
||||
{
|
||||
radius = aos::FZero();
|
||||
bMarginIsRadius = true;
|
||||
}
|
||||
|
||||
PX_INLINE SphereV(const aos::Vec3VArg _center, const aos::FloatV _radius) : ConvexV(ConvexType::eSPHERE, _center)
|
||||
{
|
||||
using namespace aos;
|
||||
radius = _radius;
|
||||
FStore(radius, &margin);
|
||||
FStore(radius, &minMargin);
|
||||
FStore(radius, &sweepMargin);
|
||||
bMarginIsRadius = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Copy constructor
|
||||
*/
|
||||
PX_INLINE SphereV(const SphereV& sphere) : ConvexV(ConvexType::eSPHERE), radius(sphere.radius)
|
||||
{
|
||||
|
||||
margin = sphere.margin;
|
||||
minMargin = sphere.minMargin;
|
||||
sweepMargin = sphere.sweepMargin;
|
||||
bMarginIsRadius = true;
|
||||
}
|
||||
|
||||
PX_INLINE SphereV(const PxGeometry& geom) : ConvexV(ConvexType::eSPHERE, aos::V3Zero())
|
||||
{
|
||||
using namespace aos;
|
||||
const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom);
|
||||
const FloatV r = FLoad(sphereGeom.radius);
|
||||
radius = r;
|
||||
margin = sphereGeom.radius;
|
||||
minMargin = sphereGeom.radius;
|
||||
sweepMargin = sphereGeom.radius;
|
||||
bMarginIsRadius = true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Destructor
|
||||
*/
|
||||
PX_INLINE ~SphereV()
|
||||
{
|
||||
}
|
||||
|
||||
PX_INLINE void setV(const aos::Vec3VArg _center, const aos::FloatVArg _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
|
||||
using namespace aos;
|
||||
return BAllEqTTTT(FIsGrtrOrEq(radius, FZero())) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\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 aos::Vec3VArg p) const
|
||||
{
|
||||
using namespace aos;
|
||||
const FloatV rr = FMul(radius, radius);
|
||||
const FloatV cc = V3LengthSq(V3Sub(center, p));
|
||||
return FAllGrtrOrEq(rr, cc) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Tests if a sphere is contained within the sphere.
|
||||
|
||||
\param sphere [in] the sphere to test
|
||||
\return true if inside the sphere
|
||||
*/
|
||||
PX_INLINE bool contains(const SphereV& sphere) const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const Vec3V centerDif = V3Sub(center, sphere.center);
|
||||
const FloatV radiusDif = FSub(radius, sphere.radius);
|
||||
const FloatV cc = V3Dot(centerDif, centerDif);
|
||||
const FloatV rr = FMul(radiusDif, radiusDif);
|
||||
|
||||
const BoolV con0 = FIsGrtrOrEq(radiusDif, FZero());//might contain
|
||||
const BoolV con1 = FIsGrtr(rr, cc);//return true
|
||||
return BAllEqTTTT(BAnd(con0, con1))==1;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Tests if a box is contained within the sphere.
|
||||
|
||||
\param minimum [in] minimum value of the box
|
||||
\param maximum [in] maximum value of the box
|
||||
\return true if inside the sphere
|
||||
*/
|
||||
PX_INLINE bool contains(const aos::Vec3VArg minimum, const aos::Vec3VArg maximum) const
|
||||
{
|
||||
|
||||
//compute the sphere which wrap around the box
|
||||
using namespace aos;
|
||||
const FloatV zero = FZero();
|
||||
const FloatV half = FHalf();
|
||||
|
||||
const Vec3V boxSphereCenter = V3Scale(V3Add(maximum, minimum), half);
|
||||
const Vec3V v = V3Scale(V3Sub(maximum, minimum), half);
|
||||
const FloatV boxSphereR = V3Length(v);
|
||||
|
||||
const Vec3V w = V3Sub(center, boxSphereCenter);
|
||||
const FloatV wLength = V3Length(w);
|
||||
const FloatV dif = FSub(FSub(radius, wLength), boxSphereR);
|
||||
|
||||
return FAllGrtrOrEq(dif, zero) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Tests if the sphere intersects another sphere
|
||||
|
||||
\param sphere [in] the other sphere
|
||||
\return true if spheres overlap
|
||||
*/
|
||||
PX_INLINE bool intersect(const SphereV& sphere) const
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V centerDif = V3Sub(center, sphere.center);
|
||||
const FloatV cc = V3Dot(centerDif, centerDif);
|
||||
const FloatV r = FAdd(radius, sphere.radius);
|
||||
const FloatV rr = FMul(r, r);
|
||||
return FAllGrtrOrEq(rr, cc) != 0;
|
||||
}
|
||||
|
||||
//return point in local space
|
||||
PX_FORCE_INLINE aos::Vec3V getPoint(const PxU8)
|
||||
{
|
||||
return aos::V3Zero();
|
||||
}
|
||||
//
|
||||
//sweep code need to have full version
|
||||
PX_FORCE_INLINE aos::Vec3V supportSweep(const aos::Vec3VArg dir)const
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V _dir = V3Normalize(dir);
|
||||
return V3ScaleAdd(_dir, radius, center);
|
||||
}
|
||||
|
||||
//make the support function the same as support margin
|
||||
PX_FORCE_INLINE aos::Vec3V support(const aos::Vec3VArg)const
|
||||
{
|
||||
return center;//_margin is the same as radius
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportMargin(const aos::Vec3VArg dir, const aos::FloatVArg _margin, aos::Vec3V& support)const
|
||||
{
|
||||
PX_UNUSED(_margin);
|
||||
PX_UNUSED(dir);
|
||||
|
||||
support = center;
|
||||
return center;//_margin is the same as radius
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::BoolV isMarginEqRadius()const
|
||||
{
|
||||
return aos::BTTTT();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getSweepMargin() const
|
||||
{
|
||||
return aos::FZero();
|
||||
}
|
||||
|
||||
|
||||
aos::FloatV radius; //!< Sphere's center, w component is radius
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
245
engine/third_party/physx/source/geomutils/src/gjk/GuVecTetrahedron.h
vendored
Normal file
245
engine/third_party/physx/source/geomutils/src/gjk/GuVecTetrahedron.h
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
// 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_VEC_TETRAHEDRON_H
|
||||
#define GU_VEC_TETRAHEDRON_H
|
||||
|
||||
#include "GuVecConvex.h"
|
||||
#include "GuConvexSupportTable.h"
|
||||
#include "GuDistancePointTriangle.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
|
||||
|
||||
class TetrahedronV : public ConvexV
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief Constructor
|
||||
*/
|
||||
PX_FORCE_INLINE TetrahedronV() : ConvexV(ConvexType::eTETRAHEDRON)
|
||||
{
|
||||
margin = 0.02f;
|
||||
minMargin = PX_MAX_REAL;
|
||||
sweepMargin = PX_MAX_REAL;
|
||||
}
|
||||
/**
|
||||
\brief Constructor
|
||||
|
||||
\param[in] p0 Point 0
|
||||
\param[in] p1 Point 1
|
||||
\param[in] p2 Point 2
|
||||
\param[in] p3 Point 3
|
||||
*/
|
||||
|
||||
PX_FORCE_INLINE TetrahedronV(const aos::Vec3VArg p0, const aos::Vec3VArg p1, const aos::Vec3VArg p2,
|
||||
const aos::Vec3VArg p3) : ConvexV(ConvexType::eTETRAHEDRON)
|
||||
{
|
||||
using namespace aos;
|
||||
//const FloatV zero = FZero();
|
||||
const FloatV num = FLoad(0.25f);
|
||||
center = V3Scale(V3Add(V3Add(p0, p1), V3Add(p2, p3)), num);
|
||||
//vertsX store all the x elements form those four point
|
||||
vertsX = V4SetW(V4SetZ(V4SetY(Vec4V_From_Vec3V(p0), V3GetX(p1)), V3GetX(p2)), V3GetX(p3));
|
||||
//vertsY store all the y elements from those four point
|
||||
vertsY = V4SetW(V4SetZ(V4SetY(V4Splat(V3GetY(p0)), V3GetY(p1)), V3GetY(p2)), V3GetY(p3));
|
||||
//vertsZ store all the z elements from those four point
|
||||
vertsZ = V4SetW(V4SetZ(V4SetY(V4Splat(V3GetZ(p0)), V3GetZ(p1)), V3GetZ(p2)), V3GetZ(p3));
|
||||
|
||||
verts[0] = p0; verts[1] = p1; verts[2] = p2; verts[3] = p3;
|
||||
margin = 0.f;
|
||||
minMargin = PX_MAX_REAL;
|
||||
sweepMargin = PX_MAX_REAL;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE TetrahedronV(const PxVec3* pts) : ConvexV(ConvexType::eTETRAHEDRON)
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V p0 = V3LoadU(pts[0]);
|
||||
const Vec3V p1 = V3LoadU(pts[1]);
|
||||
const Vec3V p2 = V3LoadU(pts[2]);
|
||||
const Vec3V p3 = V3LoadU(pts[3]);
|
||||
const FloatV num = FLoad(0.25f);
|
||||
center = V3Scale(V3Add(V3Add(p0, p1), V3Add(p2, p3)), num);
|
||||
|
||||
vertsX = V4SetW(V4SetZ(V4SetY(Vec4V_From_Vec3V(p0), V3GetX(p1)), V3GetX(p2)), V3GetX(p3));
|
||||
vertsY = V4SetW(V4SetZ(V4SetY(V4Splat(V3GetY(p0)), V3GetY(p1)), V3GetY(p2)), V3GetY(p3));
|
||||
vertsZ = V4SetW(V4SetZ(V4SetY(V4Splat(V3GetZ(p0)), V3GetZ(p1)), V3GetZ(p2)), V3GetZ(p3));
|
||||
|
||||
verts[0] = p0; verts[1] = p1; verts[2] = p2; verts[3] = p3;
|
||||
margin = 0.f;
|
||||
minMargin = PX_MAX_REAL;
|
||||
sweepMargin = PX_MAX_REAL;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Copy constructor
|
||||
|
||||
\param[in] tetrahedron Tetrahedron to copy
|
||||
*/
|
||||
PX_FORCE_INLINE TetrahedronV(const Gu::TetrahedronV& tetrahedron) : ConvexV(ConvexType::eTETRAHEDRON)
|
||||
{
|
||||
using namespace aos;
|
||||
vertsX = tetrahedron.vertsX;
|
||||
vertsY = tetrahedron.vertsY;
|
||||
vertsZ = tetrahedron.vertsZ;
|
||||
|
||||
verts[0] = tetrahedron.verts[0];
|
||||
verts[1] = tetrahedron.verts[1];
|
||||
verts[2] = tetrahedron.verts[2];
|
||||
verts[3] = tetrahedron.verts[3];
|
||||
|
||||
center = tetrahedron.center;
|
||||
margin = 0.f;
|
||||
minMargin = PX_MAX_REAL;
|
||||
sweepMargin = PX_MAX_REAL;
|
||||
}
|
||||
/**
|
||||
\brief Destructor
|
||||
*/
|
||||
PX_FORCE_INLINE ~TetrahedronV()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getSweepMargin() const
|
||||
{
|
||||
return aos::FMax();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setCenter(const aos::Vec3VArg _center)
|
||||
{
|
||||
using namespace aos;
|
||||
Vec3V offset = V3Sub(_center, center);
|
||||
center = _center;
|
||||
vertsX = V4Add(vertsX, V4Splat(V3GetX(offset)));
|
||||
vertsY = V4Add(vertsY, V4Splat(V3GetY(offset)));
|
||||
vertsZ = V4Add(vertsZ, V4Splat(V3GetZ(offset)));
|
||||
|
||||
verts[0] = V3Add(verts[0], offset);
|
||||
verts[1] = V3Add(verts[1], offset);
|
||||
verts[2] = V3Add(verts[2], offset);
|
||||
verts[3] = V3Add(verts[3], offset);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec4V getProjection(const aos::Vec3VArg dir) const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const Vec4V dx = V4Scale(vertsX, V3GetX(dir));
|
||||
const Vec4V dy = V4Scale(vertsY, V3GetY(dir));
|
||||
const Vec4V dz = V4Scale(vertsZ, V3GetZ(dir));
|
||||
|
||||
return V4Add(dx, V4Add(dy, dz));
|
||||
}
|
||||
|
||||
//dir is in local space, verts in the local space
|
||||
PX_FORCE_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir) const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
const Vec4V d = getProjection(dir);
|
||||
|
||||
const FloatV d0 = V4GetX(d);
|
||||
const FloatV d1 = V4GetY(d);
|
||||
const FloatV d2 = V4GetZ(d);
|
||||
const FloatV d3 = V4GetW(d);
|
||||
|
||||
const BoolV con0 = BAnd(BAnd(FIsGrtr(d0, d1), FIsGrtr(d0, d2)), FIsGrtr(d0, d3));
|
||||
const BoolV con1 = BAnd(FIsGrtr(d1, d2), FIsGrtr(d1, d3));
|
||||
const BoolV con2 = FIsGrtr(d2, d3);
|
||||
return V3Sel(con0, verts[0], V3Sel(con1, verts[1], V3Sel(con2, verts[2], verts[3])));
|
||||
}
|
||||
|
||||
|
||||
//dir is in b space
|
||||
PX_FORCE_INLINE aos::Vec3V supportRelative(const aos::Vec3VArg dir, const aos::PxMatTransformV& aToB, const aos::PxMatTransformV& aTobT) const
|
||||
{
|
||||
using namespace aos;
|
||||
//verts are in local space
|
||||
// const Vec3V _dir = aToB.rotateInv(dir); //transform dir back to a space
|
||||
const Vec3V _dir = aTobT.rotate(dir); //transform dir back to a space
|
||||
const Vec3V maxPoint = supportLocal(_dir);
|
||||
return aToB.transform(maxPoint);//transform maxPoint to the b space
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir, PxI32& index) const
|
||||
{
|
||||
|
||||
using namespace aos;
|
||||
|
||||
const Vec4V d = getProjection(dir);
|
||||
const FloatV d0 = V4GetX(d);
|
||||
const FloatV d1 = V4GetY(d);
|
||||
const FloatV d2 = V4GetZ(d);
|
||||
const FloatV d3 = V4GetW(d);
|
||||
|
||||
const BoolV con0 = BAnd(BAnd(FIsGrtr(d0, d1), FIsGrtr(d0, d2)), FIsGrtr(d0, d3));
|
||||
const BoolV con1 = BAnd(FIsGrtr(d1, d2), FIsGrtr(d1, d3));
|
||||
const BoolV con2 = FIsGrtr(d2, d3);
|
||||
|
||||
|
||||
const VecI32V vIndex = VecI32V_Sel(con0, I4Load(0), VecI32V_Sel(con1, I4Load(1), VecI32V_Sel(con2, I4Load(2), I4Load(3))));
|
||||
PxI32_From_VecI32V(vIndex, &index);
|
||||
|
||||
//return V3Sel(con0, v0, V3Sel(con1, v1, v2));
|
||||
return verts[index];
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportRelative(const aos::Vec3VArg dir, const aos::PxMatTransformV& aToB,
|
||||
const aos::PxMatTransformV& aTobT, PxI32& index)const
|
||||
{
|
||||
//don't put margin in the triangle
|
||||
using namespace aos;
|
||||
//transfer dir into the local space of triangle
|
||||
// const Vec3V _dir = aToB.rotateInv(dir);
|
||||
const Vec3V _dir = aTobT.rotate(dir);
|
||||
return aToB.transform(supportLocal(_dir, index));//transform the support poin to b space
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportPoint(const PxI32 index)const
|
||||
{
|
||||
return verts[index];
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Array of Vertices.
|
||||
*/
|
||||
aos::Vec3V verts[4];
|
||||
aos::Vec4V vertsX;
|
||||
aos::Vec4V vertsY;
|
||||
aos::Vec4V vertsZ;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
264
engine/third_party/physx/source/geomutils/src/gjk/GuVecTriangle.h
vendored
Normal file
264
engine/third_party/physx/source/geomutils/src/gjk/GuVecTriangle.h
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
// 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_VEC_TRIANGLE_H
|
||||
#define GU_VEC_TRIANGLE_H
|
||||
|
||||
#include "GuVecConvex.h"
|
||||
#include "GuConvexSupportTable.h"
|
||||
#include "GuDistancePointTriangle.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Gu
|
||||
{
|
||||
|
||||
|
||||
class TriangleV : public ConvexV
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief Constructor
|
||||
*/
|
||||
PX_FORCE_INLINE TriangleV() : ConvexV(ConvexType::eTRIANGLE)
|
||||
{
|
||||
margin = 0.02f;
|
||||
minMargin = PX_MAX_REAL;
|
||||
sweepMargin = PX_MAX_REAL;
|
||||
}
|
||||
/**
|
||||
\brief Constructor
|
||||
|
||||
\param[in] p0 Point 0
|
||||
\param[in] p1 Point 1
|
||||
\param[in] p2 Point 2
|
||||
*/
|
||||
|
||||
PX_FORCE_INLINE TriangleV(const aos::Vec3VArg p0, const aos::Vec3VArg p1, const aos::Vec3VArg p2): ConvexV(ConvexType::eTRIANGLE)
|
||||
{
|
||||
using namespace aos;
|
||||
//const FloatV zero = FZero();
|
||||
const FloatV num = FLoad(0.333333f);
|
||||
center = V3Scale(V3Add(V3Add(p0, p1), p2), num);
|
||||
verts[0] = p0;
|
||||
verts[1] = p1;
|
||||
verts[2] = p2;
|
||||
margin = 0.f;
|
||||
minMargin = PX_MAX_REAL;
|
||||
sweepMargin = PX_MAX_REAL;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE TriangleV(const PxVec3* pts) : ConvexV(ConvexType::eTRIANGLE)
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V p0 = V3LoadU(pts[0]);
|
||||
const Vec3V p1 = V3LoadU(pts[1]);
|
||||
const Vec3V p2 = V3LoadU(pts[2]);
|
||||
const FloatV num = FLoad(0.333333f);
|
||||
center = V3Scale(V3Add(V3Add(p0, p1), p2), num);
|
||||
verts[0] = p0;
|
||||
verts[1] = p1;
|
||||
verts[2] = p2;
|
||||
margin = 0.f;
|
||||
minMargin = PX_MAX_REAL;
|
||||
sweepMargin = PX_MAX_REAL;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Copy constructor
|
||||
|
||||
\param[in] triangle Tri to copy
|
||||
*/
|
||||
PX_FORCE_INLINE TriangleV(const Gu::TriangleV& triangle) : ConvexV(ConvexType::eTRIANGLE)
|
||||
{
|
||||
using namespace aos;
|
||||
verts[0] = triangle.verts[0];
|
||||
verts[1] = triangle.verts[1];
|
||||
verts[2] = triangle.verts[2];
|
||||
|
||||
center = triangle.center;
|
||||
margin = 0.f;
|
||||
minMargin = PX_MAX_REAL;
|
||||
sweepMargin = PX_MAX_REAL;
|
||||
}
|
||||
/**
|
||||
\brief Destructor
|
||||
*/
|
||||
PX_FORCE_INLINE ~TriangleV()
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void populateVerts(const PxU8* inds, PxU32 numInds, const PxVec3* originalVerts, aos::Vec3V* vertexs)const
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
for(PxU32 i=0; i<numInds; ++i)
|
||||
{
|
||||
vertexs[i] = V3LoadU(originalVerts[inds[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV getSweepMargin() const
|
||||
{
|
||||
return aos::FMax();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setCenter(const aos::Vec3VArg _center)
|
||||
{
|
||||
using namespace aos;
|
||||
Vec3V offset = V3Sub(_center, center);
|
||||
center = _center;
|
||||
verts[0] = V3Add(verts[0], offset);
|
||||
verts[1] = V3Add(verts[1], offset);
|
||||
verts[2] = V3Add(verts[2], offset);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Compute the normal of the Triangle.
|
||||
|
||||
\return Triangle normal.
|
||||
*/
|
||||
PX_FORCE_INLINE aos::Vec3V normal() const
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V ab = V3Sub(verts[1], verts[0]);
|
||||
const Vec3V ac = V3Sub(verts[2], verts[0]);
|
||||
const Vec3V n = V3Cross(ab, ac);
|
||||
return V3Normalize(n);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Compute the unnormalized normal of the Triangle.
|
||||
|
||||
\param[out] _normal Triangle normal (not normalized).
|
||||
*/
|
||||
PX_FORCE_INLINE void denormalizedNormal(aos::Vec3V& _normal) const
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V ab = V3Sub(verts[1], verts[0]);
|
||||
const Vec3V ac = V3Sub(verts[2], verts[0]);
|
||||
_normal = V3Cross(ab, ac);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::FloatV area() const
|
||||
{
|
||||
using namespace aos;
|
||||
const FloatV half = FLoad(0.5f);
|
||||
const Vec3V ba = V3Sub(verts[0], verts[1]);
|
||||
const Vec3V ca = V3Sub(verts[0], verts[2]);
|
||||
const Vec3V v = V3Cross(ba, ca);
|
||||
return FMul(V3Length(v), half);
|
||||
}
|
||||
|
||||
//dir is in local space, verts in the local space
|
||||
PX_FORCE_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir) const
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V v0 = verts[0];
|
||||
const Vec3V v1 = verts[1];
|
||||
const Vec3V v2 = verts[2];
|
||||
const FloatV d0 = V3Dot(v0, dir);
|
||||
const FloatV d1 = V3Dot(v1, dir);
|
||||
const FloatV d2 = V3Dot(v2, dir);
|
||||
|
||||
const BoolV con0 = BAnd(FIsGrtr(d0, d1), FIsGrtr(d0, d2));
|
||||
const BoolV con1 = FIsGrtr(d1, d2);
|
||||
return V3Sel(con0, v0, V3Sel(con1, v1, v2));
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void supportLocal(const aos::Vec3VArg dir, aos::FloatV& min, aos::FloatV& max) const
|
||||
{
|
||||
using namespace aos;
|
||||
const Vec3V v0 = verts[0];
|
||||
const Vec3V v1 = verts[1];
|
||||
const Vec3V v2 = verts[2];
|
||||
FloatV d0 = V3Dot(v0, dir);
|
||||
FloatV d1 = V3Dot(v1, dir);
|
||||
FloatV d2 = V3Dot(v2, dir);
|
||||
|
||||
max = FMax(d0, FMax(d1, d2));
|
||||
min = FMin(d0, FMin(d1, d2));
|
||||
}
|
||||
|
||||
//dir is in b space
|
||||
PX_FORCE_INLINE aos::Vec3V supportRelative(const aos::Vec3VArg dir, const aos::PxMatTransformV& aToB, const aos::PxMatTransformV& aTobT) const
|
||||
{
|
||||
using namespace aos;
|
||||
//verts are in local space
|
||||
// const Vec3V _dir = aToB.rotateInv(dir); //transform dir back to a space
|
||||
const Vec3V _dir = aTobT.rotate(dir); //transform dir back to a space
|
||||
const Vec3V maxPoint = supportLocal(_dir);
|
||||
return aToB.transform(maxPoint);//transform maxPoint to the b space
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir, PxI32& index) const
|
||||
{
|
||||
|
||||
using namespace aos;
|
||||
const VecI32V vZero = VecI32V_Zero();
|
||||
const VecI32V vOne = VecI32V_One();
|
||||
const VecI32V vTwo = VecI32V_Two();
|
||||
const Vec3V v0 = verts[0];
|
||||
const Vec3V v1 = verts[1];
|
||||
const Vec3V v2 = verts[2];
|
||||
const FloatV d0 = V3Dot(v0, dir);
|
||||
const FloatV d1 = V3Dot(v1, dir);
|
||||
const FloatV d2 = V3Dot(v2, dir);
|
||||
const BoolV con0 = BAnd(FIsGrtr(d0, d1), FIsGrtr(d0, d2));
|
||||
const BoolV con1 = FIsGrtr(d1, d2);
|
||||
const VecI32V vIndex = VecI32V_Sel(con0, vZero, VecI32V_Sel(con1, vOne, vTwo));
|
||||
PxI32_From_VecI32V(vIndex, &index);
|
||||
return V3Sel(con0, v0, V3Sel(con1, v1, v2));
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportRelative( const aos::Vec3VArg dir, const aos::PxMatTransformV& aToB,
|
||||
const aos::PxMatTransformV& aTobT, PxI32& index)const
|
||||
{
|
||||
//don't put margin in the triangle
|
||||
using namespace aos;
|
||||
//transfer dir into the local space of triangle
|
||||
// const Vec3V _dir = aToB.rotateInv(dir);
|
||||
const Vec3V _dir = aTobT.rotate(dir);
|
||||
return aToB.transform(supportLocal(_dir, index));//transform the support poin to b space
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE aos::Vec3V supportPoint(const PxI32 index)const
|
||||
{
|
||||
return verts[index];
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Array of Vertices.
|
||||
*/
|
||||
aos::Vec3V verts[3];
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user