From a12093af046a8130d68c55c8e616bf246a843e7b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 27 Jan 2022 20:19:53 +0100 Subject: [PATCH] - use full precision math for rotating sectors in Blood. --- source/common/thirdparty/math/cmath.h | 12 ++++ source/core/binaryangle.h | 5 ++ source/core/gamefuncs.cpp | 16 +++++ source/core/gamefuncs.h | 1 + source/core/maptypes.h | 2 +- source/games/blood/src/triggers.cpp | 86 +++++++++++---------------- 6 files changed, 71 insertions(+), 51 deletions(-) diff --git a/source/common/thirdparty/math/cmath.h b/source/common/thirdparty/math/cmath.h index 5c02c4e87..7059e5e57 100644 --- a/source/common/thirdparty/math/cmath.h +++ b/source/common/thirdparty/math/cmath.h @@ -54,6 +54,16 @@ extern FFastTrig fasttrig; #define RAD2BAM(f) ((unsigned)xs_CRoundToInt((f) * (0x80000000/3.14159265358979323846))) +inline double fastcosbam(double v) +{ + return fasttrig.cos(v); +} + +inline double fastsinbam(double v) +{ + return fasttrig.sin(v); +} + inline double fastcosdeg(double v) { return fasttrig.cos(DEG2BAM(v)); @@ -129,6 +139,8 @@ inline double cosdeg(double v) #else #define g_sindeg fastsindeg #define g_cosdeg fastcosdeg +#define g_sinbam fastsinbam +#define g_cosbam fastcosbam #define g_sin fastsin #define g_cos fastcos #endif diff --git a/source/core/binaryangle.h b/source/core/binaryangle.h index adb863a13..2c37f3eed 100644 --- a/source/core/binaryangle.h +++ b/source/core/binaryangle.h @@ -182,6 +182,11 @@ public: return binangle(value - other.value); } + constexpr binangle operator- () const + { + return binangle(0 - value); + } + constexpr binangle &operator<<= (const uint8_t shift) { value = tosigned() << shift; diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 906cac767..a5416fa2a 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -410,6 +410,22 @@ void dragpoint(walltype* startwall, int newx, int newy) // //========================================================================== +DVector2 rotatepoint(const DVector2& pivot, const DVector2& point, binangle angle) +{ + auto cosang = g_cosbam(angle.asbam()); + auto sinang = g_sinbam(angle.asbam()); + auto p = point - pivot; + return { + p.X * cosang - p.Y * sinang + pivot.X, + p.Y * cosang + p.X * sinang + pivot.Y }; +} + +//========================================================================== +// +// +// +//========================================================================== + tspritetype* renderAddTsprite(tspritetype* tsprite, int& spritesortcnt, DCoreActor* actor) { validateTSpriteSize(tsprite, spritesortcnt); diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index ec6d03e94..85961d9c4 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -169,6 +169,7 @@ void GetFlatSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, int* void checkRotatedWalls(); bool sectorsConnected(int sect1, int sect2); void dragpoint(walltype* wal, int newx, int newy); +DVector2 rotatepoint(const DVector2& pivot, const DVector2& point, binangle angle); // 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! diff --git a/source/core/maptypes.h b/source/core/maptypes.h index 7722d1316..298b8c09c 100644 --- a/source/core/maptypes.h +++ b/source/core/maptypes.h @@ -397,7 +397,7 @@ struct walltype // Blood is the only game which extends the wall struct. Blood::XWALL* _xw; - vec2_t baseWall; + DVector2 baseWall; int xpan() const { return int(xpan_); } int ypan() const { return int(ypan_); } diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp index cdae92be5..f996be9a8 100644 --- a/source/games/blood/src/triggers.cpp +++ b/source/games/blood/src/triggers.cpp @@ -833,21 +833,6 @@ void PathSound(sectortype* pSector, int nSound) // //--------------------------------------------------------------------------- -void DragPoint(walltype* pWall, int x, int y) -{ - vertexscan(pWall, [&](walltype* wal) - { - viewInterpolateWall(wal); - wal->move(x, y); - }); -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - void TranslateSector(sectortype* pSector, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, char a12) { int x, y; @@ -859,17 +844,33 @@ void TranslateSector(sectortype* pSector, int a2, int a3, int a4, int a5, int a6 int v8 = interpolatedvalue(a7, a10, a3); int v2c = v8 - v24; int v44 = interpolatedvalue(a8, a11, a2); - int vbp = interpolatedvalue(a8, a11, a3); - int v14 = vbp - v44; + int ang = interpolatedvalue(a8, a11, a3); + int v14 = ang - v44; + + DVector2 pivot = { a4 * maptoworld, a5 * maptoworld }; + DVector2 offset = { (vc - a4) * maptoworld, (v8 - a5) * maptoworld }; + auto angle = buildang(ang); + + auto rotatewall = [=](walltype* wal, binangle angle, const DVector2& offset) + { + auto vec = wal->baseWall; + if (angle.asbam() != 0) + vec = rotatepoint(pivot, vec, angle); + vec += offset; + + vertexscan(wal, [&](walltype* wal) + { + viewInterpolateWall(wal); + wal->pos = vec; + wal->moved(); + }); + }; + if (a12) { for (auto& wal : wallsofsector(pSector)) { - x = wal.baseWall.X; - y = wal.baseWall.Y; - if (vbp) - RotatePoint((int*)&x, (int*)&y, vbp, a4, a5); - DragPoint(&wal, x + vc - a4, y + v8 - a5); + rotatewall(&wal, angle, offset); } } else @@ -877,35 +878,23 @@ void TranslateSector(sectortype* pSector, int a2, int a3, int a4, int a5, int a6 for (auto& wal : wallsofsector(pSector)) { auto p2Wall = wal.point2Wall(); - x = wal.baseWall.X; - y = wal.baseWall.Y; if (wal.cstat & CSTAT_WALL_MOVE_FORWARD) { - if (vbp) - RotatePoint((int*)&x, (int*)&y, vbp, a4, a5); - DragPoint(&wal, x + vc - a4, y + v8 - a5); + rotatewall(&wal, angle, offset); + if ((p2Wall->cstat & CSTAT_WALL_MOVE_MASK) == 0) { - x = p2Wall->baseWall.X; - y = p2Wall->baseWall.Y; - if (vbp) - RotatePoint((int*)&x, (int*)&y, vbp, a4, a5); - DragPoint(p2Wall, x + vc - a4, y + v8 - a5); + rotatewall(p2Wall, angle, offset); } continue; } if (wal.cstat & CSTAT_WALL_MOVE_BACKWARD) { - if (vbp) - RotatePoint((int*)&x, (int*)&y, -vbp, a4, a5); - DragPoint(&wal, x - (vc - a4), y - (v8 - a5)); + rotatewall(&wal, -angle, -offset); + if ((p2Wall->cstat & CSTAT_WALL_MOVE_MASK) == 0) { - x = p2Wall->baseWall.X; - y = p2Wall->baseWall.Y; - if (vbp) - RotatePoint((int*)&x, (int*)&y, -vbp, a4, a5); - DragPoint(p2Wall, x - (vc - a4), y - (v8 - a5)); + rotatewall(p2Wall, -angle, -offset); } continue; } @@ -930,8 +919,8 @@ void TranslateSector(sectortype* pSector, int a2, int a3, int a4, int a5, int a6 y = actor->basePoint.Y; if (actor->spr.cstat & CSTAT_SPRITE_MOVE_FORWARD) { - if (vbp) - RotatePoint((int*)&x, (int*)&y, vbp, a4, a5); + if (ang) + RotatePoint((int*)&x, (int*)&y, ang, a4, a5); viewBackupSpriteLoc(actor); actor->spr.ang = (actor->spr.ang + v14) & 2047; actor->spr.pos.X = x + vc - a4; @@ -939,8 +928,8 @@ void TranslateSector(sectortype* pSector, int a2, int a3, int a4, int a5, int a6 } else if (actor->spr.cstat & CSTAT_SPRITE_MOVE_REVERSE) { - if (vbp) - RotatePoint((int*)&x, (int*)&y, -vbp, a4, a4); + if (ang) + RotatePoint((int*)&x, (int*)&y, -ang, a4, a4); viewBackupSpriteLoc(actor); actor->spr.ang = (actor->spr.ang - v14) & 2047; actor->spr.pos.X = x - (vc - a4); @@ -2172,8 +2161,7 @@ void trInit(TArray& actors) gBusy.Clear(); for (auto& wal : wall) { - wal.baseWall.X = wal.wall_int_pos().X; - wal.baseWall.Y = wal.wall_int_pos().Y; + wal.baseWall = wal.pos; } for (auto actor : actors) { @@ -2224,8 +2212,7 @@ void trInit(TArray& actors) TranslateSector(pSector, 0, -65536, marker0->spr.pos.X, marker0->spr.pos.Y, marker0->spr.pos.X, marker0->spr.pos.Y, marker0->spr.ang, marker1->spr.pos.X, marker1->spr.pos.Y, marker1->spr.ang, pSector->type == kSectorSlide); for (auto& wal : wallsofsector(pSector)) { - wal.baseWall.X = wal.wall_int_pos().X; - wal.baseWall.Y = wal.wall_int_pos().Y; + wal.baseWall = wal.pos; } BloodSectIterator it(pSector); while (auto actor = it.Next()) @@ -2243,8 +2230,7 @@ void trInit(TArray& actors) TranslateSector(pSector, 0, -65536, marker0->spr.pos.X, marker0->spr.pos.Y, marker0->spr.pos.X, marker0->spr.pos.Y, 0, marker0->spr.pos.X, marker0->spr.pos.Y, marker0->spr.ang, pSector->type == kSectorRotate); for (auto& wal : wallsofsector(pSector)) { - wal.baseWall.X = wal.wall_int_pos().X; - wal.baseWall.Y = wal.wall_int_pos().Y; + wal.baseWall = wal.pos; } BloodSectIterator it(pSector); while (auto actor = it.Next())