71 PxReal mOneOverRowScale;
72 PxReal mOneOverHeightScale;
73 PxReal mOneOverColumnScale;
84 PX_ASSERT(mHfGeom->
heightScale >= PX_MIN_HEIGHTFIELD_Y_SCALE);
85 PX_ASSERT(absRowScale >= PX_MIN_HEIGHTFIELD_XZ_SCALE);
86 PX_ASSERT(absColScale >= PX_MIN_HEIGHTFIELD_XZ_SCALE);
87 PX_UNUSED(absRowScale);
88 PX_UNUSED(absColScale);
92 mOneOverRowScale = 1.0f / mHfGeom->
rowScale;
99 PX_FORCE_INLINE PxReal getOneOverRowScale()
const {
return mOneOverRowScale; }
100 PX_FORCE_INLINE PxReal getOneOverHeightScale()
const {
return mOneOverHeightScale; }
101 PX_FORCE_INLINE PxReal getOneOverColumnScale()
const {
return mOneOverColumnScale; }
103 void computeLocalBounds(
PxBounds3& bounds)
const;
107 return mHfGeom->
heightScale * mHeightField->getHeightInternal(x * mOneOverRowScale, z * mOneOverColumnScale);
112 return mHeightField->getNormal_(x * mOneOverRowScale, z * mOneOverColumnScale, mOneOverRowScale, mOneOverHeightScale, mOneOverColumnScale);
115 PxU32 getTriangle(
const PxTransform&,
PxTriangle& worldTri, PxU32* vertexIndices, PxU32* adjacencyIndices, PxTriangleID triangleIndex,
bool worldSpaceTranslation=
true,
bool worldSpaceRotation=
true)
const;
117 void overlapAABBTriangles(
const PxBounds3& localBounds,
OverlapReport& callback, PxU32 batchSize=HF_OVERLAP_REPORT_BUFFER_SIZE)
const;
132 overlapAABBTriangles(b, callback, batchSize);
138 overlapAABBTriangles0to1(pose1.getInverse(), bounds0, callback, batchSize);
143 overlapAABBTriangles0to1(pose1.transformInv(pose0), bounds0, callback, batchSize);
148 return PxVec3(v.x * mOneOverRowScale, v.y * mOneOverHeightScale, v.z * mOneOverColumnScale);
153 return PxVec3(v.x * mOneOverRowScale, v.y * mOneOverHeightScale, v.z * mOneOverColumnScale);
163 const PxVec3 s = hf2shapep(v);
164 return pose.transform(s);
169 const PxVec3 s = hf2shapen(v);
180 static PX_FORCE_INLINE PxF32 floorDown(PxF32 x) { PxF32 f = PxFloor(x);
return (f == x) ? f-1 : f; }
181 static PX_FORCE_INLINE PxF32 ceilUp (PxF32 x) { PxF32 f = PxCeil (x);
return (f == x) ? f+1 : f; }
224 : mInitialized(false), mHfUtil(hfUtil), mHf(hf), mNbIndices(0) {}
232 mMinY = (
PxMin(aP1.y,aP0.y) - overlapObjectExtent.y) * mHfUtil.getOneOverHeightScale();
233 mMaxY = (
PxMax(aP1.y,aP0.y) + overlapObjectExtent.y) * mHfUtil.getOneOverHeightScale();
236 mMinRow = PxI32(mHf.getMinRow((
PxMin(aP1.x,aP0.x) - overlapObjectExtent.x)* mHfUtil.getOneOverRowScale()));
237 mMaxRow = PxI32(mHf.getMaxRow((
PxMax(aP1.x,aP0.x) + overlapObjectExtent.x)* mHfUtil.getOneOverRowScale()));
238 mMinColumn = PxI32(mHf.getMinColumn((
PxMin(aP1.z,aP0.z) - overlapObjectExtent.z)* mHfUtil.getOneOverColumnScale()));
239 mMaxColumn = PxI32(mHf.getMaxColumn((
PxMax(aP1.z,aP0.z) + overlapObjectExtent.z)* mHfUtil.getOneOverColumnScale()));
242 expandu = PxCeil(overlapObjectExtent.x*mHfUtil.getOneOverRowScale());
243 expandv = PxCeil(overlapObjectExtent.z*mHfUtil.getOneOverColumnScale());
246 mOffsetU = PxI32(expandu) + 1;
247 mOffsetV = PxI32(expandv) + 1;
251 PX_INLINE bool init(
const PxI32 ui,
const PxI32 vi,
const PxI32 nbVi,
const PxI32 step_ui,
const PxI32 step_vi, T* aCallback)
254 mCallback = aCallback;
256 mStep_ui = step_ui > 0 ? 0 : -1;
257 mStep_vi = step_vi > 0 ? 0 : -1;
260 mCurrentRectangle.invalidate();
261 mPreviousRectangle.mMinu = ui - mOffsetU;
262 mPreviousRectangle.mMaxu = ui + mOffsetU;
263 mPreviousRectangle.mMinv = vi - mOffsetV;
264 mPreviousRectangle.mMaxv = vi + mOffsetV;
267 if(!visitCells(mPreviousRectangle))
271 if(!reportOverlaps())
279 PX_INLINE bool step(
const PxI32 ui,
const PxI32 vi)
281 mCurrentRectangle.mMinu = ui - mOffsetU;
282 mCurrentRectangle.mMaxu = ui + mOffsetU;
283 mCurrentRectangle.mMinv = vi - mOffsetV;
284 mCurrentRectangle.mMaxv = vi + mOffsetV;
286 computeRectangleDifference(mCurrentRectangle,mPreviousRectangle,line);
288 if(!visitCells(line))
290 if(!reportOverlaps())
293 mPreviousRectangle = mCurrentRectangle;
297 PX_INLINE void computeRectangleDifference(
const OverlapRectangle& currentRectangle,
const OverlapRectangle& previousRectangle, OverlapLine& line)
300 if(currentRectangle.mMinu != previousRectangle.mMinu)
302 line.mColumn =
false;
303 line.mLine = currentRectangle.mMinu < previousRectangle.mMinu ? currentRectangle.mMinu : currentRectangle.mMaxu;
304 line.mMin = currentRectangle.mMinv;
305 line.mMax = currentRectangle.mMaxv;
310 if(currentRectangle.mMinv != previousRectangle.mMinv)
313 line.mLine = currentRectangle.mMinv < previousRectangle.mMinv ? currentRectangle.mMinv : currentRectangle.mMaxv;
314 line.mMin = currentRectangle.mMinu;
315 line.mMax = currentRectangle.mMaxu;
320 PX_INLINE bool visitCells(
const OverlapRectangle& rectangle)
322 for(PxI32 ui = rectangle.mMinu + mStep_ui; ui <= rectangle.mMaxu + mStep_ui; ui++)
328 for(PxI32 vi = rectangle.mMinv + mStep_vi; vi <= rectangle.mMaxv + mStep_vi; vi++)
334 const PxI32 vertexIndex = ui*mNumColumns + vi;
335 if(!testVertexIndex(PxU32(vertexIndex)))
343 PX_INLINE bool visitCells(
const OverlapLine& line)
345 if(line.mMin > line.mMax)
350 const PxI32 vi = line.mLine + mStep_vi;
357 for(PxI32 ui = line.mMin + mStep_ui; ui <= line.mMax + mStep_ui; ui++)
366 if(!testVertexIndex(PxU32(mNumColumns * ui + vi)))
372 const PxI32 ui = line.mLine + mStep_ui;
379 for(PxI32 vi = line.mMin + mStep_vi; vi <= line.mMax + mStep_vi; vi++)
388 if(!testVertexIndex(PxU32(mNumColumns * ui + vi)))
396 PX_INLINE bool testVertexIndex(
const PxU32 vertexIndex)
398 const PxReal h0 = mHf.getHeight(vertexIndex);
399 const PxReal h1 = mHf.getHeight(vertexIndex + 1);
400 const PxReal h2 = mHf.getHeight(vertexIndex + mNumColumns);
401 const PxReal h3 = mHf.getHeight(vertexIndex + mNumColumns + 1);
403 if(!((mMaxY < h0 && mMaxY < h1 && mMaxY < h2 && mMaxY < h3) || (mMinY > h0 && mMinY > h1 && mMinY > h2 && mMinY > h3)))
406 if(mHf.getMaterialIndex0(vertexIndex) != PxHeightFieldMaterial::eHOLE)
408 if(!addIndex(vertexIndex*2))
411 if(mHf.getMaterialIndex1(vertexIndex) != PxHeightFieldMaterial::eHOLE)
413 if(!addIndex(vertexIndex*2 + 1))
421 bool addIndex(PxU32 triangleIndex)
423 if(mNbIndices == HF_SWEEP_REPORT_BUFFER_SIZE)
425 if(!reportOverlaps())
429 mIndexBuffer[mNbIndices++] = triangleIndex;
437 if(!mCallback->onEvent(mNbIndices, mIndexBuffer))
446 const HeightFieldUtil& mHfUtil;
447 const Gu::HeightField& mHf;
460 OverlapRectangle mPreviousRectangle;
461 OverlapRectangle mCurrentRectangle;
462 PxU32 mIndexBuffer[HF_SWEEP_REPORT_BUFFER_SIZE];
479 template<
class T,
bool useUnderFaceCallback,
bool overlap>
480 PX_INLINE void traceSegment(
const PxVec3& aP0,
const PxVec3& rayDir,
const float rayLength , T* aCallback,
const PxBounds3& hfLocalBounds,
bool backfaceCull,
481 const PxVec3* overlapObjectExtent = NULL)
const
484 if(!Gu::intersectRayAABB2(hfLocalBounds.minimum, hfLocalBounds.maximum, aP0, rayDir, rayLength, tnear, tfar))
487 const PxVec3 p0 = aP0 + rayDir * tnear;
488 const PxVec3 p1 = aP0 + rayDir * tfar;
491 OverlapTraceSegment<T> overlapTraceSegment(*
this, *mHeightField);
494 PxF32 expandu = 0.0f, expandv = 0.0f;
499 overlapTraceSegment.prepare(aP0,aP0 + rayDir*rayLength,*overlapObjectExtent,expandu,expandv);
503 const PxF32 rowScale = mHfGeom->rowScale, columnScale = mHfGeom->columnScale, heightScale = mHfGeom->heightScale;
504 const PxI32 nbVi = PxI32(mHeightField->getNbColumnsFast()), nbUi = PxI32(mHeightField->getNbRowsFast());
505 PX_ASSERT(nbVi > 0 && nbUi > 0);
508 const PxF32 clampEps = 1e-7f;
511 const PxF32 nbUcells = PxF32(nbUi-1)*(1.0f-clampEps), nbVcells = PxF32(nbVi-1)*(1.0f-clampEps);
520 const PxF32 uu0 = p0.x * mOneOverRowScale;
521 PxF32 u0 =
PxMin(
PxMax(uu0, 1e-7f - expandu), nbUcells + expandu);
522 const PxF32 uv0 = p0.z * mOneOverColumnScale;
523 PxF32 v0 =
PxMin(
PxMax(uv0, 1e-7f - expandv), nbVcells + expandv);
524 const PxReal h0 = p0.y;
528 const PxF32 uu1 = p1.x * mOneOverRowScale;
529 const PxF32 uv1 = p1.z * mOneOverColumnScale;
530 const PxReal h1 = p1.y;
532 PxF32 du = uu1 - uu0, dv = uv1 - uv0;
533 const PxReal dh = h1 - h0;
537 const PxF32 step_uif = PxSign(du), step_vif = PxSign(dv);
538 const PxI32 step_ui = PxI32(step_uif), step_vi = PxI32(step_vif);
541 const PxF32 divEpsilon = 1e-10f;
542 if(
PxAbs(du) < divEpsilon)
543 du = step_uif * divEpsilon;
544 if(
PxAbs(dv) < divEpsilon)
545 dv = step_vif * divEpsilon;
547 const PxVec3 auhP0(aP0.x*mOneOverRowScale, aP0.y, aP0.z*mOneOverColumnScale);
548 const PxVec3 duhv(rayDir.x*rayLength*mOneOverRowScale, rayDir.y*rayLength, rayDir.z*rayLength*mOneOverColumnScale);
549 const PxReal duhvLength = duhv.magnitude();
550 PxVec3 duhvNormalized = duhv;
551 if(duhvLength > PX_NORMALIZATION_EPSILON)
552 duhvNormalized *= 1.0f/duhvLength;
563 PxI32 ui = (du > 0.0f) ? PxI32(PxFloor(u0)) : PxI32(PxCeil(u0));
564 PxI32 vi = (dv > 0.0f) ? PxI32(PxFloor(v0)) : PxI32(PxCeil(v0));
567 const PxReal uhit0 = du > 0.0f ? ceilUp(u0) : floorDown(u0);
568 const PxReal vhit0 = dv > 0.0f ? ceilUp(v0) : floorDown(v0);
571 PxF32 last_tu = 0.0f, last_tv = 0.0f;
572 PxReal tu = (uhit0 - uu0) / du;
573 PxReal tv = (vhit0 - uv0) / dv;
575 tu =
PxAbs(clampEps / du);
577 tv =
PxAbs(clampEps / dv);
580 const PxReal step_tu = 1.0f /
PxAbs(du), step_tv = 1.0f /
PxAbs(dv);
583 #define COMPUTE_H_FROM_T(t) (h0 + (t) * dh)
585 const PxF32 hEpsilon = 1e-4f;
586 PxF32 uif = PxF32(ui), vif = PxF32(vi);
589 PxI32 uflip = 1-step_ui;
590 PxI32 vflip = (1-step_vi)/2;
594 PxF32 tEnd = 1.0f - 1e-4f;
599 const Gu::HeightField& hf = *mHeightField;
602 PxReal hLinePrev = COMPUTE_H_FROM_T(0);
606 tMinUV =
PxMin(tu, tv);
607 PxF32 hLineNext = COMPUTE_H_FROM_T(tMinUV);
610 PX_ASSERT(ui >= 0 - expandu && ui < nbUi + expandu && vi >= 0 - expandv && vi < nbVi + expandv);
611 PX_ASSERT(ui+step_ui >= 0 - expandu && ui+step_ui < nbUi + expandu && vi+step_vi >= 0 - expandv && vi+step_vi < nbVi + expandv);
616 if(!overlapTraceSegment.initialized())
619 if(!overlapTraceSegment.init(ui,vi,nbVi,step_ui,step_vi,aCallback))
625 if(!overlapTraceSegment.step(ui,vi))
631 const PxU32 colIndex0 = PxU32(nbVi * ui + vi);
632 const PxU32 colIndex1 = PxU32(nbVi * (ui + step_ui) + vi);
633 const PxReal h[4] = {
634 hf.getHeight(colIndex0) * heightScale, hf.getHeight(colIndex0 + step_vi) * heightScale,
635 hf.getHeight(colIndex1) * heightScale, hf.getHeight(colIndex1 + step_vi) * heightScale };
641 PxF32 hLineCellRangeMin =
PxMin(hLinePrev, hLineNext);
642 PxF32 hLineCellRangeMax =
PxMax(hLinePrev, hLineNext);
645 if(!(hLineCellRangeMin-hEpsilon > maxH || hLineCellRangeMax+hEpsilon < minH) ||
646 (useUnderFaceCallback && hLineCellRangeMax < maxH))
651 const PxF32 h00 = h[0+uflip+vflip];
652 const PxF32 h01 = h[1+uflip-vflip];
653 const PxF32 h10 = h[2-uflip+vflip];
654 const PxF32 h11 = h[3-uflip-vflip];
656 const PxF32 minuif =
PxMin(uif, uif+step_uif);
657 const PxF32 maxuif =
PxMax(uif, uif+step_uif);
658 const PxF32 minvif =
PxMin(vif, vif+step_vif);
659 const PxF32 maxvif =
PxMax(vif, vif+step_vif);
660 const PxVec3 p00(minuif, h00, minvif);
661 const PxVec3 p01(minuif, h01, maxvif);
662 const PxVec3 p10(maxuif, h10, minvif);
663 const PxVec3 p11(maxuif, h11, maxvif);
665 const PxF32 enlargeEpsilon = 0.0001f;
666 const PxVec3* p00a = &p00, *p01a = &p01, *p10a = &p10, *p11a = &p11;
667 PxU32 minui = PxU32(
PxMin(ui+step_ui, ui)), minvi = PxU32(
PxMin(vi+step_vi, vi));
670 const PxU32 vertIndex = nbVi * minui + minvi;
671 const PxU32 cellIndex = vertIndex;
672 bool isZVS = hf.isZerothVertexShared(vertIndex);
686 if(!useUnderFaceCallback)
688 PxReal triT0 = PX_MAX_REAL, triT1 = PX_MAX_REAL;
689 bool hit0 =
false, hit1 =
false;
690 PxF32 triU0, triV0, triU1, triV1;
693 if(Gu::intersectRayTriangle(auhP0, duhvNormalized, *p10a, *p00a, *p11a, triT0, triU0, triV0, backfaceCull, enlargeEpsilon) && triT0 >= 0.0f && triT0 <= duhvLength && (hf.getMaterialIndex0(vertIndex) != PxHeightFieldMaterial::eHOLE))
700 if(Gu::intersectRayTriangle(auhP0, duhvNormalized, *p01a, *p11a, *p00a, triT1, triU1, triV1, backfaceCull, enlargeEpsilon) && triT1 >= 0.0f && triT1 <= duhvLength && (hf.getMaterialIndex1(vertIndex) != PxHeightFieldMaterial::eHOLE))
707 if(hit0 && triT0 <= triT1)
709 const PxVec3 hitPoint((auhP0.x + duhvNormalized.x*triT0) * rowScale, auhP0.y + duhvNormalized.y * triT0, (auhP0.z + duhvNormalized.z*triT0) * columnScale);
710 if(!aCallback->faceHit(*
this, hitPoint, cellIndex*2, triU0, triV0))
714 PxVec3 hitPoint1((auhP0.x + duhvNormalized.x*triT1) * rowScale, auhP0.y + duhvNormalized.y * triT1, (auhP0.z + duhvNormalized.z*triT1) * columnScale);
715 if(!aCallback->faceHit(*
this, hitPoint1, cellIndex*2 + 1, triU1, triV1))
719 else if(hit1 && triT1 <= triT0)
721 PxVec3 hitPoint((auhP0.x + duhvNormalized.x*triT1) * rowScale, auhP0.y + duhvNormalized.y * triT1, (auhP0.z + duhvNormalized.z*triT1) * columnScale);
722 if(!aCallback->faceHit(*
this, hitPoint, cellIndex*2 + 1, triU1, triV1))
726 PxVec3 hitPoint1((auhP0.x + duhvNormalized.x*triT0) * rowScale, auhP0.y + duhvNormalized.y * triT0, (auhP0.z + duhvNormalized.z*triT0) * columnScale);
727 if(!aCallback->faceHit(*
this, hitPoint1, cellIndex*2, triU0, triV0))
736 const PxVec3 p00s(p00a->x * rowScale, p00a->y, p00a->z * columnScale);
737 const PxVec3 p01s(p01a->x * rowScale, p01a->y, p01a->z * columnScale);
738 const PxVec3 p10s(p10a->x * rowScale, p10a->y, p10a->z * columnScale);
739 const PxVec3 p11s(p11a->x * rowScale, p11a->y, p11a->z * columnScale);
741 PxVec3 triNormals[2] = { (p00s - p10s).
cross(p11s - p10s), (p11s - p01s).
cross(p00s-p01s) };
742 triNormals[0] *=
PxRecipSqrt(triNormals[0].magnitudeSquared());
743 triNormals[1] *=
PxRecipSqrt(triNormals[1].magnitudeSquared());
749 const PxF32 wnu = isZVS ? -1.0f : 1.0f, wnv = 1.0f;
750 const PxF32 wpu = uif + 0.5f * step_uif, wpv = vif + 0.5f * step_vif;
755 const PxF32 tNext =
PxMin(
PxMin(tu, tv), 1.0f), tPrev =
PxMax(last_tu, last_tv);
758 const PxF32 unext = u0 + tNext*du, vnext = v0 + tNext*dv;
759 const PxF32 uprev = u0 + tPrev*du, vprev = v0 + tPrev*dv;
761 const PxReal& h00_ = h[0], &h01_ = h[1], &h10_ = h[2];
766 const PxU32 dotPrevGtz = PxU32(((uprev - wpu) * wnu + (vprev - wpv) * wnv) > 0);
767 const PxU32 dotNextGtz = PxU32(((unext - wpu) * wnu + (vnext - wpv) * wnv) > 0);
768 const PxU32 triIndex0 = cellIndex*2 + dotPrevGtz;
769 const PxU32 triIndex1 = cellIndex*2 + dotNextGtz;
770 PxU32 isHole0 = PxU32(hf.getMaterialIndex0(vertIndex) == PxHeightFieldMaterial::eHOLE);
771 PxU32 isHole1 = PxU32(hf.getMaterialIndex1(vertIndex) == PxHeightFieldMaterial::eHOLE);
772 if(triIndex0 > triIndex1)
773 PxSwap<PxU32>(isHole0, isHole1);
777 if(last_tu > last_tv)
778 crossedEdge = PxVec3(0.0f, h01_-h00_, step_vif * columnScale);
780 crossedEdge = PxVec3(step_uif * rowScale, h10_-h00_, 0.0f);
782 if(!isHole0 && !aCallback->underFaceHit(*
this, triNormals[dotPrevGtz], crossedEdge,
783 uprev * rowScale, vprev * columnScale, COMPUTE_H_FROM_T(tPrev), triIndex0))
786 if(triIndex1 != triIndex0 && !isHole1)
792 const PxF32 denom = du*wnu + dv*wnv;
793 if(
PxAbs(denom) > 1e-6f)
795 const PxF32 tw = (wnu*(wpu-u0)+wnv*(wpv-v0)) / denom;
796 if(!aCallback->underFaceHit(*
this, triNormals[dotNextGtz], p10s-p01s,
797 (u0+tw*du) * rowScale, (v0+tw*dv) * columnScale, COMPUTE_H_FROM_T(tw), triIndex1))
810 if(ui+step_ui< (0 - expandu) || ui+step_ui>=(nbUi + expandu))
820 if(vi+step_vi< (0 - expandv) || vi+step_vi>=(nbVi + expandv))
825 hLinePrev = hLineNext;
829 while (tMinUV < tEnd);
830 #undef COMPUTE_H_FROM_T