diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index b4d81d6b7..41e7c3c12 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -1499,7 +1499,7 @@ int hitscan(const vec3_t& start, const sectortype* startsect, const vec3_t& dire case CSTAT_SPRITE_ALIGNMENT_SLOPE: { - int32_t x3, y3, x4, y4, zz; + int32_t x3, y3, x4, y4; int32_t const heinum = spriteGetSlope(spr); int32_t const dax = (heinum * sintable[(spr->ang + 1024) & 2047]) << 1; int32_t const day = (heinum * sintable[(spr->ang + 512) & 2047]) << 1; diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index df8f8e999..6c83bcd10 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -2635,24 +2635,6 @@ static int32_t polymost_lintersect(int32_t x1, int32_t y1, int32_t x2, int32_t y return rv; } - -static inline int16_t tspriteGetSlope(tspriteptr_t const tspr) -{ - if (!(tspr->cstat2 & CSTAT2_SPRITE_SLOPE)) - return 0; - return uint8_t(tspr->xoffset) + (uint8_t(tspr->yoffset) << 8); -} - -static inline int32_t tspriteGetZOfSlope(tspriteptr_t const tspr, int32_t dax, int32_t day) -{ - int16_t const heinum = tspriteGetSlope(tspr); - if (heinum == 0) - return tspr->z; - - int const j = DMulScale(bsin(tspr->ang + 1024), day - tspr->y, -bsin(tspr->ang + 512), dax - tspr->x, 4); - return tspr->z + MulScale(heinum, j, 18); -} - static inline float tspriteGetZOfSlopeFloat(tspriteptr_t const tspr, float dax, float day) { int16_t const heinum = tspriteGetSlope(tspr); @@ -3700,7 +3682,7 @@ void renderDrawMasks(void) if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) == CSTAT_SPRITE_ALIGNMENT_FLOOR) { numpts = 4; - GetFlatSpritePosition(tspr, tspr->pos.vec2, pp); + GetFlatSpritePosition(tspr, tspr->pos.vec2, pp, nullptr); } else { diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 2b947528e..f5d7a10ad 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -274,12 +274,13 @@ void GetWallSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, bool // //========================================================================== -template -void TGetFlatSpritePosition(const sprt* spr, vec2_t pos, vec2_t* out, bool render) +void TGetFlatSpritePosition(const spritetypebase* spr, vec2_t pos, vec2_t* out, int* outz, int heinum, bool render) { auto tex = tileGetTexture(spr->picnum); int width, height, leftofs, topofs; + int ratio = ksqrt(heinum * heinum + 4096 * 4096); + if (render && hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) { width = TileFiles.tiledata[spr->picnum].hiofs.xsize * spr->xrepeat; @@ -303,26 +304,40 @@ void TGetFlatSpritePosition(const sprt* spr, vec2_t pos, vec2_t* out, bool rende int cosang = bcos(spr->ang); int sinang = bsin(spr->ang); + int cosangslope = DivScale(cosang, ratio, 12); + int sinangslope = DivScale(sinang, ratio, 12); - out[0].x = pos.x + DMulScale(sinang, sprcenterx, cosang, sprcentery, 16); - out[0].y = pos.y + DMulScale(sinang, sprcentery, -cosang, sprcenterx, 16); + out[0].x = pos.x + DMulScale(sinang, sprcenterx, cosangslope, sprcentery, 16); + out[0].y = pos.y + DMulScale(sinangslope, sprcentery, -cosang, sprcenterx, 16); out[1].x = out[0].x - MulScale(sinang, width, 16); out[1].y = out[0].y + MulScale(cosang, width, 16); - vec2_t sub = { MulScale(cosang, height, 16), MulScale(sinang, height, 16) }; + vec2_t sub = { MulScale(cosangslope, height, 16), MulScale(sinangslope, height, 16) }; out[2] = out[1] - sub; out[3] = out[0] - sub; + if (outz) + { + if (!heinum) outz[3] = outz[2] = outz[1] = outz[0] = 0; + else + { + for (int i = 0; i < 4; i++) + { + int spos = DMulScale(-sinang, out[i].y - spr->y, -cosang, out[i].x - spr->x, 4); + outz[i] = MulScale(heinum, spos, 18); + } + } + } } void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool render) { - TGetFlatSpritePosition(spr, pos, out, render); + TGetFlatSpritePosition(spr, pos, out, nullptr, spriteGetSlope(spr), render); } -void GetFlatSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, bool render) +void GetFlatSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, int* outz, bool render) { - TGetFlatSpritePosition(spr, pos, out, render); + TGetFlatSpritePosition(spr, pos, out, outz, tspriteGetSlope(spr), render); } //========================================================================== diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index e73b442c4..50931f94d 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -126,8 +126,8 @@ int getslopeval(sectortype* sect, int x, int y, int z, int planez); void setWallSectors(); void GetWallSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, bool render = false); -void GetFlatSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, bool render = false); void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool render = false); +void GetFlatSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, int* outz = nullptr, bool render = false); void checkRotatedWalls(); bool sectorsConnected(int sect1, int sect2); @@ -265,6 +265,22 @@ inline int spriteGetSlope(const spritetype* spr) return ((spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != CSTAT_SPRITE_ALIGNMENT_SLOPE) ? 0 : uint8_t(spr->xoffset) + (uint8_t(spr->yoffset) << 8); } +// same stuff, different flag... +inline int tspriteGetSlope(const tspritetype* spr) +{ + return !(spr->cstat2 & CSTAT2_SPRITE_SLOPE) ? 0 : uint8_t(spr->xoffset) + (uint8_t(spr->yoffset) << 8); +} + +inline int32_t tspriteGetZOfSlope(const tspritetype* tspr, int dax, int day) +{ + int heinum = tspriteGetSlope(tspr); + if (heinum == 0) return tspr->z; + + int const j = DMulScale(bsin(tspr->ang + 1024), day - tspr->y, -bsin(tspr->ang + 512), dax - tspr->x, 4); + return tspr->z + MulScale(heinum, j, 18); +} + + inline int I_GetBuildTime() { return I_GetTime(120); diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index 275af90a9..95e6417b3 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -272,7 +272,7 @@ public: int plane; int vertindex, vertcount; // this should later use a static vertex buffer, but that'd hinder the development phase, so for now vertex data gets created on the fly. - void MakeVertices(); + void MakeVertices(HWDrawInfo* di); int dynlightindex; diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index ce62ac4b3..84e612d5a 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -93,7 +93,7 @@ void HWFlat::SetupLights(HWDrawInfo *di, FLightNode * node, FDynLightData &light // //========================================================================== -void HWFlat::MakeVertices() +void HWFlat::MakeVertices(HWDrawInfo* di) { if (vertcount > 0) return; bool canvas = texture->isHardwareCanvas(); @@ -120,17 +120,54 @@ void HWFlat::MakeVertices() else { vec2_t pos[4]; - GetFlatSpritePosition(Sprite, Sprite->pos.vec2, pos, true); + int ofsz[4]; + GetFlatSpritePosition(Sprite, Sprite->pos.vec2, pos, ofsz, true); auto ret = screen->mVertexData->AllocVertices(6); auto vp = ret.first; float x = !(Sprite->cstat & CSTAT_SPRITE_XFLIP) ? 0.f : 1.f; float y = !(Sprite->cstat & CSTAT_SPRITE_YFLIP) ? 0.f : 1.f; + if (Sprite->cstat2 & CSTAT2_SPRITE_SLOPE) + { + + int posx = int(di->Viewpoint.Pos.X * 16.f); + int posy = int(di->Viewpoint.Pos.Y * -16.f); + int posz = int(di->Viewpoint.Pos.Z * -256.f); + + // Make adjustments for poorly aligned slope sprites on floors or ceilings + constexpr float ONPLANE_THRESHOLD = 3.f; + if (tspriteGetZOfSlope(Sprite, posx, posy) < posz) + { + float maxofs = -FLT_MAX, minofs = FLT_MAX; + for (int i = 0; i < 4; i++) + { + float vz = getceilzofslopeptr(Sprite->sectp, pos[i].x, pos[i].y) * (1 / -256.f); + float sz = z + ofsz[i] * (1 / -256.f); + int diff = vz - sz; + if (diff > maxofs) maxofs = diff; + if (diff < minofs) minofs = diff; + } + if (maxofs > 0 && minofs >= -ONPLANE_THRESHOLD && maxofs <= ONPLANE_THRESHOLD) z -= maxofs; + } + else + { + float maxofs = -FLT_MAX, minofs = FLT_MAX; + for (int i = 0; i < 4; i++) + { + float vz = getflorzofslopeptr(Sprite->sectp, pos[i].x, pos[i].y) * (1 / -256.f); + float sz = z + ofsz[i] * (1 / -256.f); + int diff = vz - sz; + if (diff > maxofs) maxofs = diff; + if (diff < minofs) minofs = diff; + } + if (minofs < 0 && maxofs <= -ONPLANE_THRESHOLD && minofs >= ONPLANE_THRESHOLD) z -= minofs; + } + } for (unsigned i = 0; i < 6; i++) { const static unsigned indices[] = { 0, 1, 2, 0, 2, 3 }; int j = indices[i]; - vp->SetVertex(pos[j].x * (1 / 16.f), z, pos[j].y * (1 / -16.f)); + vp->SetVertex(pos[j].x * (1 / 16.f), z + ofsz[j] * (1 / -256.f), pos[j].y * (1 / -16.f)); if (!canvas) vp->SetTexCoord(j == 1 || j == 2 ? 1.f - x : x, j == 2 || j == 3 ? 1.f - y : y); else vp->SetTexCoord(j == 1 || j == 2 ? 1.f - x : x, j == 2 || j == 3 ? y : 1.f - y); vp++; @@ -149,7 +186,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) { if (screen->BuffersArePersistent() && !Sprite) { - MakeVertices(); + MakeVertices(di); } #ifdef _DEBUG @@ -228,7 +265,7 @@ void HWFlat::PutFlat(HWDrawInfo *di, int whichplane) SetupLights(di, section->lighthead, lightdata, sector->PortalGroup); } #endif - MakeVertices(); + MakeVertices(di); } di->AddFlat(this); rendered_flats++;