From f4c046a32ac8609cc016307679b22bf2fcca970b Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Sun, 17 Mar 2024 02:43:00 +0300 Subject: [PATCH] geom: simplify sweepAABB (this also will fix crash on ARMv8) --- src/game/g_grid.pas | 2 +- src/game/g_panel.pas | 4 ++-- src/shared/geom.pas | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas index 0e2876a..f19b11f 100644 --- a/src/game/g_grid.pas +++ b/src/game/g_grid.pas @@ -1653,7 +1653,7 @@ begin if ((ptag and TagDisabled) = 0) and ((ptag and tagmask) <> 0) and (px.mQueryMark <> lq) then begin px.mQueryMark := lq; // mark as processed - if not sweepAABB(ax0, ay0, aw, ah, dx, dy, px.mX, px.mY, px.mWidth, px.mHeight, @u0) then continue; + if not sweepAABB(ax0, ay0, aw, ah, dx, dy, px.mX, px.mY, px.mWidth, px.mHeight, u0) then continue; if (minu0 > u0) then begin hitpx := px; diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas index 964a95f..bc121df 100644 --- a/src/game/g_panel.pas +++ b/src/game/g_panel.pas @@ -644,7 +644,7 @@ var if (szdx < 0) then szdx := 0; if (szdy < 0) then szdy := 0; // move platform by szd* back, and check for szd* movement - if sweepAABB(ox-szdx, oy-szdy, nw, nh, szdx, szdy, px, py, pw, ph, @u0) then + if sweepAABB(ox-szdx, oy-szdy, nw, nh, szdx, szdy, px, py, pw, ph, u0) then begin // yes, platform hits the entity, push the entity in the resizing direction u0 := 1.0-u0; // how much path left? @@ -661,7 +661,7 @@ var end; end; // second, process platform movement, using te* as entity starting point - if sweepAABB(ox, oy, nw, nh, pdx, pdy, tex, tey, pw, ph, @u0) then + if sweepAABB(ox, oy, nw, nh, pdx, pdy, tex, tey, pw, ph, u0) then begin //e_LogWritefln('T: platsweep; u0=%s; u1=%s; hedge=%s; sweepAABB(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', [u0, u1, hedge, ox, oy, mpw, mph, pdx, pdy, px-1, py-1, pw+2, ph+2]); // yes, platform hits the entity, push the entity in the direction of the platform diff --git a/src/shared/geom.pas b/src/shared/geom.pas index b19a677..12a6409 100644 --- a/src/shared/geom.pas +++ b/src/shared/geom.pas @@ -44,9 +44,13 @@ type // enter/exit coords will form non-intersecting configuration (i.e. will be before/after the actual collision) // but beware of floating point inexactness; `sweepAABB()` will try to (crudely) compensate for it // while calculating `hitx` and `hity`. +{ function sweepAABB (mex0, mey0, mew, meh: Integer; medx, medy: Integer; itx0, ity0, itw, ith: Integer; u0: PSingle=nil; hitedge: PSweepEdge=nil; u1: PSingle=nil; hitx: PInteger=nil; hity: PInteger=nil): Boolean; +} +function sweepAABB (mex0, mey0, mew, meh: Integer; medx, medy: Integer; itx0, ity0, itw, ith: Integer; + out u0: Single): Boolean; function distanceSq (x0, y0, x1, y1: Integer): Integer; inline; @@ -170,6 +174,7 @@ end; // ////////////////////////////////////////////////////////////////////////// // +{ function sweepAABB (mex0, mey0, mew, meh: Integer; medx, medy: Integer; itx0, ity0, itw, ith: Integer; u0: PSingle=nil; hitedge: PSweepEdge=nil; u1: PSingle=nil; hitx: PInteger=nil; hity: PInteger=nil): Boolean; @@ -263,6 +268,69 @@ begin end; end; end; +} + +function sweepAABB (mex0, mey0, mew, meh: Integer; medx, medy: Integer; itx0, ity0, itw, ith: Integer; + out u0: Single): Boolean; +var + tin, tout: Single; + + function axisOverlap (me0, me1, it0, it1, d: Integer): Boolean; inline; + var t: Single; + begin + Result := false; + + if me1 < it0 then + begin + if (d >= 0) then + exit; // oops, no hit + t := (me1 - it0 + 1) / d; + if t > tin then + tin := t; + end + else if it1 < me0 then + begin + if d <= 0 then + exit; // oops, no hit + t := (me0 - it1 - 1) / d; + if t > tin then + tin := t; + end; + + if (d < 0) and (it1 > me0) then + begin + t := (me0 - it1 - 1) / d; + if t < tout then + tout := t; + end + else if (d > 0) and (me1 > it0) then + begin + t := (me1 - it0 + 1) / d; + if t < tout then + tout := t; + end; + + result := true; + end; + +begin + Result := False; + u0 := -1; + + if (mew >= 1) and (meh >= 1) and (itw >= 1) and (ith >= 1) and (medx <> 0) and (medy <> 0) then + begin + tin := -100000000.0; + tout := 100000000.0; + if axisOverlap(mex0, mex0 + mew - 1, itx0, itx0 + itw - 1, -medx) then + begin + if not axisOverlap(mey0, mey0 + meh - 1, ity0, ity0 + ith - 1, -medy) then + begin + u0 := tin; + Result := (tin <= tout) and (tin >= 0.0) and (tin <= 1.0); + end; + end; + end; +end; end. -- 2.11.4.GIT