diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/GeomUtils/src/hf/GuOverlapTestsHF.cpp | |
| download | physx-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/GuOverlapTestsHF.cpp')
| -rw-r--r-- | PhysX_3.4/Source/GeomUtils/src/hf/GuOverlapTestsHF.cpp | 768 |
1 files changed, 768 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/hf/GuOverlapTestsHF.cpp b/PhysX_3.4/Source/GeomUtils/src/hf/GuOverlapTestsHF.cpp new file mode 100644 index 00000000..0fe55f18 --- /dev/null +++ b/PhysX_3.4/Source/GeomUtils/src/hf/GuOverlapTestsHF.cpp @@ -0,0 +1,768 @@ +// 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 "PsIntrinsics.h" +#include "PsAllocator.h" +#include "GuOverlapTests.h" + +#include "PsUtilities.h" +#include "PsVecMath.h" + +#include "GuHeightFieldUtil.h" +#include "GuIntersectionBoxBox.h" +#include "GuIntersectionTriangleBox.h" +#include "GuDistancePointSegment.h" +#include "GuDistanceSegmentBox.h" +#include "GuDistanceSegmentSegment.h" +#include "GuDistanceSegmentSegmentSIMD.h" + +#include "PxSphereGeometry.h" +#include "PxBoxGeometry.h" +#include "PxCapsuleGeometry.h" +#include "PxPlaneGeometry.h" +#include "PxConvexMeshGeometry.h" + +#include "GuCapsule.h" +#include "GuEdgeCache.h" +#include "GuBoxConversion.h" + +#include "GuInternal.h" +#include "GuConvexUtilsInternal.h" + +#include "GuVecTriangle.h" +#include "GuVecSphere.h" +#include "GuVecCapsule.h" +#include "GuVecConvexHull.h" +#include "GuConvexMesh.h" + +using namespace physx; +using namespace Cm; +using namespace Gu; +using namespace Ps::aos; + +static bool intersectHeightFieldSphere(const HeightFieldUtil& hfUtil, const Sphere& sphereInHfShape) +{ + const HeightField& hf = hfUtil.getHeightField(); + + // sample the sphere center in the heightfield to find out + // if we have penetration with more than the sphere radius + if(hfUtil.isShapePointOnHeightField(sphereInHfShape.center.x, sphereInHfShape.center.z)) + { + // The sphere origin projects within the bounds of the heightfield in the X-Z plane + PxReal sampleHeight = hfUtil.getHeightAtShapePoint(sphereInHfShape.center.x, sphereInHfShape.center.z); + PxReal deltaHeight = sphereInHfShape.center.y - sampleHeight; + if(hf.isDeltaHeightInsideExtent(deltaHeight)) + { + // The sphere origin is 'below' the heightfield surface + PxU32 faceIndex = hfUtil.getFaceIndexAtShapePoint(sphereInHfShape.center.x, sphereInHfShape.center.z); + if(faceIndex != 0xffffffff) + { + return true; + } + return false; + } + } + + const PxReal radiusSquared = sphereInHfShape.radius * sphereInHfShape.radius; + + const PxVec3 sphereInHF = hfUtil.shape2hfp(sphereInHfShape.center); + + const PxReal radiusOverRowScale = sphereInHfShape.radius * PxAbs(hfUtil.getOneOverRowScale()); + const PxReal radiusOverColumnScale = sphereInHfShape.radius * PxAbs(hfUtil.getOneOverColumnScale()); + + const PxU32 minRow = hf.getMinRow(sphereInHF.x - radiusOverRowScale); + const PxU32 maxRow = hf.getMaxRow(sphereInHF.x + radiusOverRowScale); + const PxU32 minColumn = hf.getMinColumn(sphereInHF.z - radiusOverColumnScale); + const PxU32 maxColumn = hf.getMaxColumn(sphereInHF.z + radiusOverColumnScale); + + for(PxU32 r = minRow; r < maxRow; r++) + { + for(PxU32 c = minColumn; c < maxColumn; c++) + { + + // x--x--x + // | x | + // x x x + // | x | + // x--x--x + PxVec3 pcp[11]; + PxU32 npcp = 0; + npcp = hfUtil.findClosestPointsOnCell(r, c, sphereInHfShape.center, pcp, NULL, true, true, true); + + for(PxU32 pi = 0; pi < npcp; pi++) + { + PxVec3 d = sphereInHfShape.center - pcp[pi]; + + PxReal ll = d.magnitudeSquared(); + + if(ll > radiusSquared) + // Too far + continue; + + return true; + } + } + } + return false; +} + +static bool intersectHeightFieldCapsule(const HeightFieldUtil& hfUtil, const PxCapsuleGeometry& capsuleGeom, const PxTransform& capsulePose) +{ + const HeightField& hf = hfUtil.getHeightField(); + + PxVec3 verticesInHfShape[2]; + PxVec3 capsuleOrigin, capsuleExtent; + { + const PxVec3 capsuleHalfHeightVector = getCapsuleHalfHeightVector(capsulePose, capsuleGeom); + + capsuleOrigin = capsulePose.p + capsuleHalfHeightVector; + capsuleExtent = -capsuleHalfHeightVector*2.0f; + + verticesInHfShape[0] = capsuleOrigin; + verticesInHfShape[1] = capsulePose.p - capsuleHalfHeightVector; + } + + const PxReal radius = capsuleGeom.radius; + const PxReal radiusOverRowScale = radius * PxAbs(hfUtil.getOneOverRowScale()); + const PxReal radiusOverColumnScale = radius * PxAbs(hfUtil.getOneOverColumnScale()); + + PxU32 absMinRow = 0xffffffff; + PxU32 absMaxRow = 0; + PxU32 absMinColumn = 0xffffffff; + PxU32 absMaxColumn = 0; + + PxReal radiusSquared = radius * radius; + + // test both of capsule's corner vertices+radius for HF overlap + for(PxU32 i = 0; i<2; i++) + { + const PxVec3& sphereInHfShape = verticesInHfShape[i]; + + // we have to do this first to update the absMin / absMax correctly even if + // we decide to continue from inside the deep penetration code. + + const PxVec3 sphereInHF = hfUtil.shape2hfp(sphereInHfShape); + + const PxU32 minRow = hf.getMinRow(sphereInHF.x - radiusOverRowScale); + const PxU32 maxRow = hf.getMaxRow(sphereInHF.x + radiusOverRowScale); + const PxU32 minColumn = hf.getMinColumn(sphereInHF.z - radiusOverColumnScale); + const PxU32 maxColumn = hf.getMaxColumn(sphereInHF.z + radiusOverColumnScale); + + if(minRow < absMinRow) absMinRow = minRow; + if(minColumn < absMinColumn) absMinColumn = minColumn; + if(maxRow > absMaxRow) absMaxRow = maxRow; + if(maxColumn > absMaxColumn) absMaxColumn = maxColumn; + + if(hfUtil.isShapePointOnHeightField(sphereInHfShape.x, sphereInHfShape.z)) + { + // The sphere origin projects within the bounds of the heightfield in the X-Z plane + const PxReal sampleHeight = hfUtil.getHeightAtShapePoint(sphereInHfShape.x, sphereInHfShape.z); + const PxReal deltaHeight = sphereInHfShape.y - sampleHeight; + if(hf.isDeltaHeightInsideExtent(deltaHeight)) + { + // The sphere origin is 'below' the heightfield surface + const PxU32 faceIndex = hfUtil.getFaceIndexAtShapePoint(sphereInHfShape.x, sphereInHfShape.z); + if(faceIndex != 0xffffffff) + { + return true; + } + continue; + } + } + + for(PxU32 r = minRow; r < maxRow; r++) + { + for(PxU32 c = minColumn; c < maxColumn; c++) + { + + // x--x--x + // | x | + // x x x + // | x | + // x--x--x + PxVec3 pcp[11]; + PxU32 npcp = 0; + npcp = hfUtil.findClosestPointsOnCell(r, c, sphereInHfShape, pcp, NULL, true, true, true); + + for(PxU32 pi = 0; pi < npcp; pi++) + { + const PxVec3 d = sphereInHfShape - pcp[pi]; + + if(hf.isDeltaHeightOppositeExtent(d.y)) + { + // We are 'above' the heightfield + + const PxReal ll = d.magnitudeSquared(); + if(ll > radiusSquared) + // Too far above + continue; + + return true; + } + } + } + } + } + + const Vec3V p1 = V3LoadU(capsuleOrigin); + const Vec3V d1 = V3LoadU(capsuleExtent); + + // now test capsule's inflated segment for overlap with HF edges + PxU32 row, column; + for(row = absMinRow; row <= absMaxRow; row++) + { + for(column = absMinColumn; column <= absMaxColumn; column++) + { + const PxU32 vertexIndex = row * hf.getNbColumnsFast() + column; + const PxU32 firstEdge = 3 * vertexIndex; + // omg I am sorry about this code but I can't find a simpler way: + // last column will only test edge 2 + // last row will only test edge 0 + // and most importantly last row and column will not go inside the for + const PxU32 minEi = (column == absMaxColumn) ? 2u : 0; + const PxU32 maxEi = (row == absMaxRow ) ? 1u : 3u; + for(PxU32 ei = minEi; ei < maxEi; ei++) + { + const PxU32 edgeIndex = firstEdge + ei; + + const PxU32 cell = vertexIndex; + PX_ASSERT(cell == edgeIndex / 3); + const PxU32 row_ = row; + PX_ASSERT(row_ == cell / hf.getNbColumnsFast()); + const PxU32 column_ = column; + PX_ASSERT(column_ == cell % hf.getNbColumnsFast()); + + const PxU32 faceIndex = hfUtil.getEdgeFaceIndex(edgeIndex, cell, row_, column_); + if(faceIndex != 0xffffffff) + { + PxVec3 origin; + PxVec3 direction; + hfUtil.getEdge(edgeIndex, cell, row_, column_, origin, direction); + + const Vec3V p2 = V3LoadU(origin); + const Vec3V d2 = V3LoadU(direction); + FloatV s, t; + const FloatV llV = Gu::distanceSegmentSegmentSquared(p1, d1, p2, d2, s, t); + + PxReal ll; + FStore(llV, &ll); + + if(ll < radiusSquared) + return true; + } + } + } + } + return false; +} + +namespace physx +{ +namespace Gu +{ + const PxReal signs[24] = + { + -1,-1,-1, + -1,-1, 1, + -1, 1,-1, + -1, 1, 1, + 1,-1,-1, + 1,-1, 1, + 1, 1,-1, + 1, 1, 1, + }; + + const char edges[24] = + { + 0,1, + 1,3, + 3,2, + 2,0, + 4,5, + 5,7, + 7,6, + 6,4, + 0,4, + 1,5, + 2,6, + 3,7, + }; + + struct TriggerTraceSegmentCallback + { + bool intersection; + + PX_INLINE TriggerTraceSegmentCallback() : intersection(false) + { + } + + PX_INLINE bool underFaceHit( + const HeightFieldUtil&, const PxVec3&, + const PxVec3&, PxF32, PxF32, PxF32, PxU32) + { + return true; + } + + PX_INLINE bool faceHit(const HeightFieldUtil&, const PxVec3&, PxU32, PxReal, PxReal) + { + intersection = true; + return false; + } + bool onEvent(PxU32 , PxU32* ) + { + return true; + } + }; + + + class OverlapHeightfieldTraceSegmentHelper + { + PX_NOCOPY(OverlapHeightfieldTraceSegmentHelper) + public: + OverlapHeightfieldTraceSegmentHelper(const HeightFieldUtil& hfUtil) + : mHfUtil(hfUtil) + { + mHfUtil.computeLocalBounds(mLocalBounds); + } + + PX_INLINE void traceSegment(const PxVec3& aP0, const PxVec3& aP1, TriggerTraceSegmentCallback* aCallback) const + { + mHfUtil.traceSegment<TriggerTraceSegmentCallback, false, false>(aP0, aP1 - aP0, 1.0f, aCallback, mLocalBounds, false, NULL); + } + + private: + const HeightFieldUtil& mHfUtil; + PxBounds3 mLocalBounds; + }; + +} // namespace +} + +static bool intersectHeightFieldBox(const HeightFieldUtil& hfUtil, const Box& boxInHfShape) +{ + const HeightField& hf = hfUtil.getHeightField(); + + // Get box vertices + PxVec3 boxVertices[8]; + for(PxU32 i=0; i<8; i++) + boxVertices[i] = PxVec3(boxInHfShape.extents.x*signs[3*i], boxInHfShape.extents.y*signs[3*i+1], boxInHfShape.extents.z*signs[3*i+2]); + + // Transform box vertices to HeightFieldShape space + PxVec3 boxVerticesInHfShape[8]; + for(PxU32 i=0; i<8; i++) + boxVerticesInHfShape[i] = boxInHfShape.transform(boxVertices[i]); + + // Test box vertices. + { + for(PxU32 i=0; i<8; i++) + { + const PxVec3& boxVertexInHfShape = boxVerticesInHfShape[i]; + if(hfUtil.isShapePointOnHeightField(boxVertexInHfShape.x, boxVertexInHfShape.z)) + { + const PxReal y = hfUtil.getHeightAtShapePoint(boxVertexInHfShape.x, boxVertexInHfShape.z); + const PxReal dy = boxVertexInHfShape.y - y; + if(hf.isDeltaHeightInsideExtent(dy)) + { + PxU32 faceIndex = hfUtil.getFaceIndexAtShapePoint(boxVertexInHfShape.x, boxVertexInHfShape.z); + if(faceIndex != 0xffffffff) + { + return true; + } + } + } + } + } + + // Test box edges. + { + OverlapHeightfieldTraceSegmentHelper traceSegmentHelper(hfUtil); + + for(PxU32 i=0; i<12; i++) + { + const PxVec3 v0 = boxVerticesInHfShape[PxU8(edges[2*i])]; + const PxVec3 v1 = boxVerticesInHfShape[PxU8(edges[2*i+1])]; + TriggerTraceSegmentCallback cb; + traceSegmentHelper.traceSegment(v0, v1, &cb); + if(cb.intersection) + return true; + } + } + + // Test HeightField vertices. + { + PsTransformV _hfShape2BoxShape; + const PxQuat bq(boxInHfShape.rot); + const QuatV q1 = QuatVLoadU(&bq.x); + const Vec3V p1 = V3LoadU(&boxInHfShape.center.x); + const PsTransformV _boxPose(p1, q1); + _hfShape2BoxShape = _boxPose.getInverse(); + + PxReal minx(PX_MAX_REAL); + PxReal minz(PX_MAX_REAL); + PxReal maxx(-PX_MAX_REAL); + PxReal maxz(-PX_MAX_REAL); + + for(PxU32 i=0; i<8; i++) + { + const PxVec3& boxVertexInHfShape = boxVerticesInHfShape[i]; + +/* if(boxVertexInHfShape.x < minx) minx = boxVertexInHfShape.x; + if(boxVertexInHfShape.z < minz) minz = boxVertexInHfShape.z; + if(boxVertexInHfShape.x > maxx) maxx = boxVertexInHfShape.x; + if(boxVertexInHfShape.z > maxz) maxz = boxVertexInHfShape.z;*/ + minx = physx::intrinsics::selectMin(boxVertexInHfShape.x, minx); + minz = physx::intrinsics::selectMin(boxVertexInHfShape.z, minz); + maxx = physx::intrinsics::selectMax(boxVertexInHfShape.x, maxx); + maxz = physx::intrinsics::selectMax(boxVertexInHfShape.z, maxz); + } + + const PxReal oneOverRowScale = hfUtil.getOneOverRowScale(); + const PxReal oneOverColumnScale = hfUtil.getOneOverColumnScale(); + const PxU32 minRow = hf.getMinRow(minx * oneOverRowScale); + const PxU32 maxRow = hf.getMaxRow(maxx * oneOverRowScale); + const PxU32 minColumn = hf.getMinColumn(minz * oneOverColumnScale); + const PxU32 maxColumn = hf.getMaxColumn(maxz * oneOverColumnScale); + + const Vec4V extentV = V4LoadXYZW(boxInHfShape.extents.x, boxInHfShape.extents.y, boxInHfShape.extents.z, PX_MAX_REAL); + const PxHeightFieldGeometry& geom = hfUtil.getHeightFieldGeometry(); + + for(PxU32 row = minRow; row <= maxRow; row++) + { + for(PxU32 column = minColumn; column <= maxColumn; column++) + { + PxU32 vertexIndex = row * hf.getNbColumnsFast() + column; + if(hfUtil.isQueryVertex(vertexIndex, row, column)) + { + // check if hf vertex is inside the box + const Vec4V hfVertex = V4LoadXYZW(geom.rowScale * row, geom.heightScale * hf.getHeight(vertexIndex), geom.columnScale * column, 0.0f); + const Vec4V hfVertexInBoxShape = Vec4V_From_Vec3V(_hfShape2BoxShape.transform(Vec3V_From_Vec4V(hfVertex))); + const Vec4V hfVertexInBoxShapeAbs = V4Abs(hfVertexInBoxShape); + + if(V4AllGrtr(extentV, hfVertexInBoxShapeAbs)) + { + return true; + } + } + } + } + } + return false; +} + +static Matrix34 multiplyInverseRTLeft(const Matrix34& left, const Matrix34& right) +{ +// t = left.M % (right.t - left.t); + PxVec3 t = left.rotateTranspose(right.p - left.p); + +// M.setMultiplyTransposeLeft(left.M, right.M); + const PxMat33& left33 = left.m; + const PxMat33& right33 = right.m; + PxMat33 multiplyTransposeLeft33 = (left33.getTranspose()) * right33; + + return Matrix34(multiplyTransposeLeft33, t); +} + +static bool intersectHeightFieldConvex( + const HeightFieldUtil& hfUtil, const PxTransform& _hfAbsPose, const ConvexMesh& convexMesh, + const PxTransform& _convexAbsPose, const PxMeshScale& convexMeshScaling) +{ + const Matrix34 hfAbsPose34(_hfAbsPose); + const Matrix34 convexAbsPose34(_convexAbsPose); + const Matrix34 vertexToShapeSkew34(convexMeshScaling.toMat33()); + const Matrix34 temp34 = convexAbsPose34 * vertexToShapeSkew34; + const Matrix34 convexShape2HfShapeSkew34 = multiplyInverseRTLeft(hfAbsPose34, temp34); + + const ConvexHullData* hull = &convexMesh.getHull(); + + // Allocate space for transformed vertices. + PxVec3* convexVerticesInHfShape = reinterpret_cast<PxVec3*>(PxAlloca(hull->mNbHullVertices*sizeof(PxVec3))); + + // Transform vertices to height field shape + const PxVec3* hullVerts = hull->getHullVertices(); + for(PxU32 i=0; i<hull->mNbHullVertices; i++) + convexVerticesInHfShape[i] = convexShape2HfShapeSkew34.transform(hullVerts[i]); + + // Compute bounds of convex in hf space + PxBounds3 convexBoundsInHfShape; + computeBoundsAroundVertices(convexBoundsInHfShape, hull->mNbHullVertices, convexVerticesInHfShape); + + // Compute the height field extreme over the bounds area. + const HeightField& hf = hfUtil.getHeightField(); + PxReal hfExtreme = (hf.getThicknessFast() <= 0) ? -PX_MAX_REAL : PX_MAX_REAL; + const PxReal oneOverRowScale = hfUtil.getOneOverRowScale(); + const PxReal oneOverColumnScale = hfUtil.getOneOverColumnScale(); + const PxReal rowScale = (1.0f / hfUtil.getOneOverRowScale()); + const PxReal columnScale = (1.0f / hfUtil.getOneOverColumnScale()); + const PxReal heightScale = (1.0f / hfUtil.getOneOverHeightScale()); + + // negative scale support + PxU32 minRow; + PxU32 maxRow; + if(oneOverRowScale > 0.0f) + { + minRow = hf.getMinRow(convexBoundsInHfShape.minimum.x * oneOverRowScale); + maxRow = hf.getMaxRow(convexBoundsInHfShape.maximum.x * oneOverRowScale); + } + else + { + minRow = hf.getMinRow(convexBoundsInHfShape.maximum.x * oneOverRowScale); + maxRow = hf.getMaxRow(convexBoundsInHfShape.minimum.x * oneOverRowScale); + } + + PxU32 minColumn; + PxU32 maxColumn; + if(oneOverColumnScale > 0.0f) + { + minColumn = hf.getMinColumn(convexBoundsInHfShape.minimum.z * oneOverColumnScale); + maxColumn = hf.getMaxColumn(convexBoundsInHfShape.maximum.z * oneOverColumnScale); + } + else + { + minColumn = hf.getMinColumn(convexBoundsInHfShape.maximum.z * oneOverColumnScale); + maxColumn = hf.getMaxColumn(convexBoundsInHfShape.minimum.z * oneOverColumnScale); + } + + for(PxU32 row = minRow; row <= maxRow; row++) + { + for(PxU32 column = minColumn; column <= maxColumn; column++) + { + const PxReal h = hf.getHeight(row * hf.getNbColumnsFast() + column); + hfExtreme = (hf.getThicknessFast() <= 0) ? PxMax(hfExtreme, h) : PxMin(hfExtreme, h); + } + } + hfExtreme *= heightScale; + + + // Return if convex is on the wrong side of the extreme. + if(hf.getThicknessFast() <= 0) + { + if(convexBoundsInHfShape.minimum.y > hfExtreme) + return false; + } + else + { + if(convexBoundsInHfShape.maximum.y < hfExtreme) + return false; + } + + + // Test convex vertices + { + for(PxU32 i=0; i<hull->mNbHullVertices; i++) + { + const PxVec3& convexVertexInHfShape = convexVerticesInHfShape[i]; + bool insideExtreme = (hf.getThicknessFast() <= 0) ? (convexVertexInHfShape.y < hfExtreme) : (convexVertexInHfShape.y > hfExtreme); + if(insideExtreme && hfUtil.isShapePointOnHeightField(convexVertexInHfShape.x, convexVertexInHfShape.z)) + { + const PxReal y = hfUtil.getHeightAtShapePoint(convexVertexInHfShape.x, convexVertexInHfShape.z); + const PxReal dy = convexVertexInHfShape.y - y; + if(hf.isDeltaHeightInsideExtent(dy)) + { + const PxU32 faceIndex = hfUtil.getFaceIndexAtShapePoint(convexVertexInHfShape.x, convexVertexInHfShape.z); + if(faceIndex != 0xffffffff) + return true; + } + } + } + } + + // Test convex edges. + { + EdgeCache edgeCache; + PxU32 numPolygons = hull->mNbPolygons; + const HullPolygonData* polygons = hull->mPolygons; + const PxU8* const vertexData = hull->getVertexData8(); + + OverlapHeightfieldTraceSegmentHelper traceSegmentHelper(hfUtil); + + while(numPolygons--) + { + const HullPolygonData& polygon = *polygons++; + + const PxU8* verts = vertexData + polygon.mVRef8; + + PxU32 numEdges = polygon.mNbVerts; + + PxU32 a = numEdges - 1; + PxU32 b = 0; + while(numEdges--) + { + PxU8 vi0 = verts[a]; + PxU8 vi1 = verts[b]; + + if(vi1 < vi0) + { + PxU8 tmp = vi0; + vi0 = vi1; + vi1 = tmp; + } + + if(edgeCache.isInCache(vi0, vi1)) //avoid processing edges 2x if possible (this will typically have cache misses about 5% of the time leading to 5% redundant work. + continue; + + const PxVec3& sv0 = convexVerticesInHfShape[vi0]; + const PxVec3& sv1 = convexVerticesInHfShape[vi1]; + a = b; + b++; + + + if(hf.getThicknessFast() <= 0) + { + if((sv0.y > hfExtreme) && (sv1.y > hfExtreme)) + continue; + } + else + { + if((sv0.y < hfExtreme) && (sv1.y < hfExtreme)) + continue; + } + const PxVec3 v0 = sv0; + const PxVec3 v1 = sv1; + TriggerTraceSegmentCallback cb; + traceSegmentHelper.traceSegment(v0, v1, &cb); + if(cb.intersection) + return true; + } + } + } + + // Test HeightField vertices + { + const Matrix34 tmp34 = multiplyInverseRTLeft(convexAbsPose34, hfAbsPose34); + const Matrix34 hfShape2ConvexShapeSkew34 = vertexToShapeSkew34 * tmp34; + + for(PxU32 row = minRow; row <= maxRow; row++) + { + for(PxU32 column = minColumn; column <= maxColumn; column++) + { + const PxU32 hfVertexIndex = row * hf.getNbColumnsFast() + column; + if(hfUtil.isQueryVertex(hfVertexIndex, row, column)) + { + // Check if hf vertex is inside the convex + const PxVec3 hfVertex(rowScale * row, heightScale * hf.getHeight(hfVertexIndex), columnScale * column); + const PxVec3 hfVertexInConvexShape = hfShape2ConvexShapeSkew34.transform(hfVertex); + + bool inside = true; + for(PxU32 poly = 0; poly < hull->mNbPolygons; poly++) + { + PxReal d = hull->mPolygons[poly].mPlane.distance(hfVertexInConvexShape); + if(d >= 0) + { + inside = false; + break; + } + } + if(inside) + return true; + } + } + } + } + return false; +} + +bool Gu::checkOverlapAABB_heightFieldGeom(const PxGeometry& geom, const PxTransform& pose, const PxBounds3& box) +{ + PX_ASSERT(geom.getType() == PxGeometryType::eHEIGHTFIELD); + const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom); + + const Matrix34 invAbsPose(pose.getInverse()); + + const Box boxInHfShape( + invAbsPose.transform(box.getCenter()), + box.getExtents(), + invAbsPose.m); + + HeightFieldUtil hfUtil(hfGeom); + return intersectHeightFieldBox(hfUtil, boxInHfShape); +} + +bool GeomOverlapCallback_SphereHeightfield(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eSPHERE); + PX_ASSERT(geom1.getType()==PxGeometryType::eHEIGHTFIELD); + PX_UNUSED(cache); + + const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom0); + const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom1); + + const Sphere sphereInHf(pose1.transformInv(pose0.p), sphereGeom.radius); + + HeightFieldUtil hfUtil(hfGeom); + return intersectHeightFieldSphere(hfUtil, sphereInHf); +} + +bool GeomOverlapCallback_CapsuleHeightfield(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eCAPSULE); + PX_ASSERT(geom1.getType()==PxGeometryType::eHEIGHTFIELD); + PX_UNUSED(cache); + + const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom0); + const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom1); + + const PxTransform capsuleShapeToHfShape = pose1.transformInv(pose0); + + const HeightFieldUtil hfUtil(hfGeom); + return intersectHeightFieldCapsule(hfUtil, capsuleGeom, capsuleShapeToHfShape); +} + +bool GeomOverlapCallback_BoxHeightfield(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eBOX); + PX_ASSERT(geom1.getType()==PxGeometryType::eHEIGHTFIELD); + PX_UNUSED(cache); + + const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom0); + const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom1); + + const PxTransform boxShape2HfShape = pose1.transformInv(pose0); + + Box box; + buildFrom(box, boxShape2HfShape.p, boxGeom.halfExtents, boxShape2HfShape.q); + + HeightFieldUtil hfUtil(hfGeom); + return intersectHeightFieldBox(hfUtil, box); +} + +/////////////////////////////////////////////////////////////////////////////// +bool GeomOverlapCallback_ConvexHeightfield(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eCONVEXMESH); + PX_ASSERT(geom1.getType()==PxGeometryType::eHEIGHTFIELD); + PX_UNUSED(cache); + + const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom0); + const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom1); + + ConvexMesh* cm = static_cast<ConvexMesh*>(convexGeom.convexMesh); + + HeightFieldUtil hfUtil(hfGeom); + return intersectHeightFieldConvex(hfUtil, pose1, *cm, pose0, convexGeom.scale); +} |