Files
XCEngine/engine/third_party/physx/source/geomutils/src/GuSweepTests.cpp

1303 lines
39 KiB
C++
Raw Normal View History

// 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 "geometry/PxSphereGeometry.h"
#include "geometry/PxCustomGeometry.h"
#include "geometry/PxConvexCoreGeometry.h"
#include "geometry/PxHeightFieldGeometry.h"
#include "GuSweepTests.h"
#include "GuVecCapsule.h"
#include "GuVecBox.h"
#include "GuVecTriangle.h"
#include "GuSweepTriangleUtils.h"
#include "GuInternal.h"
#include "GuGJKRaycast.h"
#include "GuConvexGeometry.h"
#include "GuConvexSupport.h"
#include "GuMidphaseInterface.h"
#include "geometry/PxGjkQuery.h"
#include "GuHeightField.h"
#include "GuEntityReport.h"
#include "GuHeightFieldUtil.h"
using namespace physx;
using namespace Gu;
using namespace Cm;
using namespace aos;
//#define USE_VIRTUAL_GJK
#ifdef USE_VIRTUAL_GJK
static bool virtualGjkRaycastPenetration(const GjkConvex& a, const GjkConvex& 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)
{
return gjkRaycastPenetration<GjkConvex, GjkConvex >(a, b, initialDir, initialLambda, s, r, lambda, normal, closestA, _inflation, initialOverlap);
}
#endif
bool sweepCapsule_BoxGeom(GU_CAPSULE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(hitFlags);
PX_UNUSED(threadContext);
using namespace aos;
PX_ASSERT(geom.getType() == PxGeometryType::eBOX);
const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom);
const FloatV zero = FZero();
const Vec3V zeroV = V3Zero();
const Vec3V boxExtents0 = V3LoadU(boxGeom.halfExtents);
const FloatV dist = FLoad(distance);
const Vec3V worldDir = V3LoadU(unitDir);
const PxTransformV capPos = loadTransformU(capsulePose_);
const PxTransformV boxPos = loadTransformU(pose);
const PxMatTransformV aToB(boxPos.transformInv(capPos));
const FloatV capsuleHalfHeight = FLoad(capsuleGeom_.halfHeight);
const FloatV capsuleRadius = FLoad(lss.radius);
BoxV box(zeroV, boxExtents0);
CapsuleV capsule(aToB.p, aToB.rotate(V3Scale(V3UnitX(), capsuleHalfHeight)), capsuleRadius);
const Vec3V dir = boxPos.rotateInv(V3Neg(V3Scale(worldDir, dist)));
const bool isMtd = hitFlags & PxHitFlag::eMTD;
FloatV toi = FMax();
Vec3V closestA, normal;//closestA and normal is in the local space of box
const LocalConvex<CapsuleV> convexA(capsule);
const LocalConvex<BoxV> convexB(box);
const Vec3V initialSearchDir = V3Sub(capsule.getCenter(), box.getCenter());
#ifdef USE_VIRTUAL_GJK
if(!virtualGjkRaycastPenetration(convexA, convexB, initialSearchDir, zero, zeroV, dir, toi, normal, closestA, lss.radius + inflation, isMtd))
return false;
#else
if(!gjkRaycastPenetration<LocalConvex<CapsuleV>, LocalConvex<BoxV> >(convexA, convexB, initialSearchDir, zero, zeroV, dir, toi, normal, closestA, lss.radius + inflation, isMtd))
return false;
#endif
sweepHit.flags = PxHitFlag::eNORMAL;
if(FAllGrtrOrEq(zero, toi))
{
//initial overlap
if(isMtd)
{
sweepHit.flags |= PxHitFlag::ePOSITION;
const Vec3V worldPointA = boxPos.transform(closestA);
const Vec3V destNormal = boxPos.rotate(normal);
const FloatV length = toi;
const Vec3V destWorldPointA = V3NegScaleSub(destNormal, length, worldPointA);
V3StoreU(destWorldPointA, sweepHit.position);
V3StoreU(destNormal, sweepHit.normal);
FStore(length, &sweepHit.distance);
}
else
{
sweepHit.distance = 0.0f;
sweepHit.normal = -unitDir;
}
}
else
{
sweepHit.flags |= PxHitFlag::ePOSITION;
const Vec3V worldPointA = boxPos.transform(closestA);
const Vec3V destNormal = boxPos.rotate(normal);
const FloatV length = FMul(dist, toi);
const Vec3V destWorldPointA = V3ScaleAdd(worldDir, length, worldPointA);
V3StoreU(destNormal, sweepHit.normal);
V3StoreU(destWorldPointA, sweepHit.position);
FStore(length, &sweepHit.distance);
}
return true;
}
bool sweepBox_SphereGeom(GU_BOX_SWEEP_FUNC_PARAMS)
{
PX_ASSERT(geom.getType() == PxGeometryType::eSPHERE);
PX_UNUSED(threadContext);
PX_UNUSED(hitFlags);
PX_UNUSED(boxGeom_);
const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom);
const FloatV zero = FZero();
const Vec3V zeroV = V3Zero();
const Vec3V boxExtents = V3LoadU(box.extents);
const FloatV worldDist = FLoad(distance);
const Vec3V unitDirV = V3LoadU(unitDir);
const FloatV sphereRadius = FLoad(sphereGeom.radius);
const PxTransformV spherePos = loadTransformU(pose);
const PxTransformV boxPos = loadTransformU(boxPose_);
const PxMatTransformV aToB(boxPos.transformInv(spherePos));
const BoxV boxV(zeroV, boxExtents);
const CapsuleV capsuleV(aToB.p, sphereRadius);
//transform into b space
const Vec3V dir = boxPos.rotateInv(V3Scale(unitDirV, worldDist));
const bool isMtd = hitFlags & PxHitFlag::eMTD;
FloatV toi;
Vec3V closestA, normal;//closestA and normal is in the local space of box
const Vec3V initialSearchDir = V3Sub(capsuleV.getCenter(), boxV.getCenter());
const LocalConvex<CapsuleV> convexA(capsuleV);
const LocalConvex<BoxV> convexB(boxV);
#ifdef USE_VIRTUAL_GJK
if(!virtualGjkRaycastPenetration(convexA, convexB, initialSearchDir, zero, zeroV, dir, toi, normal, closestA, sphereGeom.radius+inflation, isMtd))
return false;
#else
if(!gjkRaycastPenetration<LocalConvex<CapsuleV>, LocalConvex<BoxV> >(convexA, convexB, initialSearchDir, zero, zeroV, dir, toi, normal, closestA, sphereGeom.radius+inflation, isMtd))
return false;
#endif
sweepHit.flags = PxHitFlag::eNORMAL;
//initial overlap
if(FAllGrtrOrEq(zero, toi))
{
if(isMtd)
{
sweepHit.flags |= PxHitFlag::ePOSITION;
const Vec3V destWorldPointA = boxPos.transform(closestA);
const Vec3V destNormal = V3Neg(boxPos.rotate(normal));
const FloatV length = toi;
V3StoreU(destNormal, sweepHit.normal);
V3StoreU(destWorldPointA, sweepHit.position);
FStore(length, &sweepHit.distance);
}
else
{
sweepHit.distance = 0.0f;
sweepHit.normal = -unitDir;
}
}
else
{
sweepHit.flags |= PxHitFlag::ePOSITION;
const Vec3V destWorldPointA = boxPos.transform(closestA);
const Vec3V destNormal = V3Neg(boxPos.rotate(normal));
const FloatV length = FMul(worldDist, toi);
V3StoreU(destNormal, sweepHit.normal);
V3StoreU(destWorldPointA, sweepHit.position);
FStore(length, &sweepHit.distance);
}
return true;
}
bool sweepBox_CapsuleGeom(GU_BOX_SWEEP_FUNC_PARAMS)
{
using namespace aos;
PX_ASSERT(geom.getType() == PxGeometryType::eCAPSULE);
PX_UNUSED(threadContext);
PX_UNUSED(hitFlags);
PX_UNUSED(boxGeom_);
const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom);
const FloatV capsuleHalfHeight = FLoad(capsuleGeom.halfHeight);
const FloatV capsuleRadius = FLoad(capsuleGeom.radius);
const FloatV zero = FZero();
const Vec3V zeroV = V3Zero();
const Vec3V boxExtents = V3LoadU(box.extents);
const FloatV worldDist = FLoad(distance);
const Vec3V unitDirV = V3LoadU(unitDir);
const PxTransformV capPos = loadTransformU(pose);
const PxTransformV boxPos = loadTransformU(boxPose_);
const PxMatTransformV aToB(boxPos.transformInv(capPos));
const BoxV boxV(zeroV, boxExtents);
const CapsuleV capsuleV(aToB.p, aToB.rotate(V3Scale(V3UnitX(), capsuleHalfHeight)), capsuleRadius);
//transform into b space
const Vec3V dir = boxPos.rotateInv(V3Scale(unitDirV, worldDist));
const bool isMtd = hitFlags & PxHitFlag::eMTD;
FloatV toi;
Vec3V closestA, normal;//closestA and normal is in the local space of box
const Vec3V initialSearchDir = V3Sub(capsuleV.getCenter(), boxV.getCenter());
const LocalConvex<CapsuleV> convexA(capsuleV);
const LocalConvex<BoxV> convexB(boxV);
#ifdef USE_VIRTUAL_GJK
if(!virtualGjkRaycastPenetration(convexA, convexB, initialSearchDir, zero, zeroV, dir, toi, normal, closestA, capsuleGeom.radius+inflation, isMtd))
return false;
#else
if(!gjkRaycastPenetration<LocalConvex<CapsuleV>, LocalConvex<BoxV> >(convexA, convexB, initialSearchDir, zero, zeroV, dir, toi, normal, closestA, capsuleGeom.radius+inflation, isMtd))
return false;
#endif
sweepHit.flags = PxHitFlag::eNORMAL;
//initial overlap
if(FAllGrtrOrEq(zero, toi))
{
if(isMtd)
{
sweepHit.flags |= PxHitFlag::ePOSITION;
//initial overlap is toi < 0
const FloatV length = toi;
const Vec3V destWorldPointA = boxPos.transform(closestA);
const Vec3V destNormal = boxPos.rotate(normal);
V3StoreU(V3Neg(destNormal), sweepHit.normal);
V3StoreU(destWorldPointA, sweepHit.position);
FStore(length, &sweepHit.distance);
}
else
{
sweepHit.distance = 0.0f;
sweepHit.normal = -unitDir;
}
return true;
}
else
{
sweepHit.flags |= PxHitFlag::ePOSITION;
const Vec3V destWorldPointA = boxPos.transform(closestA);
const Vec3V destNormal = boxPos.rotate(normal);
const FloatV length = FMul(worldDist, toi);
V3StoreU(V3Neg(destNormal), sweepHit.normal);
V3StoreU(destWorldPointA, sweepHit.position);
FStore(length, &sweepHit.distance);
}
return true;
}
bool sweepBox_BoxGeom(GU_BOX_SWEEP_FUNC_PARAMS)
{
PX_ASSERT(geom.getType() == PxGeometryType::eBOX);
PX_UNUSED(threadContext);
PX_UNUSED(boxGeom_);
const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom);
const FloatV zero = FZero();
const Vec3V zeroV = V3Zero();
const Vec3V boxExtents0 = V3LoadU(boxGeom.halfExtents);
const Vec3V boxExtents1 = V3LoadU(box.extents);
const FloatV worldDist = FLoad(distance);
const Vec3V unitDirV = V3LoadU(unitDir);
const PxTransformV boxTrans0 = loadTransformU(pose);
const PxTransformV boxTrans1 = loadTransformU(boxPose_);
const PxMatTransformV aToB(boxTrans1.transformInv(boxTrans0));
const BoxV box0(zeroV, boxExtents0);
const BoxV box1(zeroV, boxExtents1);
//transform into b space
const Vec3V dir = boxTrans1.rotateInv(V3Scale(unitDirV, worldDist));
const bool isMtd = hitFlags & PxHitFlag::eMTD;
FloatV toi;
Vec3V closestA, normal;//closestA and normal is in the local space of box
const RelativeConvex<BoxV> convexA(box0, aToB);
const LocalConvex<BoxV> convexB(box1);
#ifdef USE_VIRTUAL_GJK
if(!virtualGjkRaycastPenetration(convexA, convexB, aToB.p, zero, zeroV, dir, toi, normal, closestA, inflation, isMtd))
return false;
#else
if(!gjkRaycastPenetration<RelativeConvex<BoxV>, LocalConvex<BoxV> >(convexA, convexB, aToB.p, zero, zeroV, dir, toi, normal, closestA, inflation, isMtd))
return false;
#endif
sweepHit.flags = PxHitFlag::eNORMAL;
if(FAllGrtrOrEq(zero, toi))
{
if(isMtd)
{
sweepHit.flags |= PxHitFlag::ePOSITION;
const FloatV length = toi;
const Vec3V destWorldPointA = boxTrans1.transform(closestA);
const Vec3V destNormal = V3Normalize(boxTrans1.rotate(normal));
V3StoreU(V3Neg(destNormal), sweepHit.normal);
V3StoreU(destWorldPointA, sweepHit.position);
FStore(length, &sweepHit.distance);
}
else
{
sweepHit.distance = 0.0f;
sweepHit.normal = -unitDir;
}
}
else
{
sweepHit.flags |= PxHitFlag::ePOSITION;
const Vec3V destWorldPointA = boxTrans1.transform(closestA);
const Vec3V destNormal = V3Normalize(boxTrans1.rotate(normal));
const FloatV length = FMul(worldDist, toi);
V3StoreU(V3Neg(destNormal), sweepHit.normal);
V3StoreU(destWorldPointA, sweepHit.position);
FStore(length, &sweepHit.distance);
}
return true;
}
bool Gu::sweepBoxTriangles(GU_SWEEP_TRIANGLES_FUNC_PARAMS(PxBoxGeometry))
{
PX_UNUSED(hitFlags);
if(!nbTris)
return false;
const bool meshBothSides = hitFlags & PxHitFlag::eMESH_BOTH_SIDES;
const bool doBackfaceCulling = !doubleSided && !meshBothSides;
Box box;
buildFrom(box, pose.p, geom.halfExtents, pose.q);
PxGeomSweepHit sweepHit;
// Move to AABB space
PxMat34 worldToBox;
computeWorldToBoxMatrix(worldToBox, box);
const PxVec3 localDir = worldToBox.rotate(unitDir);
const PxVec3 localMotion = localDir * distance;
const Vec3V base0 = V3LoadU(worldToBox.m.column0);
const Vec3V base1 = V3LoadU(worldToBox.m.column1);
const Vec3V base2 = V3LoadU(worldToBox.m.column2);
const Mat33V matV(base0, base1, base2);
const Vec3V p = V3LoadU(worldToBox.p);
const PxMatTransformV worldToBoxV(p, matV);
const FloatV zero = FZero();
const Vec3V zeroV = V3Zero();
const Vec3V boxExtents = V3LoadU(box.extents);
const Vec3V boxDir = V3LoadU(localDir);
const FloatV inflationV = FLoad(inflation);
const Vec3V absBoxDir = V3Abs(boxDir);
const FloatV boxRadiusV = FAdd(V3Dot(absBoxDir, boxExtents), inflationV);
BoxV boxV(zeroV, boxExtents);
#if PX_DEBUG
PxU32 totalTestsExpected = nbTris;
PxU32 totalTestsReal = 0;
PX_UNUSED(totalTestsExpected);
PX_UNUSED(totalTestsReal);
#endif
Vec3V boxLocalMotion = V3LoadU(localMotion);
Vec3V minClosestA = zeroV, minNormal = zeroV;
PxU32 minTriangleIndex = 0;
PxVec3 bestTriNormal(0.0f);
FloatV dist = FLoad(distance);
const PxTransformV boxPos = loadTransformU(pose);
bool status = false;
const PxU32 idx = cachedIndex ? *cachedIndex : 0;
for(PxU32 ii=0;ii<nbTris;ii++)
{
const PxU32 triangleIndex = getTriangleIndex(ii, idx);
const Vec3V localV0 = V3LoadU(triangles[triangleIndex].verts[0]);
const Vec3V localV1 = V3LoadU(triangles[triangleIndex].verts[1]);
const Vec3V localV2 = V3LoadU(triangles[triangleIndex].verts[2]);
const Vec3V triV0 = worldToBoxV.transform(localV0);
const Vec3V triV1 = worldToBoxV.transform(localV1);
const Vec3V triV2 = worldToBoxV.transform(localV2);
const Vec3V triNormal = V3Cross(V3Sub(triV2, triV1),V3Sub(triV0, triV1));
if(doBackfaceCulling && FAllGrtrOrEq(V3Dot(triNormal, boxLocalMotion), zero)) // backface culling
continue;
const FloatV dp0 = V3Dot(triV0, boxDir);
const FloatV dp1 = V3Dot(triV1, boxDir);
const FloatV dp2 = V3Dot(triV2, boxDir);
const FloatV dp = FMin(dp0, FMin(dp1, dp2));
const Vec3V dpV = V3Merge(dp0, dp1, dp2);
const FloatV temp1 = FAdd(boxRadiusV, dist);
const BoolV con0 = FIsGrtr(dp, temp1);
const BoolV con1 = V3IsGrtr(zeroV, dpV);
if(BAllEqTTTT(BOr(con0, con1)))
continue;
#if PX_DEBUG
totalTestsReal++;
#endif
TriangleV triangleV(triV0, triV1, triV2);
FloatV lambda;
Vec3V closestA, normal;//closestA and normal is in the local space of convex hull
const LocalConvex<TriangleV> convexA(triangleV);
const LocalConvex<BoxV> convexB(boxV);
const Vec3V initialSearchDir = V3Sub(triangleV.getCenter(), boxV.getCenter());
#ifdef USE_VIRTUAL_GJK
if(virtualGjkRaycastPenetration(convexA, convexB, initialSearchDir, zero, zeroV, boxLocalMotion, lambda, normal, closestA, inflation, false))
#else
if(gjkRaycastPenetration<LocalConvex<TriangleV>, LocalConvex<BoxV> >(convexA, convexB, initialSearchDir, zero, zeroV, boxLocalMotion, lambda, normal, closestA, inflation, false))
#endif
{
//hitCount++;
if(FAllGrtrOrEq(zero, lambda))
{
hit.distance = 0.0f;
hit.faceIndex = triangleIndex;
hit.normal = -unitDir;
hit.flags = PxHitFlag::eNORMAL;
return true;
}
dist = FMul(dist, lambda);
boxLocalMotion = V3Scale(boxDir, dist);
minClosestA = closestA;
minNormal = normal;
minTriangleIndex = triangleIndex;
V3StoreU(triNormal, bestTriNormal);
status = true;
if(hitFlags & PxHitFlag::eANY_HIT)
break;
}
}
if(!status)
return false;
hit.faceIndex = minTriangleIndex;
const Vec3V destNormal = V3Neg(V3Normalize(boxPos.rotate(minNormal)));
const Vec3V destWorldPointA = boxPos.transform(minClosestA);
V3StoreU(destNormal, hit.normal);
V3StoreU(destWorldPointA, hit.position);
FStore(dist, &hit.distance);
// PT: by design, returned normal is opposed to the sweep direction.
if(shouldFlipNormal(hit.normal, meshBothSides, doubleSided, bestTriNormal, unitDir))
hit.normal = -hit.normal;
hit.flags = PxHitFlag::ePOSITION|PxHitFlag::eNORMAL;
return true;
}
bool sweepCapsule_SphereGeom (GU_CAPSULE_SWEEP_FUNC_PARAMS);
bool sweepCapsule_PlaneGeom (GU_CAPSULE_SWEEP_FUNC_PARAMS);
bool sweepCapsule_CapsuleGeom (GU_CAPSULE_SWEEP_FUNC_PARAMS);
bool sweepCapsule_BoxGeom (GU_CAPSULE_SWEEP_FUNC_PARAMS);
bool sweepCapsule_BoxGeom_Precise (GU_CAPSULE_SWEEP_FUNC_PARAMS);
bool sweepCapsule_ConvexGeom (GU_CAPSULE_SWEEP_FUNC_PARAMS);
bool sweepCapsule_MeshGeom (GU_CAPSULE_SWEEP_FUNC_PARAMS);
bool sweepCapsule_HeightFieldGeom (GU_CAPSULE_SWEEP_FUNC_PARAMS);
bool sweepBox_SphereGeom (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_SphereGeom_Precise (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_PlaneGeom (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_CapsuleGeom (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_CapsuleGeom_Precise (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_BoxGeom (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_BoxGeom_Precise (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_ConvexGeom (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_MeshGeom (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_HeightFieldGeom (GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepBox_HeightFieldGeom_Precise(GU_BOX_SWEEP_FUNC_PARAMS);
bool sweepConvex_SphereGeom (GU_CONVEX_SWEEP_FUNC_PARAMS);
bool sweepConvex_PlaneGeom (GU_CONVEX_SWEEP_FUNC_PARAMS);
bool sweepConvex_CapsuleGeom (GU_CONVEX_SWEEP_FUNC_PARAMS);
bool sweepConvex_BoxGeom (GU_CONVEX_SWEEP_FUNC_PARAMS);
bool sweepConvex_ConvexCoreGeom (GU_CONVEX_SWEEP_FUNC_PARAMS);
bool sweepConvex_ConvexGeom (GU_CONVEX_SWEEP_FUNC_PARAMS);
bool sweepConvex_MeshGeom (GU_CONVEX_SWEEP_FUNC_PARAMS);
bool sweepConvex_HeightFieldGeom (GU_CONVEX_SWEEP_FUNC_PARAMS);
static bool sweepCapsule_InvalidGeom(GU_CAPSULE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(capsuleGeom_);
PX_UNUSED(capsulePose_);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(lss);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
return false;
}
static bool sweepBox_InvalidGeom(GU_BOX_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(boxPose_);
PX_UNUSED(boxGeom_);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(box);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
return false;
}
static bool sweepConvexCore_InvalidGeom(GU_CONVEXCORE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(convexGeom);
PX_UNUSED(convexPose);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
return false;
}
static bool sweepConvex_InvalidGeom(GU_CONVEX_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(convexGeom);
PX_UNUSED(convexPose);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
return false;
}
static bool sweepCapsule_CustomGeom(GU_CAPSULE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(lss);
if(geom.getType() == PxGeometryType::eCUSTOM)
return static_cast<const PxCustomGeometry&>(geom).callbacks->sweep(unitDir, distance, geom, pose, capsuleGeom_, capsulePose_, sweepHit, hitFlags, inflation, threadContext);
return false;
}
static bool sweepBox_CustomGeom(GU_BOX_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(box);
if(geom.getType() == PxGeometryType::eCUSTOM)
return static_cast<const PxCustomGeometry&>(geom).callbacks->sweep(unitDir, distance, geom, pose, boxGeom_, boxPose_, sweepHit, hitFlags, inflation, threadContext);
return false;
}
static bool sweepConvexCore_CustomGeom(GU_CONVEXCORE_SWEEP_FUNC_PARAMS)
{
if (geom.getType() == PxGeometryType::eCUSTOM)
return static_cast<const PxCustomGeometry&>(geom).callbacks->sweep(unitDir, distance, geom, pose, convexGeom, convexPose, sweepHit, hitFlags, inflation, threadContext);
return false;
}
static bool sweepConvex_CustomGeom(GU_CONVEX_SWEEP_FUNC_PARAMS)
{
if(geom.getType() == PxGeometryType::eCUSTOM)
return static_cast<const PxCustomGeometry&>(geom).callbacks->sweep(unitDir, distance, geom, pose, convexGeom, convexPose, sweepHit, hitFlags, inflation, threadContext);
return false;
}
static bool sweepCapsule_ConvexCoreGeom(GU_CAPSULE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(capsuleGeom_);
PX_UNUSED(capsulePose_);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(lss);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
struct CapsuleSupport : PxGjkQuery::Support
{
PxCapsuleGeometry capsule;
CapsuleSupport(const PxCapsuleGeometry& c)
: capsule(c) {}
virtual PxReal getMargin() const
{ return capsule.radius; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ return PxVec3(PxSign(dir.x) * capsule.halfHeight, 0, 0); }
};
struct ConvexCoreSupport : PxGjkQuery::Support
{
Gu::ConvexShape shape;
ConvexCoreSupport(const PxConvexCoreGeometry& g)
{ Gu::makeConvexShape(g, PxTransform(PxIdentity), shape); }
virtual PxReal getMargin() const
{ return shape.margin; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ return shape.supportLocal(dir); }
};
const PxConvexCoreGeometry& convex = static_cast<const PxConvexCoreGeometry&>(geom);
if (convex.isValid())
{
PxBounds3 bounds = Gu::computeBounds(convex, pose);
bounds.include(Gu::computeBounds(capsuleGeom_, capsulePose_));
PxReal wiseDist = PxMin(distance, bounds.getDimensions().magnitude());
PxReal t;
PxVec3 n, p;
if (PxGjkQuery::sweep(ConvexCoreSupport(convex), CapsuleSupport(capsuleGeom_), pose, capsulePose_, unitDir, wiseDist, t, n, p))
{
PxGeomSweepHit& hit = sweepHit;
hit.distance = t;
hit.position = p;
hit.normal = n;
hit.flags |= PxHitFlag::ePOSITION | PxHitFlag::eNORMAL;
return 1;
}
}
return 0;
}
static bool sweepBox_ConvexCoreGeom(GU_BOX_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(boxPose_);
PX_UNUSED(boxGeom_);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(box);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
struct BoxSupport : PxGjkQuery::Support
{
PxBoxGeometry box;
BoxSupport(const PxBoxGeometry& b)
: box(b) {}
virtual PxReal getMargin() const
{ return 0; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ return PxVec3(PxSign(dir.x) * box.halfExtents.x,
PxSign(dir.y) * box.halfExtents.y, PxSign(dir.z) * box.halfExtents.z); }
};
struct ConvexCoreSupport : PxGjkQuery::Support
{
Gu::ConvexShape shape;
ConvexCoreSupport(const PxConvexCoreGeometry& g)
{ Gu::makeConvexShape(g, PxTransform(PxIdentity), shape); }
virtual PxReal getMargin() const
{ return shape.margin; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ return shape.supportLocal(dir); }
};
const PxConvexCoreGeometry& convex = static_cast<const PxConvexCoreGeometry&>(geom);
if (convex.isValid())
{
PxBounds3 bounds = Gu::computeBounds(convex, pose);
bounds.include(Gu::computeBounds(boxGeom_, boxPose_));
PxReal wiseDist = PxMin(distance, bounds.getDimensions().magnitude());
PxReal t;
PxVec3 n, p;
if (PxGjkQuery::sweep(ConvexCoreSupport(convex), BoxSupport(boxGeom_), pose, boxPose_, unitDir, wiseDist, t, n, p))
{
PxGeomSweepHit& hit = sweepHit;
hit.distance = t;
hit.position = p;
hit.normal = n;
hit.flags |= PxHitFlag::ePOSITION | PxHitFlag::eNORMAL;
return 1;
}
}
return 0;
}
static bool sweepConvexCore_Plane(GU_CONVEXCORE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(convexGeom);
PX_UNUSED(convexPose);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
PxPlane plane = getPlane(pose);
Gu::ConvexShape shape;
Gu::makeConvexShape(convexGeom, convexPose, shape);
shape.margin += inflation;
PxVec3 closestPoint = shape.support(-plane.n);
PxReal closestDist = plane.distance(closestPoint);
sweepHit.faceIndex = 0xffffffff;
if (closestDist <= 0)
{
if (hitFlags & PxHitFlag::eMTD)
{
sweepHit.flags = PxHitFlag::eNORMAL | PxHitFlag::ePOSITION;
sweepHit.distance = closestDist;
sweepHit.normal = plane.n;
sweepHit.position = closestPoint + plane.n * closestDist;
return true;
}
else if (!(hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP))
{
sweepHit.flags = PxHitFlag::eNORMAL;
sweepHit.distance = 0.0f;
sweepHit.normal = -unitDir;
return true;
}
}
PxReal dirDotNorm = unitDir.dot(plane.n);
const PxReal dotEps = 1e-5f;
if (dirDotNorm < -dotEps)
{
PxReal hitDistance = closestDist / -dirDotNorm;
if (hitDistance < distance)
{
sweepHit.flags = PxHitFlag::eNORMAL | PxHitFlag::ePOSITION;
sweepHit.distance = hitDistance;
sweepHit.normal = plane.n;
sweepHit.position = closestPoint + unitDir * hitDistance;
return true;
}
}
return false;
}
static bool sweepConvexCore_Convex(GU_CONVEXCORE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(convexGeom);
PX_UNUSED(convexPose);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
bool res = false;
switch (geom.getType())
{
case PxGeometryType::eSPHERE:
res = sweepCapsule_ConvexCoreGeom(convexGeom, convexPose, PxCapsuleGeometry(static_cast<const PxSphereGeometry&>(geom).radius, 0),
pose, Gu::Capsule(), -unitDir, distance, sweepHit, hitFlags, inflation, threadContext);
break;
case PxGeometryType::eCAPSULE:
res = sweepCapsule_ConvexCoreGeom(convexGeom, convexPose, static_cast<const PxCapsuleGeometry&>(geom), pose,
Gu::Capsule(), -unitDir, distance, sweepHit, hitFlags, inflation, threadContext);
break;
case PxGeometryType::eBOX:
res = sweepBox_ConvexCoreGeom(convexGeom, convexPose, static_cast<const PxBoxGeometry&>(geom), pose,
Gu::Box(), -unitDir, distance, sweepHit, hitFlags, inflation, threadContext);
break;
case PxGeometryType::eCONVEXMESH:
res = sweepConvex_ConvexCoreGeom(convexGeom, convexPose, static_cast<const PxConvexMeshGeometry&>(geom), pose,
-unitDir, distance, sweepHit, hitFlags, inflation, threadContext);
break;
default:
PX_ASSERT(0);
}
if (res)
{
if (sweepHit.flags & PxHitFlag::eNORMAL)
sweepHit.normal = -sweepHit.normal;
if (sweepHit.flags & PxHitFlag::ePOSITION)
sweepHit.position += unitDir * sweepHit.distance;
}
return res;
}
static bool sweepConvexCore_ConvexCore(GU_CONVEXCORE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(convexGeom);
PX_UNUSED(convexPose);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
struct ConvexCoreSupport : PxGjkQuery::Support
{
Gu::ConvexShape shape;
ConvexCoreSupport(const PxConvexCoreGeometry& g)
{ Gu::makeConvexShape(g, PxTransform(PxIdentity), shape); }
virtual PxReal getMargin() const
{ return shape.margin; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ return shape.supportLocal(dir); }
};
const PxConvexCoreGeometry& convex = static_cast<const PxConvexCoreGeometry&>(geom);
if (convex.isValid())
{
PxBounds3 bounds = Gu::computeBounds(convex, pose);
bounds.include(Gu::computeBounds(convexGeom, convexPose));
PxReal wiseDist = PxMin(distance, bounds.getDimensions().magnitude());
PxReal t;
PxVec3 n, p;
if (PxGjkQuery::sweep(ConvexCoreSupport(convex), ConvexCoreSupport(convexGeom), pose, convexPose, unitDir, wiseDist, t, n, p))
{
PxGeomSweepHit& hit = sweepHit;
hit.distance = t;
hit.position = p;
hit.normal = n;
hit.flags |= PxHitFlag::ePOSITION | PxHitFlag::eNORMAL;
return true;
}
}
return false;
}
static bool sweepConvexCore_MeshGeom(GU_CONVEXCORE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(convexGeom);
PX_UNUSED(convexPose);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
struct TriSupport : PxGjkQuery::Support
{
PxVec3 v0, v1, v2;
TriSupport(const PxVec3& _v0, const PxVec3& _v1, const PxVec3& _v2)
: v0(_v0), v1(_v1), v2(_v2) {}
virtual PxReal getMargin() const
{ return 0; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ PxReal d0 = dir.dot(v0), d1 = dir.dot(v1), d2 = dir.dot(v2);
return (d0 > d1 && d0 > d2) ? v0 : (d1 > d2) ? v1 : v2; }
};
struct ConvexCoreSupport : PxGjkQuery::Support
{
Gu::ConvexShape shape;
PxReal inflation;
ConvexCoreSupport(const PxConvexCoreGeometry& g, PxReal inf)
: inflation(inf)
{ Gu::makeConvexShape(g, PxTransform(PxIdentity), shape); }
virtual PxReal getMargin() const
{ return shape.margin + inflation; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ return shape.supportLocal(dir); }
};
struct Callback : MeshHitCallback<PxGeomRaycastHit>
{
ConvexCoreSupport convexSupport;
PxTransform convexPose;
PxVec3 unitDir;
PxReal maxDist;
PxGeomSweepHit closestHit;
Callback(const PxConvexCoreGeometry& geom, const PxTransform& pose, const PxVec3& dir, PxReal dist, PxReal inf)
:
MeshHitCallback<PxGeomRaycastHit>(CallbackMode::eMULTIPLE),
convexSupport(geom, inf), convexPose(pose), unitDir(dir), maxDist(dist)
{
closestHit.distance = FLT_MAX;
}
virtual PxAgain processHit(const PxGeomRaycastHit& hit, const PxVec3& v0, const PxVec3& v1, const PxVec3& v2, PxReal&, const PxU32*)
{
PxReal t; PxVec3 n, p;
TriSupport triSupport(v0, v1, v2);
if (PxGjkQuery::sweep(triSupport, convexSupport, PxTransform(PxIdentity), convexPose, unitDir, maxDist, t, n, p))
{
if (t < closestHit.distance)
{
closestHit.distance = t;
closestHit.position = p;
closestHit.normal = n;
closestHit.faceIndex = hit.faceIndex;
}
}
return true;
}
};
const PxTriangleMeshGeometry& meshGeom = static_cast<const PxTriangleMeshGeometry&>(geom);
const TriangleMesh* meshData = _getMeshData(meshGeom);
const bool doubleSided = (meshGeom.meshFlags & PxMeshGeometryFlag::eDOUBLE_SIDED) || (hitFlags & PxHitFlag::eMESH_BOTH_SIDES);
PxTransform localPose = pose.transformInv(convexPose);
PxVec3 localDir = pose.transformInv(unitDir);
PxBounds3 bounds = Gu::computeBounds(convexGeom, localPose);
bounds.include(Gu::computeBounds(convexGeom, PxTransform(localPose.p + localDir * distance, localPose.q)));
Box queryBox;
queryBox.extents = bounds.getExtents() + PxVec3(inflation);
queryBox.center = bounds.getCenter();
queryBox.rot = PxMat33(PxIdentity);
Callback callback(convexGeom, localPose, localDir, distance, inflation);
Midphase::intersectOBB(meshData, queryBox, callback, doubleSided);
if (callback.closestHit.distance <= distance)
{
PxGeomSweepHit& hit = sweepHit;
hit.distance = callback.closestHit.distance;
hit.position = pose.transform(callback.closestHit.position);
hit.normal = pose.rotate(callback.closestHit.normal);
hit.faceIndex = callback.closestHit.faceIndex;
hit.flags |= PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eFACE_INDEX;
return true;
}
return false;
}
bool sweepConvexCore_HeightFieldGeom(GU_CONVEXCORE_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(convexGeom);
PX_UNUSED(convexPose);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
struct TriSupport : PxGjkQuery::Support
{
PxVec3 v0, v1, v2;
TriSupport(const PxVec3& _v0, const PxVec3& _v1, const PxVec3& _v2)
: v0(_v0), v1(_v1), v2(_v2) {}
virtual PxReal getMargin() const
{ return 0; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ PxReal d0 = dir.dot(v0), d1 = dir.dot(v1), d2 = dir.dot(v2);
return (d0 > d1 && d0 > d2) ? v0 : (d1 > d2) ? v1 : v2; }
};
struct ConvexCoreSupport : PxGjkQuery::Support
{
Gu::ConvexShape shape;
PxReal inflation;
ConvexCoreSupport(const PxConvexCoreGeometry& g, PxReal inf)
: inflation(inf)
{ Gu::makeConvexShape(g, PxTransform(PxIdentity), shape); }
virtual PxReal getMargin() const
{ return shape.margin + inflation; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ return shape.supportLocal(dir); }
};
struct Callback : Gu::OverlapReport
{
ConvexCoreSupport convexSupport;
PxTransform convexPose;
PxVec3 unitDir;
PxReal maxDist;
const Gu::HeightFieldUtil mHfUtil;
const PxTransform& mHFPose;
PxGeomSweepHit closestHit;
Callback(const PxConvexCoreGeometry& geom, const PxTransform& pose, const PxVec3& dir, PxReal dist, PxReal inf, const PxHeightFieldGeometry& hfGeom, const PxTransform& hfPose)
: convexSupport(geom, inf), convexPose(pose), unitDir(dir), maxDist(dist), mHfUtil(hfGeom), mHFPose(hfPose)
{
closestHit.distance = FLT_MAX;
}
virtual bool reportTouchedTris(PxU32 nb, const PxU32* indices)
{
while(nb--)
{
const PxU32 triangleIndex = *indices++;
PxTrianglePadded currentTriangle;
mHfUtil.getTriangle(mHFPose, currentTriangle, NULL, NULL, triangleIndex, false, false);
const PxVec3& v0 = currentTriangle.verts[0];
const PxVec3& v1 = currentTriangle.verts[1];
const PxVec3& v2 = currentTriangle.verts[2];
PxReal t; PxVec3 n, p;
TriSupport triSupport(v0, v1, v2);
if (PxGjkQuery::sweep(triSupport, convexSupport, PxTransform(PxIdentity), convexPose, unitDir, maxDist, t, n, p))
{
if (t < closestHit.distance)
{
closestHit.distance = t;
closestHit.position = p;
closestHit.normal = n;
closestHit.faceIndex = triangleIndex;
}
}
}
return true;
}
};
const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom);
const HeightField* hf = static_cast<const HeightField*>(hfGeom.heightField);
if(!hf)
return false;
PxTransform localPose = pose.transformInv(convexPose);
PxVec3 localDir = pose.rotateInv(unitDir);
PxBounds3 bounds = Gu::computeBounds(convexGeom, localPose);
bounds.include(Gu::computeBounds(convexGeom, PxTransform(localPose.p + localDir * distance, localPose.q)));
Callback callback(convexGeom, localPose, localDir, distance, inflation, hfGeom, pose);
callback.mHfUtil.overlapAABBTriangles(bounds, callback, 4);
if (callback.closestHit.distance <= distance)
{
PxGeomSweepHit& hit = sweepHit;
hit.distance = callback.closestHit.distance;
hit.position = pose.transform(callback.closestHit.position);
hit.normal = pose.rotate(callback.closestHit.normal);
hit.faceIndex = callback.closestHit.faceIndex;
hit.flags |= PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eFACE_INDEX;
return true;
}
return false;
}
bool sweepConvex_ConvexCoreGeom(GU_CONVEX_SWEEP_FUNC_PARAMS)
{
PX_UNUSED(threadContext);
PX_UNUSED(geom);
PX_UNUSED(pose);
PX_UNUSED(convexGeom);
PX_UNUSED(convexPose);
PX_UNUSED(unitDir);
PX_UNUSED(distance);
PX_UNUSED(sweepHit);
PX_UNUSED(hitFlags);
PX_UNUSED(inflation);
struct ConvexSupport : PxGjkQuery::Support
{
PxConvexMeshGeometry convex;
PxReal inflation;
ConvexSupport(const PxConvexMeshGeometry& c, PxReal inf)
: convex(c), inflation(inf) {}
virtual PxReal getMargin() const
{ return inflation; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{
PxVec3 d = convex.scale.rotation.rotateInv(convex.scale.rotation.rotate(dir)
.multiply(convex.scale.scale));
const PxVec3* verts = convex.convexMesh->getVertices();
int count = int(convex.convexMesh->getNbVertices());
float maxDot = -FLT_MAX;
int index = -1;
for (int i = 0; i < count; ++i)
{
float dot = verts[i].dot(d);
if (dot > maxDot)
{
maxDot = dot;
index = i;
}
}
if (index == -1)
return PxVec3(0);
return convex.scale.rotation.rotateInv(convex.scale.rotation.rotate(verts[index])
.multiply(convex.scale.scale));
}
};
struct ConvexCoreSupport : PxGjkQuery::Support
{
Gu::ConvexShape shape;
ConvexCoreSupport(const PxConvexCoreGeometry& g)
{ Gu::makeConvexShape(g, PxTransform(PxIdentity), shape); }
virtual PxReal getMargin() const
{ return shape.margin; }
virtual PxVec3 supportLocal(const PxVec3& dir) const
{ return shape.supportLocal(dir); }
};
const PxConvexCoreGeometry& convex = static_cast<const PxConvexCoreGeometry&>(geom);
if (convex.isValid())
{
PxBounds3 bounds = Gu::computeBounds(convex, pose);
bounds.include(Gu::computeBounds(convexGeom, convexPose));
PxReal wiseDist = PxMin(distance, bounds.getDimensions().magnitude());
PxReal t;
PxVec3 n, p;
if (PxGjkQuery::sweep(ConvexCoreSupport(convex), ConvexSupport(convexGeom, inflation), pose,
convexPose, unitDir, wiseDist, t, n, p))
{
PxGeomSweepHit& hit = sweepHit;
hit.distance = t;
hit.position = p;
hit.normal = n;
hit.flags |= PxHitFlag::ePOSITION | PxHitFlag::eNORMAL;
return true;
}
}
return false;
}
Gu::GeomSweepFuncs gGeomSweepFuncs =
{
{
sweepCapsule_SphereGeom,
sweepCapsule_PlaneGeom,
sweepCapsule_CapsuleGeom,
sweepCapsule_BoxGeom,
sweepCapsule_ConvexCoreGeom,
sweepCapsule_ConvexGeom,
sweepCapsule_InvalidGeom,
sweepCapsule_InvalidGeom,
sweepCapsule_MeshGeom,
sweepCapsule_HeightFieldGeom,
sweepCapsule_CustomGeom
},
{
sweepCapsule_SphereGeom,
sweepCapsule_PlaneGeom,
sweepCapsule_CapsuleGeom,
sweepCapsule_BoxGeom_Precise,
sweepCapsule_ConvexCoreGeom,
sweepCapsule_ConvexGeom,
sweepCapsule_InvalidGeom,
sweepCapsule_InvalidGeom,
sweepCapsule_MeshGeom ,
sweepCapsule_HeightFieldGeom,
sweepCapsule_CustomGeom
},
{
sweepBox_SphereGeom,
sweepBox_PlaneGeom,
sweepBox_CapsuleGeom,
sweepBox_BoxGeom,
sweepBox_ConvexCoreGeom,
sweepBox_ConvexGeom,
sweepBox_InvalidGeom,
sweepBox_InvalidGeom,
sweepBox_MeshGeom,
sweepBox_HeightFieldGeom,
sweepBox_CustomGeom
},
{
sweepBox_SphereGeom_Precise,
sweepBox_PlaneGeom,
sweepBox_CapsuleGeom_Precise,
sweepBox_BoxGeom_Precise,
sweepBox_ConvexCoreGeom,
sweepBox_ConvexGeom,
sweepBox_InvalidGeom,
sweepBox_InvalidGeom,
sweepBox_MeshGeom,
sweepBox_HeightFieldGeom_Precise,
sweepBox_CustomGeom
},
{
sweepConvexCore_Convex, // 0
sweepConvexCore_Plane, // 1
sweepConvexCore_Convex, // 2
sweepConvexCore_Convex, // 3
sweepConvexCore_ConvexCore, // 4
sweepConvexCore_Convex, // 5
sweepConvexCore_InvalidGeom, // 6
sweepConvexCore_InvalidGeom, // 7
sweepConvexCore_MeshGeom, // 8
sweepConvexCore_HeightFieldGeom,// 9
sweepConvexCore_CustomGeom // 10
},
{
sweepConvex_SphereGeom, // 0
sweepConvex_PlaneGeom, // 1
sweepConvex_CapsuleGeom, // 2
sweepConvex_BoxGeom, // 3
sweepConvex_ConvexCoreGeom, // 4
sweepConvex_ConvexGeom, // 5
sweepConvex_InvalidGeom, // 6
sweepConvex_InvalidGeom, // 7
sweepConvex_MeshGeom, // 8
sweepConvex_HeightFieldGeom,// 9
sweepConvex_CustomGeom // 10
}
};
PX_PHYSX_COMMON_API const GeomSweepFuncs& Gu::getSweepFuncTable()
{
return gGeomSweepFuncs;
}