From 7374364527b9fa78a31284319af15001fbed9a3c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 29 Jan 2022 09:29:01 +0100 Subject: [PATCH] - doFurniture floatified and inside rewritten as a floating point algorithm that works without bit masking. --- source/build/include/build.h | 6 +- source/build/src/engine.cpp | 31 ---------- source/core/gamefuncs.cpp | 32 ++++++++++ source/core/gamefuncs.h | 13 ++++ source/games/duke/src/sectors_r.cpp | 95 ++++++++++++----------------- 5 files changed, 84 insertions(+), 93 deletions(-) diff --git a/source/build/include/build.h b/source/build/include/build.h index f1cbbc0ba..92c17e5cd 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -164,7 +164,7 @@ int hitscan(const vec3_t& start, const sectortype* startsect, const vec3_t& dire void neartag(const vec3_t& pos, sectortype* sect, int angle, HitInfoBase& result, int neartagrange, int tagsearch); int cansee(int x1, int y1, int z1, sectortype* sect1, int x2, int y2, int z2, sectortype* sect2); -int32_t inside(int32_t x, int32_t y, const sectortype* sectnum); + int32_t try_facespr_intersect(DCoreActor* spr, vec3_t const in, int32_t vx, int32_t vy, int32_t vz, vec3_t * const intp, int32_t strictly_smaller_than_p); @@ -326,10 +326,6 @@ extern int skiptile; static vec2_t const zerovec = { 0, 0 }; -inline int inside_p(int32_t const x, int32_t const y, int const sectnum) { return (sectnum >= 0 && inside(x, y, §or[sectnum]) == 1); } -// same as above but with the same signature as inside_z_p for passing to updatesectorneighborz. -inline int inside_p0(int32_t const x, int32_t const y, int32_t const z, int const sectnum) { return inside_p(x, y, sectnum); } - #define SET_AND_RETURN(Lval, Rval) \ do \ { \ diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 88af7355f..bf7a90f33 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -284,37 +284,6 @@ int32_t rintersect(int32_t x1, int32_t y1, int32_t z1, return t; } -// -// inside -// -// See http://fabiensanglard.net/duke3d/build_engine_internals.php, -// "Inside details" for the idea behind the algorithm. - -int32_t inside(int32_t x, int32_t y, const sectortype* sect) -{ - if (sect) - { - unsigned cnt = 0; - vec2_t xy = { x, y }; - for(auto& wal : wallsofsector(sect)) - { - vec2_t v1 = wal.wall_int_pos() - xy; - vec2_t v2 = wal.point2Wall()->wall_int_pos() - xy; - - // If their signs differ[*], ... - // - // [*] where '-' corresponds to <0 and '+' corresponds to >=0. - // Equivalently, the branch is taken iff - // y1 != y2 AND y_m <= y < y_M, - // where y_m := min(y1, y2) and y_M := max(y1, y2). - if ((v1.Y^v2.Y) < 0) - cnt ^= (((v1.X^v2.X) >= 0) ? v1.X : (v1.X*v2.Y-v2.X*v1.Y)^v2.Y); - } - return cnt>>31; - } - return -1; -} - int32_t getangle(int32_t xvect, int32_t yvect) { diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index db290f493..9829abcb2 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -435,6 +435,38 @@ DVector2 rotatepoint(const DVector2& pivot, const DVector2& point, binangle angl // //========================================================================== +int inside(double x, double y, const sectortype* sect) +{ + if (sect) + { + double acc = 1; + for (auto& wal : wallsofsector(sect)) + { + double xs = (wal.pos.X - x); + double ys = (wal.pos.Y - y); + auto wal2 = wal.point2Wall(); + double xe = (wal2->pos.X - x); + double ye = (wal2->pos.Y - y); + + if ((ys * ye) < 0) + { + double val; + if ((xs * xe) >= 0) val = xs; + else val = (xs * ye - xe * ys) * ye; + acc *= val; + } + } + return acc < 0; + } + return -1; +} + +//========================================================================== +// +// +// +//========================================================================== + tspritetype* renderAddTsprite(tspritetype* tsprite, int& spritesortcnt, DCoreActor* actor) { validateTSpriteSize(tsprite, spritesortcnt); diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index af3afa84f..af0dd17f2 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -171,6 +171,8 @@ bool sectorsConnected(int sect1, int sect2); void dragpoint(walltype* wal, int newx, int newy); void dragpoint(walltype* wal, const DVector2& pos); DVector2 rotatepoint(const DVector2& pivot, const DVector2& point, binangle angle); +int32_t inside(double x, double y, const sectortype* sect); + // y is negated so that the orientation is the same as in GZDoom, in order to use its utilities. // The render code should NOT use Build coordinates for anything! @@ -301,6 +303,17 @@ inline int32_t tspriteGetZOfSlope(const tspritetype* tspr, int dax, int day) return tspr->pos.Z + MulScale(heinum, j, 18); } +inline int inside(int x, int y, const sectortype* sect) +{ + return inside(x * inttoworld, y * inttoworld, sect); +} + +// still needed by some parts in the engine. +inline int inside_p(int x, int y, int sectnum) { return (sectnum >= 0 && inside(x, y, §or[sectnum]) == 1); } +// this one is for template substitution. +inline int inside_p0(int32_t const x, int32_t const y, int32_t const z, int const sectnum) { return inside_p(x, y, sectnum); } + + inline int I_GetBuildTime() { diff --git a/source/games/duke/src/sectors_r.cpp b/source/games/duke/src/sectors_r.cpp index 8f6ba8191..b4508b386 100644 --- a/source/games/duke/src/sectors_r.cpp +++ b/source/games/duke/src/sectors_r.cpp @@ -2758,28 +2758,15 @@ void dofurniture(walltype* wlwal, sectortype* sectp, int snum) { assert(wlwal->twoSided()); auto nextsect = wlwal->nextSector(); - int var_C; - int x; - int y; - int min_x; - int min_y; - int max_x; - int max_y; - int ins; - int var_cx; - var_C = 1; - max_x = max_y = -0x20000; - min_x = min_y = 0x20000; - var_cx = sectp->hitag; - if (var_cx > 16) - var_cx = 16; - else if (var_cx == 0) - var_cx = 4; - for(auto& wal : wallsofsector(nextsect)) + double movestep = min(sectp->hitag * maptoworld, 1.); + if (movestep == 0) movestep = 4 * maptoworld; + + double max_x = INT32_MIN, max_y = INT32_MIN, min_x = INT32_MAX, min_y = INT32_MAX; + for (auto& wal : wallsofsector(sectp)) { - x = wal.wall_int_pos().X; - y = wal.wall_int_pos().Y; + double x = wal.pos.X; + double y = wal.pos.Y; if (x > max_x) max_x = x; if (y > max_y) @@ -2789,22 +2776,18 @@ void dofurniture(walltype* wlwal, sectortype* sectp, int snum) if (y < min_y) min_y = y; } - max_x += var_cx + 1; - max_y += var_cx + 1; - min_x -= var_cx + 1; - min_y -= var_cx + 1; - ins = inside(max_x, max_y, sectp); - if (!ins) - var_C = 0; - ins = inside(max_x, min_y, sectp); - if (!ins) - var_C = 0; - ins = inside(min_x, min_y, sectp); - if (!ins) - var_C = 0; - ins = inside(min_x, max_y, sectp); - if (!ins) - var_C = 0; + + double margin = movestep + maptoworld; + max_x += margin; + max_y += margin; + min_x -= margin; + min_y -= margin; + int pos_ok = 1; + if (!inside(max_x, max_y, sectp) || + !inside(max_x, min_y, sectp) || + !inside(min_x, min_y, sectp) || + !inside(min_x, max_y, sectp)) + pos_ok = 0; for (auto& wal : wallsofsector(nextsect)) { @@ -2822,31 +2805,30 @@ void dofurniture(walltype* wlwal, sectortype* sectp, int snum) } } - if (var_C) + if (pos_ok) { if (S_CheckActorSoundPlaying(ps[snum].GetActor(), 389) == 0) S_PlayActorSound(389, ps[snum].GetActor()); for(auto& wal : wallsofsector(nextsect)) { - x = wal.wall_int_pos().X; - y = wal.wall_int_pos().Y; + auto vec = wal.pos; switch (wlwal->lotag) { case 42: - y = wal.wall_int_pos().Y + var_cx; - dragpoint(&wal, x, y); + vec.Y += movestep; + dragpoint(&wal, vec); break; case 41: - x = wal.wall_int_pos().X - var_cx; - dragpoint(&wal, x, y); + vec.X -= movestep; + dragpoint(&wal, vec); break; case 40: - y = wal.wall_int_pos().Y - var_cx; - dragpoint(&wal, x, y); + vec.Y -= movestep; + dragpoint(&wal, vec); break; case 43: - x = wal.wall_int_pos().X + var_cx; - dragpoint(&wal, x, y); + vec.X += movestep; + dragpoint(&wal, vec); break; } } @@ -2855,25 +2837,24 @@ void dofurniture(walltype* wlwal, sectortype* sectp, int snum) { for(auto& wal : wallsofsector(nextsect)) { - x = wal.wall_int_pos().X; - y = wal.wall_int_pos().Y; + auto vec = wal.pos; switch (wlwal->lotag) { case 42: - y = wal.wall_int_pos().Y - (var_cx - 2); - dragpoint(&wal, x, y); + vec.Y -= movestep - 2; + dragpoint(&wal, vec); break; case 41: - x = wal.wall_int_pos().X + (var_cx - 2); - dragpoint(&wal, x, y); + vec.X += movestep - 2; + dragpoint(&wal, vec); break; case 40: - y = wal.wall_int_pos().Y + (var_cx - 2); - dragpoint(&wal, x, y); + vec.Y += movestep - 2; + dragpoint(&wal, vec); break; case 43: - x = wal.wall_int_pos().X - (var_cx - 2); - dragpoint(&wal, x, y); + vec.X -= movestep - 2; + dragpoint(&wal, vec); break; } }