aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/GeomUtils/src/hf/GuSweepsHF.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/GeomUtils/src/hf/GuSweepsHF.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/GeomUtils/src/hf/GuSweepsHF.cpp')
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/hf/GuSweepsHF.cpp604
1 files changed, 604 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/hf/GuSweepsHF.cpp b/PhysX_3.4/Source/GeomUtils/src/hf/GuSweepsHF.cpp
new file mode 100644
index 00000000..323a7cb6
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/hf/GuSweepsHF.cpp
@@ -0,0 +1,604 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 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 "GuSweepTests.h"
+#include "GuHeightFieldUtil.h"
+#include "GuEntityReport.h"
+#include "GuVecCapsule.h"
+#include "GuSweepMTD.h"
+#include "GuSweepTriangleUtils.h"
+#include "GuVecBox.h"
+#include "GuVecShrunkBox.h"
+#include "CmScaling.h"
+#include "GuSweepCapsuleTriangle.h"
+#include "GuInternal.h"
+#include "GuGJKRaycast.h"
+
+using namespace physx;
+using namespace Gu;
+using namespace Cm;
+using namespace physx::shdfnd::aos;
+
+#include "GuSweepConvexTri.h"
+
+#define AbortTraversal false
+#define ContinueTraversal true
+
+///////////////////////////////////////////////////////////////////////////////
+
+class HeightFieldTraceSegmentSweepHelper
+{
+ PX_NOCOPY(HeightFieldTraceSegmentSweepHelper)
+public:
+ HeightFieldTraceSegmentSweepHelper(const HeightFieldUtil& hfUtil, const PxVec3& aabbExtentHfLocalSpace)
+ : mHfUtil(hfUtil), mOverlapObjectExtent(aabbExtentHfLocalSpace)
+ {
+ mHfUtil.computeLocalBounds(mLocalBounds);
+ // extend the bounds
+ mLocalBounds.minimum = mLocalBounds.minimum - aabbExtentHfLocalSpace;
+ mLocalBounds.maximum = mLocalBounds.maximum + aabbExtentHfLocalSpace;
+ }
+
+ template<class T>
+ PX_INLINE void traceSegment(const PxVec3& aP0, const PxVec3& rayDirNorm, const float rayLength, T* aCallback) const
+ {
+ mHfUtil.traceSegment<T, false, true>(aP0, rayDirNorm, rayLength, aCallback, mLocalBounds, false, &mOverlapObjectExtent);
+ }
+
+private:
+ const HeightFieldUtil& mHfUtil;
+ const PxVec3& mOverlapObjectExtent;
+ PxBounds3 mLocalBounds;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class HeightFieldTraceSegmentReport : public EntityReport<PxU32>
+{
+ PX_NOCOPY(HeightFieldTraceSegmentReport)
+public:
+
+ HeightFieldTraceSegmentReport(const HeightFieldUtil& hfUtil, const PxHitFlags hitFlags) :
+ mHfUtil (hfUtil),
+ mHitFlags (hitFlags),
+ mStatus (false),
+ mInitialOverlap (false),
+ mIsDoubleSided ((hfUtil.getHeightFieldGeometry().heightFieldFlags & PxMeshGeometryFlag::eDOUBLE_SIDED) || (hitFlags & PxHitFlag::eMESH_BOTH_SIDES)),
+ mIsAnyHit (hitFlags & PxHitFlag::eMESH_ANY)
+ {
+ }
+
+ bool underFaceHit(const Gu::HeightFieldUtil&, const PxVec3&, const PxVec3&, PxF32, PxF32, PxF32, PxU32)
+ {
+ return true;
+ }
+
+ bool faceHit(const Gu::HeightFieldUtil&, const PxVec3&, PxU32, PxReal, PxReal)
+ {
+ return true;
+ }
+
+ protected:
+ const HeightFieldUtil& mHfUtil;
+ const PxHitFlags mHitFlags;
+ bool mStatus;
+ bool mInitialOverlap;
+ const bool mIsDoubleSided;
+ const bool mIsAnyHit;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class CapsuleTraceSegmentReport : public HeightFieldTraceSegmentReport
+{
+ PX_NOCOPY(CapsuleTraceSegmentReport)
+public:
+ CapsuleTraceSegmentReport( const HeightFieldUtil& hfUtil, const PxHitFlags hitFlags,
+ const Capsule& inflatedCapsule,
+ const PxVec3& unitDir, PxSweepHit& sweepHit, const PxTransform& pose, PxReal distance) :
+ HeightFieldTraceSegmentReport (hfUtil, hitFlags),
+ mInflatedCapsule (inflatedCapsule),
+ mUnitDir (unitDir),
+ mSweepHit (sweepHit),
+ mPose (pose),
+ mDistance (distance)
+ {
+ }
+
+ virtual PxAgain onEvent(PxU32 nb, PxU32* indices)
+ {
+ PX_ALIGN_PREFIX(16) PxU8 tribuf[HF_SWEEP_REPORT_BUFFER_SIZE*sizeof(PxTriangle)] PX_ALIGN_SUFFIX(16);
+ PxTriangle* tmpT = reinterpret_cast<PxTriangle*>(tribuf);
+ PX_ASSERT(nb <= HF_SWEEP_REPORT_BUFFER_SIZE);
+ for(PxU32 i=0; i<nb; i++)
+ {
+ const PxU32 triangleIndex = indices[i];
+ mHfUtil.getTriangle(mPose, tmpT[i], NULL, NULL, triangleIndex, true);
+ }
+
+ PxSweepHit h; // PT: TODO: ctor!
+ // PT: this one is safe because cullbox is NULL (no need to allocate one more triangle)
+ // PT: TODO: is it ok to pass the initial distance here?
+ PxVec3 bestNormal;
+ const bool status = sweepCapsuleTriangles_Precise(nb, tmpT, mInflatedCapsule, mUnitDir, mDistance, NULL, h, bestNormal, mHitFlags, mIsDoubleSided);
+ if(status && (h.distance <= mSweepHit.distance))
+ {
+ mSweepHit.faceIndex = indices[h.faceIndex];
+ mSweepHit.normal = h.normal;
+ mSweepHit.position = h.position;
+ mSweepHit.distance = h.distance;
+
+ mStatus = true;
+ if(h.distance == 0.0f)
+ {
+ mInitialOverlap = true;
+ return AbortTraversal;
+ }
+
+ if(mIsAnyHit)
+ return AbortTraversal;
+ }
+ return ContinueTraversal;
+ }
+
+ bool finalizeHit(PxSweepHit& sweepHit, const PxHeightFieldGeometry& hfGeom, const PxTransform& pose, const Capsule& lss, const Capsule& inflatedCapsule, const PxVec3& unitDir)
+ {
+ if(!mStatus)
+ return false;
+
+ if(mInitialOverlap)
+ {
+ // PT: TODO: consider using 'setInitialOverlapResults' here
+ sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::eNORMAL | PxHitFlag::eFACE_INDEX;
+
+ if(mHitFlags & PxHitFlag::eMTD)
+ {
+ const Vec3V p0 = V3LoadU(lss.p0);
+ const Vec3V p1 = V3LoadU(lss.p1);
+ const FloatV radius = FLoad(lss.radius);
+ CapsuleV capsuleV;
+ capsuleV.initialize(p0, p1, radius);
+
+ //calculate MTD
+ const bool hasContacts = computeCapsule_HeightFieldMTD(hfGeom, pose, capsuleV, inflatedCapsule.radius, mIsDoubleSided, GuHfQueryFlags::eWORLD_SPACE, sweepHit);
+
+ //ML: the center of mass is below the surface, we won't have MTD contact generate
+ if(!hasContacts)
+ {
+ sweepHit.distance = 0.0f;
+ sweepHit.normal = -unitDir;
+ }
+ else
+ {
+ sweepHit.flags |= PxHitFlag::ePOSITION;
+ }
+ }
+ else
+ {
+ sweepHit.distance = 0.0f;
+ sweepHit.normal = -unitDir;
+ }
+ }
+ else
+ {
+ sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::eNORMAL| PxHitFlag::ePOSITION | PxHitFlag::eFACE_INDEX;
+ }
+ return true;
+ }
+
+ private:
+ const Capsule& mInflatedCapsule;
+ const PxVec3& mUnitDir;
+ PxSweepHit& mSweepHit;
+ const PxTransform& mPose;
+ const PxReal mDistance;
+};
+
+bool sweepCapsule_HeightFieldGeom(GU_CAPSULE_SWEEP_FUNC_PARAMS)
+{
+ PX_UNUSED(capsuleGeom_);
+ PX_UNUSED(capsulePose_);
+
+ PX_ASSERT(geom.getType() == PxGeometryType::eHEIGHTFIELD);
+ const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom);
+
+ const Capsule inflatedCapsule(lss.p0, lss.p1, lss.radius + inflation);
+
+ // Compute swept box
+ Box capsuleBox;
+ computeBoxAroundCapsule(inflatedCapsule, capsuleBox);
+
+ const PxVec3 capsuleAABBExtents = capsuleBox.computeAABBExtent();
+
+ const HeightFieldUtil hfUtil(hfGeom);
+ CapsuleTraceSegmentReport myReport(hfUtil, hitFlags, inflatedCapsule, unitDir, sweepHit, pose, distance);
+
+ sweepHit.distance = PX_MAX_F32;
+
+ // need hf local space stuff
+ const PxTransform inversePose = pose.getInverse();
+ const PxVec3 centerLocalSpace = inversePose.transform(capsuleBox.center);
+ const PxVec3 sweepDirLocalSpace = inversePose.rotate(unitDir);
+ const PxVec3 capsuleAABBBExtentHfLocalSpace = PxBounds3::basisExtent(centerLocalSpace, PxMat33Padded(inversePose.q), capsuleAABBExtents).getExtents();
+
+ HeightFieldTraceSegmentSweepHelper traceSegmentHelper(hfUtil, capsuleAABBBExtentHfLocalSpace);
+ traceSegmentHelper.traceSegment<CapsuleTraceSegmentReport>(centerLocalSpace, sweepDirLocalSpace, distance, &myReport);
+
+ return myReport.finalizeHit(sweepHit, hfGeom, pose, lss, inflatedCapsule, unitDir);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class ConvexTraceSegmentReport : public HeightFieldTraceSegmentReport
+{
+ PX_NOCOPY(ConvexTraceSegmentReport)
+public:
+ ConvexTraceSegmentReport( const HeightFieldUtil& hfUtil, const ConvexHullData& hull, const PxMeshScale& convexScale,
+ const PxTransform& convexPose, const PxTransform& heightFieldPose,
+ const PxVec3& unitDir, PxReal distance, PxHitFlags hitFlags, PxReal inflation) :
+ HeightFieldTraceSegmentReport (hfUtil, hitFlags),
+ mUnitDir (unitDir),
+ mInflation (inflation)
+ {
+ using namespace Ps::aos;
+ mSweepHit.faceIndex = 0xFFFFffff;
+ mSweepHit.distance = distance;
+ const Vec3V worldDir = V3LoadU(unitDir);
+ const FloatV dist = FLoad(distance);
+ const QuatV q0 = QuatVLoadU(&heightFieldPose.q.x);
+ const Vec3V p0 = V3LoadU(&heightFieldPose.p.x);
+
+ const QuatV q1 = QuatVLoadU(&convexPose.q.x);
+ const Vec3V p1 = V3LoadU(&convexPose.p.x);
+
+ const PsTransformV meshTransf(p0, q0);
+ const PsTransformV convexTransf(p1, q1);
+
+ mMeshToConvex = convexTransf.transformInv(meshTransf);
+ mConvexPoseV = convexTransf;
+ mConvexSpaceDir = convexTransf.rotateInv(V3Neg(V3Scale(worldDir, dist)));
+ mDistance = dist;
+
+ const Vec3V vScale = V3LoadU_SafeReadW(convexScale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale
+ const QuatV vQuat = QuatVLoadU(&convexScale.rotation.x);
+
+ mMeshSpaceUnitDir = heightFieldPose.rotateInv(unitDir);
+ mConvexHull.initialize(&hull, V3Zero(), vScale, vQuat, convexScale.isIdentity());
+ }
+
+ virtual PxAgain onEvent(PxU32 nbEntities, PxU32* entities)
+ {
+ const PxTransform idt(PxIdentity);
+ for(PxU32 i=0; i<nbEntities; i++)
+ {
+ PxTriangle tri;
+ mHfUtil.getTriangle(idt, tri, NULL, NULL, entities[i], false, false); // First parameter not needed if local space triangle is enough
+
+ // use mSweepHit.distance as max sweep distance so far, mSweepHit.distance will be clipped by this function
+ if(sweepConvexVsTriangle( tri.verts[0], tri.verts[1], tri.verts[2], mConvexHull, mMeshToConvex, mConvexPoseV,
+ mConvexSpaceDir, mUnitDir, mMeshSpaceUnitDir, mDistance, mSweepHit.distance, mSweepHit, mIsDoubleSided,
+ mInflation, mInitialOverlap, entities[i]))
+ {
+ mStatus = true;
+ if(mIsAnyHit || mSweepHit.distance == 0.0f)
+ return AbortTraversal;
+ }
+ }
+ return ContinueTraversal;
+ }
+
+ bool finalizeHit(PxSweepHit& sweepHit,
+ const PxHeightFieldGeometry& hfGeom, const PxTransform& pose,
+ const PxConvexMeshGeometry& convexGeom, const PxTransform& convexPose,
+ const PxVec3& unitDir, PxReal inflation)
+ {
+ if(!mStatus)
+ return false;
+
+ if(mInitialOverlap)
+ {
+ if(mHitFlags & PxHitFlag::eMTD)
+ {
+ const bool hasContacts = computeConvex_HeightFieldMTD(hfGeom, pose, convexGeom, convexPose, inflation, mIsDoubleSided, GuHfQueryFlags::eWORLD_SPACE, sweepHit);
+
+ sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::eNORMAL | PxHitFlag::eFACE_INDEX;
+ if(!hasContacts)
+ {
+ sweepHit.distance = 0.0f;
+ sweepHit.normal = -unitDir;
+ }
+ else
+ {
+ sweepHit.flags |= PxHitFlag::ePOSITION;
+ }
+ }
+ else
+ {
+ setInitialOverlapResults(sweepHit, unitDir, mSweepHit.faceIndex); // hit index must be set to closest for IO
+ }
+ }
+ else
+ {
+ sweepHit = mSweepHit;
+ sweepHit.normal = -sweepHit.normal;
+ sweepHit.normal.normalize();
+ }
+ return true;
+ }
+
+ private:
+ PsMatTransformV mMeshToConvex;
+ PsTransformV mConvexPoseV;
+ ConvexHullV mConvexHull;
+ PxSweepHit mSweepHit;
+ Vec3V mConvexSpaceDir;
+ FloatV mDistance;
+ const PxVec3 mUnitDir;
+ PxVec3 mMeshSpaceUnitDir;
+ const PxReal mInflation;
+};
+
+bool sweepConvex_HeightFieldGeom(GU_CONVEX_SWEEP_FUNC_PARAMS)
+{
+ PX_ASSERT(geom.getType() == PxGeometryType::eHEIGHTFIELD);
+ const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom);
+
+ const Matrix34 convexTM(convexPose);
+ const Matrix34 meshTM(pose);
+
+ ConvexMesh* convexMesh = static_cast<ConvexMesh*>(convexGeom.convexMesh);
+
+ const bool idtScaleConvex = convexGeom.scale.isIdentity();
+
+ FastVertex2ShapeScaling convexScaling;
+ if(!idtScaleConvex)
+ convexScaling.init(convexGeom.scale);
+
+ PX_ASSERT(!convexMesh->getLocalBoundsFast().isEmpty());
+ const PxBounds3 hullAABBLocalSpace = convexMesh->getLocalBoundsFast().transformFast(convexScaling.getVertex2ShapeSkew());
+
+ const HeightFieldUtil hfUtil(hfGeom);
+ ConvexTraceSegmentReport entityReport(
+ hfUtil, convexMesh->getHull(), convexGeom.scale, convexPose, pose, -unitDir, distance, hitFlags, inflation);
+
+ // need hf local space stuff
+ const PxBounds3 hullAABB = PxBounds3::transformFast(convexPose, hullAABBLocalSpace);
+ const PxVec3 aabbExtents = hullAABB.getExtents() + PxVec3(inflation);
+ const PxTransform inversePose = pose.getInverse();
+ const PxVec3 centerLocalSpace = inversePose.transform(hullAABB.getCenter());
+ const PxVec3 sweepDirLocalSpace = inversePose.rotate(unitDir);
+ const PxVec3 convexAABBExtentHfLocalSpace = PxBounds3::basisExtent(centerLocalSpace, PxMat33Padded(inversePose.q), aabbExtents).getExtents();
+
+ HeightFieldTraceSegmentSweepHelper traceSegmentHelper(hfUtil, convexAABBExtentHfLocalSpace);
+ traceSegmentHelper.traceSegment<ConvexTraceSegmentReport>(centerLocalSpace, sweepDirLocalSpace, distance, &entityReport);
+
+ return entityReport.finalizeHit(sweepHit, hfGeom, pose, convexGeom, convexPose, unitDir, inflation);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#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 BoxTraceSegmentReport : public HeightFieldTraceSegmentReport
+{
+ PX_NOCOPY(BoxTraceSegmentReport)
+public:
+ BoxTraceSegmentReport( const HeightFieldUtil& hfUtil, const PxHitFlags hitFlags,
+ const PsTransformV& worldToBoxV, const PxTransform& pose, const BoxV& box, const PxVec3& localMotion,
+ PxSweepHit& sweepHit, PxReal inflation) :
+ HeightFieldTraceSegmentReport (hfUtil, hitFlags),
+ mWorldToBoxV (worldToBoxV),
+ mPose (pose),
+ mBox (box),
+ mLocalMotion (localMotion),
+ mSweepHit (sweepHit),
+ mInflation (inflation)
+ {
+ mMinToi = FMax();
+ }
+
+ virtual PxAgain onEvent(PxU32 nb, PxU32* indices)
+ {
+ const FloatV zero = FZero();
+ const Vec3V zeroV = V3Zero();
+ const Vec3V dir = V3LoadU(mLocalMotion);
+ //FloatV minToi = FMax();
+ FloatV toi;
+ Vec3V closestA, normal;//closestA and normal is in the local space of box
+
+ for(PxU32 i=0; i<nb; i++)
+ {
+ const PxU32 triangleIndex = indices[i];
+
+ PxTriangle currentTriangle; // in world space
+ mHfUtil.getTriangle(mPose, currentTriangle, NULL, NULL, triangleIndex, true, true);
+
+ const Vec3V localV0 = V3LoadU(currentTriangle.verts[0]);
+ const Vec3V localV1 = V3LoadU(currentTriangle.verts[1]);
+ const Vec3V localV2 = V3LoadU(currentTriangle.verts[2]);
+
+ const Vec3V triV0 = mWorldToBoxV.transform(localV0);
+ const Vec3V triV1 = mWorldToBoxV.transform(localV1);
+ const Vec3V triV2 = mWorldToBoxV.transform(localV2);
+
+ if(!mIsDoubleSided)
+ {
+ const Vec3V triNormal = V3Cross(V3Sub(triV2, triV1),V3Sub(triV0, triV1));
+ if(FAllGrtrOrEq(V3Dot(triNormal, dir), zero))
+ continue;
+ }
+
+ const TriangleV triangle(triV0, triV1, triV2);
+
+ ////move triangle to box space
+ //const Vec3V localV0 = Vec3V_From_PxVec3(WorldToBox.transform(currentTriangle.verts[0]));
+ //const Vec3V localV1 = Vec3V_From_PxVec3(WorldToBox.transform(currentTriangle.verts[1]));
+ //const Vec3V localV2 = Vec3V_From_PxVec3(WorldToBox.transform(currentTriangle.verts[2]));
+
+ //TriangleV triangle(localV0, localV1, localV2);
+ const LocalConvex<TriangleV> convexA(triangle);
+ const LocalConvex<BoxV> convexB(mBox);
+ const Vec3V initialSearchDir = V3Sub(triangle.getCenter(), mBox.getCenter());
+
+ if(gjkRaycastPenetration< LocalConvex<TriangleV>, LocalConvex<BoxV> >(convexA, convexB, initialSearchDir, zero, zeroV, dir, toi, normal, closestA, mInflation, false))
+ {
+ mStatus = true;
+ if(FAllGrtr(toi, zero))
+ {
+ if(FAllGrtr(mMinToi, toi))
+ {
+ mMinToi = toi;
+ FStore(toi, &mSweepHit.distance);
+ V3StoreU(normal, mSweepHit.normal);
+ V3StoreU(closestA, mSweepHit.position);
+ mSweepHit.faceIndex = triangleIndex;
+
+ if(mIsAnyHit)
+ return AbortTraversal;
+ }
+ }
+ else
+ {
+ mSweepHit.distance = 0.0f;
+ mSweepHit.faceIndex = triangleIndex;
+ mInitialOverlap = true;
+ return AbortTraversal;
+ }
+ }
+ }
+ return ContinueTraversal;
+ }
+
+ bool finalizeHit(PxSweepHit& sweepHit,
+ const PxHeightFieldGeometry& hfGeom, const PxTransform& pose,
+ const PxTransform& boxPose_, const Box& box,
+ const PxVec3& unitDir, PxReal distance, PxReal inflation)
+ {
+ if(!mStatus)
+ return false;
+
+ if(mInitialOverlap)
+ {
+ // PT: TODO: consider using 'setInitialOverlapResults' here
+
+ sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::eNORMAL | PxHitFlag::eFACE_INDEX;
+
+ if(mHitFlags & PxHitFlag::eMTD)
+ {
+ const bool hasContacts = computeBox_HeightFieldMTD(hfGeom, pose, box, boxPose_, inflation, mIsDoubleSided, GuHfQueryFlags::eWORLD_SPACE, sweepHit);
+
+ //ML: the center of mass is below the surface, we won't have MTD contact generate
+ if(!hasContacts)
+ {
+ sweepHit.distance = 0.0f;
+ sweepHit.normal = -unitDir;
+ }
+ else
+ {
+ sweepHit.flags |= PxHitFlag::ePOSITION;
+ }
+ }
+ else
+ {
+ sweepHit.distance = 0.0f;
+ sweepHit.normal = -unitDir;
+ }
+ }
+ else
+ {
+ PxVec3 n = sweepHit.normal.getNormalized();
+ if((n.dot(mLocalMotion))>0.0f)
+ n = -n;
+
+ sweepHit.distance *= distance; // stored as toi [0,1] during computation -> scale
+ sweepHit.normal = boxPose_.rotate(n);
+ sweepHit.position = boxPose_.transform(sweepHit.position);
+ sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eFACE_INDEX;
+ }
+ return true;
+ }
+
+ private:
+ const PsTransformV& mWorldToBoxV;
+ const PxTransform& mPose;
+ const BoxV& mBox;
+ FloatV mMinToi;
+ const PxVec3 mLocalMotion;
+ PxSweepHit& mSweepHit;
+ const PxReal mInflation;
+};
+
+#if PX_VC
+ #pragma warning(pop)
+#endif
+
+bool sweepBox_HeightFieldGeom(GU_BOX_SWEEP_FUNC_PARAMS)
+{
+ PX_ASSERT(geom.getType() == PxGeometryType::eHEIGHTFIELD);
+ PX_UNUSED(boxGeom_);
+ PX_UNUSED(hitFlags);
+
+ const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom);
+
+ const PxVec3 boxAABBExtent = box.computeAABBExtent() + PxVec3(inflation);
+
+ // Move to AABB space
+ PX_ALIGN_PREFIX(16) PxTransform WorldToBox PX_ALIGN_SUFFIX(16);
+ WorldToBox = boxPose_.getInverse();
+
+ const QuatV q1 = QuatVLoadA(&WorldToBox.q.x);
+ const Vec3V p1 = V3LoadA(&WorldToBox.p.x);
+ const PsTransformV WorldToBoxV(p1, q1);
+
+ const PxVec3 motion = unitDir * distance;
+ const PxVec3 localMotion = WorldToBox.rotate(motion);
+
+ const BoxV boxV(V3Zero(), V3LoadU(box.extents));
+
+ sweepHit.distance = PX_MAX_F32;
+
+ const HeightFieldUtil hfUtil(hfGeom);
+ BoxTraceSegmentReport myReport(hfUtil, hitFlags, WorldToBoxV, pose, boxV, localMotion, sweepHit, inflation);
+
+ // need hf local space stuff
+ const PxTransform inversePose = pose.getInverse();
+ const PxVec3 centerLocalSpace = inversePose.transform(box.center);
+ const PxVec3 sweepDirLocalSpace = inversePose.rotate(unitDir);
+ const PxVec3 boxAABBExtentInHfLocalSpace = PxBounds3::basisExtent(centerLocalSpace, PxMat33Padded(inversePose.q), boxAABBExtent).getExtents();
+
+ HeightFieldTraceSegmentSweepHelper traceSegmentHelper(hfUtil, boxAABBExtentInHfLocalSpace);
+ traceSegmentHelper.traceSegment<BoxTraceSegmentReport>(centerLocalSpace, sweepDirLocalSpace, distance, &myReport);
+
+ return myReport.finalizeHit(sweepHit, hfGeom, pose, boxPose_, box, unitDir, distance, inflation);
+}
+
+///////////////////////////////////////////////////////////////////////////////