diff options
Diffstat (limited to 'indra/newview/llvosurfacepatch.cpp')
-rw-r--r-- | indra/newview/llvosurfacepatch.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 968cc69d3a..e912a19f81 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -916,6 +916,87 @@ void LLVOSurfacePatch::getGeomSizesEast(const S32 stride, const S32 east_stride, } } +BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, BOOL pick_transparent, S32 *face_hitp, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) + +{ + + if (!lineSegmentBoundingBox(start, end)) + { + return FALSE; + } + + LLVector3 delta = end-start; + + LLVector3 pdelta = delta; + pdelta.mV[2] = 0; + + F32 plength = pdelta.length(); + + F32 tdelta = 1.f/plength; + + LLVector3 origin = start - mRegionp->getOriginAgent(); + + if (mRegionp->getLandHeightRegion(origin) > origin.mV[2]) + { + //origin is under ground, treat as no intersection + return FALSE; + } + + //step one meter at a time until intersection point found + + F32 t = 0.f; + while ( t <= 1.f) + { + LLVector3 sample = origin + delta*t; + + F32 height = mRegionp->getLandHeightRegion(sample); + if (height > sample.mV[2]) + { //ray went below ground, positive intersection + //quick and dirty binary search to get impact point + tdelta = -tdelta*0.5f; + F32 err_dist = 0.001f; + F32 dist = fabsf(sample.mV[2] - height); + + while (dist > err_dist && tdelta*tdelta > 0.0f) + { + t += tdelta; + sample = origin+delta*t; + height = mRegionp->getLandHeightRegion(sample); + if ((tdelta < 0 && height < sample.mV[2]) || + (height > sample.mV[2] && tdelta > 0)) + { //jumped over intersection point, go back + tdelta = -tdelta; + } + tdelta *= 0.5f; + dist = fabsf(sample.mV[2] - height); + } + + if (intersection) + { + sample.mV[2] = mRegionp->getLandHeightRegion(sample); + *intersection = sample + mRegionp->getOriginAgent(); + } + + if (normal) + { + *normal = mRegionp->getLand().resolveNormalGlobal(mRegionp->getPosGlobalFromRegion(sample)); + } + + return TRUE; + } + + t += tdelta; + if (t > 1 && t < 1.f+tdelta*0.99f) + { //make sure end point is checked (saves vertical lines coming up negative) + t = 1.f; + } + } + + + return FALSE; +} + void LLVOSurfacePatch::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax) { LLVector3 posAgent = getPositionAgent(); |