From 14a8dd451e127c9ec86f7a871e4501d2d1f39606 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 24 Sep 2022 19:00:06 +0200 Subject: [PATCH] - redid lintersect with backend utilities. I left out EDuke32's new handling for collinear traces because it not only was never active but also makes really no sense with neartag which is lintersect's only caller. --- source/build/src/engine.cpp | 83 ------------------------------------- source/core/gamefuncs.h | 28 +++++++++++++ 2 files changed, 28 insertions(+), 83 deletions(-) diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index a5e51fddb..548616457 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -59,89 +59,6 @@ void engineInit(void) } -// -// lintersect (internal) -// -int32_t lintersect(const int32_t originX, const int32_t originY, const int32_t originZ, - const int32_t destX, const int32_t destY, const int32_t destZ, - const int32_t lineStartX, const int32_t lineStartY, const int32_t lineEndX, const int32_t lineEndY, - int32_t *intersectionX, int32_t *intersectionY, int32_t *intersectionZ) -{ - const vec2_t ray = { destX-originX, - destY-originY }; - const vec2_t lineVec = { lineEndX-lineStartX, - lineEndY-lineStartY }; - const vec2_t originDiff = { lineStartX-originX, - lineStartY-originY }; - - const int32_t rayCrossLineVec = ray.X*lineVec.Y - ray.Y*lineVec.X; - const int32_t originDiffCrossRay = originDiff.X*ray.Y - originDiff.Y*ray.X; - - if (rayCrossLineVec == 0) - { - if (originDiffCrossRay != 0 || enginecompatibility_mode != ENGINECOMPATIBILITY_NONE) - { - // line segments are parallel - return 0; - } - - // line segments are collinear - const int32_t rayLengthSquared = ray.X*ray.X + ray.Y*ray.Y; - const int32_t rayDotOriginDiff = ray.X*originDiff.X + ray.Y*originDiff.Y; - const int32_t rayDotLineEndDiff = rayDotOriginDiff + ray.X*lineVec.X + ray.Y*lineVec.Y; - int64_t t = min(rayDotOriginDiff, rayDotLineEndDiff); - if (rayDotOriginDiff < 0) - { - if (rayDotLineEndDiff < 0) - return 0; - - t = 0; - } - else if (rayDotOriginDiff > rayLengthSquared) - { - if (rayDotLineEndDiff > rayLengthSquared) - return 0; - - t = rayDotLineEndDiff; - } - t = (t << 24) / rayLengthSquared; - - *intersectionX = originX + MulScale(ray.X, t, 24); - *intersectionY = originY + MulScale(ray.Y, t, 24); - *intersectionZ = originZ + MulScale(destZ-originZ, t, 24); - - return 1; - } - - const int32_t originDiffCrossLineVec = originDiff.X*lineVec.Y - originDiff.Y*lineVec.X; - static const int32_t signBit = 1u<<31u; - // Any point on either line can be expressed as p+t*r and q+u*s - // The two line segments intersect when we can find a t & u such that p+t*r = q+u*s - // If the point is outside of the bounds of the line segment, we know we don't have an intersection. - // t is < 0 if (originDiffCrossLineVec^rayCrossLineVec) & signBit) - // u is < 0 if (originDiffCrossRay^rayCrossLineVec) & signBit - // t is > 1 if abs(originDiffCrossLineVec) > abs(rayCrossLineVec) - // u is > 1 if abs(originDiffCrossRay) > abs(rayCrossLineVec) - // where int32_t u = tabledivide64(((int64_t) originDiffCrossRay) << 24L, rayCrossLineVec); - if (((originDiffCrossLineVec^rayCrossLineVec) & signBit) || - ((originDiffCrossRay^rayCrossLineVec) & signBit) || - abs(originDiffCrossLineVec) > abs(rayCrossLineVec) || - abs(originDiffCrossRay) > abs(rayCrossLineVec)) - { - // line segments do not overlap - return 0; - } - - int64_t t = (int64_t(originDiffCrossLineVec) << 24) / rayCrossLineVec; - // For sake of completeness/readability, alternative to the above approach for an early out & avoidance of an extra division: - - *intersectionX = originX + MulScale(ray.X, t, 24); - *intersectionY = originY + MulScale(ray.Y, t, 24); - *intersectionZ = originZ + MulScale(destZ-originZ, t, 24); - - return 1; -} - // // cansee // diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index 8952a323c..e428a8cf2 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -574,6 +574,14 @@ inline double GetRayIntersect(const DVector3& start1, const DVector3& vect1, con return factor2; } +inline bool GetLineIntersect(const DVector3& start1, const DVector3& vect1, const DVector2& start2, const DVector2& vect2, DVector3& retv) +{ + double factor = InterceptLineSegments(start1.X, start1.Y, vect1.X, vect1.Y, start2.X, start2.Y, vect2.X, vect2.Y); + if (factor <= 0 || factor > 1) return false; + retv = start1 + (factor) * vect1; + return true; +} + inline void alignceilslope(sectortype* sect, const DVector3& pos) { @@ -639,5 +647,25 @@ inline int rintersect(int x1, int y1, int z1, int vx, int vy, int vz, int x3, in return FloatToFixed(result); } +[[deprecated]] +inline int32_t lintersect(const int32_t originX, const int32_t originY, const int32_t originZ, + const int32_t destX, const int32_t destY, const int32_t destZ, + const int32_t lineStartX, const int32_t lineStartY, const int32_t lineEndX, const int32_t lineEndY, + int32_t* intersectionX, int32_t* intersectionY, int32_t* intersectionZ) +{ + DVector3 retv; + bool result = GetLineIntersect(DVector3(originX * inttoworld, originY * inttoworld, originZ * zinttoworld), + DVector3((destX - originX) * inttoworld, (destY - originY) * inttoworld, (destZ - originZ) * zinttoworld), + DVector2(lineStartX * inttoworld, lineStartY * inttoworld), DVector2((lineEndX - lineStartX) * inttoworld, (lineEndY - lineStartY) * inttoworld), retv); + if (result) + { + *intersectionX = retv.X * worldtoint; + *intersectionY = retv.Y * worldtoint; + *intersectionZ = retv.Z * zworldtoint; + } + return result; +} + + #include "updatesector.h"