From d0f38d73621ca85c1275723fa20cabad109eea98 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 27 Mar 2021 13:22:34 +0100 Subject: [PATCH] - wall sprite WIP. --- source/core/gamefuncs.cpp | 27 ++- source/core/gamefuncs.h | 2 +- source/core/rendering/scene/hw_drawinfo.cpp | 25 ++- source/core/rendering/scene/hw_drawinfo.h | 1 - source/core/rendering/scene/hw_drawlist.cpp | 94 ++++++++++- source/core/rendering/scene/hw_drawlist.h | 3 +- .../core/rendering/scene/hw_drawlistadd.cpp | 13 +- source/core/rendering/scene/hw_drawstructs.h | 2 +- source/core/rendering/scene/hw_sprites.cpp | 155 ------------------ source/core/rendering/scene/hw_walls.cpp | 107 ++++++++++++ 10 files changed, 243 insertions(+), 186 deletions(-) diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 698a7d89d..43bb4571d 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -208,13 +208,26 @@ void PlanesAtPoint(const sectortype* sec, float dax, float day, float* pceilz, f // //========================================================================== -void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out) +void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool render) { + auto tex = tileGetTexture(spr->picnum); + + int width, leftofs; + if (render && hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize) + { + width = TileFiles.tiledata[spr->picnum].h_xsize * spr->xrepeat; + leftofs = (TileFiles.tiledata[spr->picnum].h_xoffs + spr->xoffset) * spr->xrepeat; + } + else + { + width = tex->GetTexelWidth() * spr->xrepeat; + leftofs = (tex->GetTexelLeftOffset() + spr->xoffset) * spr->xrepeat; + } + int x = bsin(spr->ang) * spr->xrepeat; int y = -bcos(spr->ang) * spr->xrepeat; - int width = tileWidth(spr->picnum); - int xoff = tileLeftOffset(spr->picnum) + spr->xoffset; + int xoff = leftofs + spr->xoffset; if (spr->cstat & CSTAT_SPRITE_XFLIP) xoff = -xoff; int origin = (width >> 1) + xoff; @@ -235,19 +248,21 @@ void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool { auto tex = tileGetTexture(spr->picnum); - int width, height; + int width, height, leftofs, topofs; if (render && hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize) { width = TileFiles.tiledata[spr->picnum].h_xsize * spr->xrepeat; height = TileFiles.tiledata[spr->picnum].h_ysize * spr->yrepeat; + leftofs = (TileFiles.tiledata[spr->picnum].h_xoffs + spr->xoffset) * spr->xrepeat; + topofs = (TileFiles.tiledata[spr->picnum].h_yoffs + spr->yoffset) * spr->yrepeat; } else { width = tex->GetTexelWidth() * spr->xrepeat; height = tex->GetTexelHeight() * spr->yrepeat; + leftofs = (tex->GetTexelLeftOffset() + spr->xoffset) * spr->xrepeat; + topofs = (tex->GetTexelTopOffset() + spr->yoffset) * spr->yrepeat; } - int leftofs = (tex->GetTexelLeftOffset() + spr->xoffset) * spr->xrepeat; - int topofs = (tex->GetTexelTopOffset() + spr->yoffset) * spr->yrepeat; if (spr->cstat & CSTAT_SPRITE_XFLIP) leftofs = -leftofs; if (spr->cstat & CSTAT_SPRITE_YFLIP) topofs = -topofs; diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index 7cd485c3b..5435325e6 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -10,7 +10,7 @@ bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnu bool spriteIsModelOrVoxel(const spritetype* tspr); void PlanesAtPoint(const sectortype* sec, float dax, float day, float* ceilz, float* florz); void setWallSectors(); -void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out); +void GetWallSpritePosition(const spritetype* 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 checkRotatedWalls(); diff --git a/source/core/rendering/scene/hw_drawinfo.cpp b/source/core/rendering/scene/hw_drawinfo.cpp index 0bae0019c..233e82845 100644 --- a/source/core/rendering/scene/hw_drawinfo.cpp +++ b/source/core/rendering/scene/hw_drawinfo.cpp @@ -346,8 +346,11 @@ void HWDrawInfo::DispatchSprites() break; case CSTAT_SPRITE_ALIGNMENT_WALL: - // wall sprite + { + HWWall wall; + wall.ProcessWallSprite(this, tspr, §or[tspr->sectnum]); break; + } case CSTAT_SPRITE_ALIGNMENT_FLOOR: { @@ -445,20 +448,32 @@ void HWDrawInfo::RenderScene(FRenderState &state) // These lists must be drawn in two passes for color and depth to avoid depth fighting with overlapping entries drawlists[GLDL_MASKEDFLATS].SortFlats(this); - //drawlists[GLDL_MASKEDWALLSV].SortWalls(this); - //drawlists[GLDL_MASKEDWALLSH].SortWalls(this); + drawlists[GLDL_MASKEDWALLSV].SortWallsVert(this); + drawlists[GLDL_MASKEDWALLSH].SortWallsHorz(this); // these lists are only wall and floor sprites - often attached to walls and floors - so they need to be offset from the plane they may be attached to. drawlists[GLDL_MASKEDWALLSS].DrawWalls(this, state, false); + + // Each list must draw both its passes before the next one to ensure proper depth buffer contents. state.SetDepthBias(-1, -128); state.SetDepthMask(false); drawlists[GLDL_MASKEDWALLSV].DrawWalls(this, state, false); - drawlists[GLDL_MASKEDWALLSH].DrawWalls(this, state, false); - drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false); state.SetDepthMask(true); state.SetColorMask(false); drawlists[GLDL_MASKEDWALLSV].DrawWalls(this, state, false); + state.SetColorMask(true); + + state.SetDepthMask(false); drawlists[GLDL_MASKEDWALLSH].DrawWalls(this, state, false); + state.SetDepthMask(true); + state.SetColorMask(false); + drawlists[GLDL_MASKEDWALLSH].DrawWalls(this, state, false); + state.SetColorMask(true); + + state.SetDepthMask(false); + drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false); + state.SetDepthMask(true); + state.SetColorMask(false); drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false); state.SetColorMask(true); state.ClearDepthBias(); diff --git a/source/core/rendering/scene/hw_drawinfo.h b/source/core/rendering/scene/hw_drawinfo.h index 70bea1fa9..ea52a6857 100644 --- a/source/core/rendering/scene/hw_drawinfo.h +++ b/source/core/rendering/scene/hw_drawinfo.h @@ -76,7 +76,6 @@ enum DrawListType GLDL_MASKEDWALLSV, // vertical wall sprites GLDL_MASKEDWALLSH, // horizontal wall sprites. These two lists merely exist for easier sorting. GLDL_MASKEDFLATS, - GLDL_MASKEDWALLSOFS, GLDL_MODELS, GLDL_TRANSLUCENT, diff --git a/source/core/rendering/scene/hw_drawlist.cpp b/source/core/rendering/scene/hw_drawlist.cpp index a2c0bb116..29aeb489d 100644 --- a/source/core/rendering/scene/hw_drawlist.cpp +++ b/source/core/rendering/scene/hw_drawlist.cpp @@ -703,26 +703,104 @@ void HWDrawList::Sort(HWDrawInfo *di) //========================================================================== // -// Sorting the drawitems first by texture and then by light level +// // //========================================================================== -void HWDrawList::SortWalls() +void HWDrawList::SortWallsVert(HWDrawInfo* di) { + auto viewy = di->Viewpoint.Pos.Y; if (drawitems.Size() > 1) { - std::sort(drawitems.begin(), drawitems.end(), [=](const HWDrawItem &a, const HWDrawItem &b) -> bool + TArray list1(drawitems.Size(), false); + TArray list2(drawitems.Size(), false); + + for (auto& item : drawitems) { - HWWall * w1 = walls[a.index]; - HWWall * w2 = walls[b.index]; + HWWall* w1 = walls[item.index]; + if (w1->glseg.y1 < viewy) list1.Push(item); + else list2.Push(item); + } - if (w1->texture != w2->texture) return w1->texture < w2->texture; - return (w1->flags & 3) < (w2->flags & 3); + std::sort(list1.begin(), list1.end(), [=](const HWDrawItem& a, const HWDrawItem& b) + { + HWWall* w1 = walls[a.index]; + HWWall* w2 = walls[b.index]; + if (w1->glseg.y1 != w2->glseg.y1) return w1->glseg.y1 < w2->glseg.y1; + int time1 = w1->sprite ? w1->sprite->time : -1; + int time2 = w2->sprite ? w2->sprite->time : -1; + return time1 < time2; + }); - }); + std::sort(list2.begin(), list2.end(), [=](const HWDrawItem& a, const HWDrawItem& b) + { + HWWall* w1 = walls[a.index]; + HWWall* w2 = walls[b.index]; + if (w1->glseg.y1 != w2->glseg.y1) return w1->glseg.y1 > w2->glseg.y1; + int time1 = w1->sprite ? w1->sprite->time : -1; + int time2 = w2->sprite ? w2->sprite->time : -1; + return time1 < time2; + }); + + drawitems.Clear(); + drawitems.Append(list1); + drawitems.Append(list2); } } +//========================================================================== +// +// +// +//========================================================================== + +void HWDrawList::SortWallsHorz(HWDrawInfo* di) +{ + auto viewx = di->Viewpoint.Pos.X; + if (drawitems.Size() > 1) + { + TArray list1(drawitems.Size(), false); + TArray list2(drawitems.Size(), false); + + for (auto& item : drawitems) + { + HWWall* w1 = walls[item.index]; + if (w1->glseg.x1 < viewx) list1.Push(item); + else list2.Push(item); + } + + std::sort(list1.begin(), list1.end(), [=](const HWDrawItem& a, const HWDrawItem& b) + { + HWWall* w1 = walls[a.index]; + HWWall* w2 = walls[b.index]; + if (w1->glseg.x1 != w2->glseg.x1) return w1->glseg.x1 < w2->glseg.x1; + int time1 = w1->sprite ? w1->sprite->time : -1; + int time2 = w2->sprite ? w2->sprite->time : -1; + return time1 < time2; + }); + + std::sort(list2.begin(), list2.end(), [=](const HWDrawItem& a, const HWDrawItem& b) + { + HWWall* w1 = walls[a.index]; + HWWall* w2 = walls[b.index]; + if (w1->glseg.x1 != w2->glseg.x1) return w1->glseg.x1 > w2->glseg.x1; + int time1 = w1->sprite ? w1->sprite->time : -1; + int time2 = w2->sprite ? w2->sprite->time : -1; + return time1 < time2; + }); + + drawitems.Clear(); + drawitems.Append(list1); + drawitems.Append(list2); + } +} + +//========================================================================== +// +// +// +//========================================================================== + void HWDrawList::SortFlats(HWDrawInfo* di) { auto viewz = di->Viewpoint.Pos.Z; diff --git a/source/core/rendering/scene/hw_drawlist.h b/source/core/rendering/scene/hw_drawlist.h index e8913d904..3ddb72682 100644 --- a/source/core/rendering/scene/hw_drawlist.h +++ b/source/core/rendering/scene/hw_drawlist.h @@ -92,7 +92,8 @@ public: HWFlat *NewFlat(); HWSprite *NewSprite(); void Reset(); - void SortWalls(); + void SortWallsHorz(HWDrawInfo* di); + void SortWallsVert(HWDrawInfo* di); void SortFlats(HWDrawInfo* di); diff --git a/source/core/rendering/scene/hw_drawlistadd.cpp b/source/core/rendering/scene/hw_drawlistadd.cpp index a1c8f53d0..6be42533d 100644 --- a/source/core/rendering/scene/hw_drawlistadd.cpp +++ b/source/core/rendering/scene/hw_drawlistadd.cpp @@ -50,14 +50,11 @@ void HWDrawInfo::AddWall(HWWall *wall) bool masked = wall->type != RENDERWALL_M2S ? false : (wall->texture && wall->texture->isMasked()); int list; - if (wall->flags & HWWall::HWF_SKYHACK && wall->type == RENDERWALL_M2S) - { - list = GLDL_MASKEDWALLSOFS; - } - else - { - list = masked ? GLDL_MASKEDWALLS : GLDL_PLAINWALLS; - } + if (!masked) list = GLDL_PLAINWALLS; + else if (sprite == nullptr) list = GLDL_MASKEDWALLS; + else if (wall->glseg.x1 == wall->glseg.x2) list = GLDL_MASKEDWALLSV; + else if (wall->glseg.y1 == wall->glseg.y2) list = GLDL_MASKEDWALLSH; + else list = GLDL_MASKEDWALLSS; auto newwall = drawlists[list].NewWall(); *newwall = *wall; } diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index f5acc25dc..530c6cfea 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -230,7 +230,7 @@ public: public: void Process(HWDrawInfo* di, walltype* seg, sectortype* frontsector, sectortype* backsector); - void ProcessWallSprite(HWDrawInfo* di, walltype* seg, sectortype* frontsector, sectortype* backsector); + void ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* frontsector); float PointOnSide(float x,float y) { diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index e9302ab03..d6ae6a5f4 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -149,161 +149,6 @@ void polymost_drawsprite(int32_t snum) } break; - case 1: // Wall sprite - { - // Project 3D to 2D - if (globalorientation & 4) - off.x = -off.x; - - if (globalorientation & 8) - off.y = -off.y; - - vec2f_t const extent = { float(tspr->xrepeat * bsinf(tspr->ang, -16)), - float(tspr->xrepeat * -bcosf(tspr->ang, -16)) }; - - float f = (float)(tsiz.x >> 1) + (float)off.x; - - vec2f_t const vf = { extent.x * f, extent.y * f }; - - vec2f_t vec0 = { (float)(pos.x - globalposx) - vf.x, - (float)(pos.y - globalposy) - vf.y }; - - int32_t const s = tspr->owner; - int32_t walldist = 1; - int32_t w = (s == -1) ? -1 : wsprinfo[s].wall; - - vec2f_t p0 = { vec0.y * gcosang - vec0.x * gsinang, - vec0.x * gcosang2 + vec0.y * gsinang2 }; - - vec2f_t const pp = { extent.x * ftsiz.x + vec0.x, - extent.y * ftsiz.x + vec0.y }; - - vec2f_t p1 = { pp.y * gcosang - pp.x * gsinang, - pp.x * gcosang2 + pp.y * gsinang2 }; - - if ((p0.y <= SCISDIST) && (p1.y <= SCISDIST)) - goto _drawsprite_return; - - // Clip to close parallel-screen plane - vec2f_t const op0 = p0; - - float t0 = 0.f, t1 = 1.f; - - if (p0.y < SCISDIST) - { - t0 = (SCISDIST - p0.y) / (p1.y - p0.y); - p0 = { (p1.x - p0.x) * t0 + p0.x, SCISDIST }; - } - - if (p1.y < SCISDIST) - { - t1 = (SCISDIST - op0.y) / (p1.y - op0.y); - p1 = { (p1.x - op0.x) * t1 + op0.x, SCISDIST }; - } - - f = 1.f / p0.y; - const float ryp0 = f * gyxscale; - float sx0 = ghalfx * p0.x * f + ghalfx; - - f = 1.f / p1.y; - const float ryp1 = f * gyxscale; - float sx1 = ghalfx * p1.x * f + ghalfx; - - pos.z -= ((off.y * tspr->yrepeat) << 2); - - if (globalorientation & 128) - { - pos.z += ((tsiz.y * tspr->yrepeat) << 1); - - if (tsiz.y & 1) - pos.z += (tspr->yrepeat << 1); // Odd yspans - } - - xtex.d = (ryp0 - ryp1) * gxyaspect / (sx0 - sx1); - ytex.d = 0; - otex.d = ryp0 * gxyaspect - xtex.d * sx0; - - if (globalorientation & 4) - { - t0 = 1.f - t0; - t1 = 1.f - t1; - } - - xtex.u = (t0 * ryp0 - t1 * ryp1) * gxyaspect * ftsiz.x / (sx0 - sx1); - ytex.u = 0; - otex.u = t0 * ryp0 * gxyaspect * ftsiz.x - xtex.u * sx0; - - f = ((float) tspr->yrepeat) * ftsiz.y * 4; - - float sc0 = ((float) (pos.z - globalposz - f)) * ryp0 + ghoriz; - float sc1 = ((float) (pos.z - globalposz - f)) * ryp1 + ghoriz; - float sf0 = ((float) (pos.z - globalposz)) * ryp0 + ghoriz; - float sf1 = ((float) (pos.z - globalposz)) * ryp1 + ghoriz; - - // gvx*sx0 + gvy*sc0 + gvo = 0 - // gvx*sx1 + gvy*sc1 + gvo = 0 - // gvx*sx0 + gvy*sf0 + gvo = tsizy*(gdx*sx0 + gdo) - f = ftsiz.y * (xtex.d * sx0 + otex.d) / ((sx0 - sx1) * (sc0 - sf0)); - - if (!(globalorientation & 8)) - { - xtex.v = (sc0 - sc1) * f; - ytex.v = (sx1 - sx0) * f; - otex.v = -xtex.v * sx0 - ytex.v * sc0; - } - else - { - xtex.v = (sf1 - sf0) * f; - ytex.v = (sx0 - sx1) * f; - otex.v = -xtex.v * sx0 - ytex.v * sf0; - } - - // Clip sprites to ceilings/floors when no parallaxing - if (!(sector[tspr->sectnum].ceilingstat & 1)) - { - if (sector[tspr->sectnum].ceilingz > pos.z - (float)((tspr->yrepeat * tsiz.y) << 2)) - { - sc0 = (float)(sector[tspr->sectnum].ceilingz - globalposz) * ryp0 + ghoriz; - sc1 = (float)(sector[tspr->sectnum].ceilingz - globalposz) * ryp1 + ghoriz; - } - } - if (!(sector[tspr->sectnum].floorstat & 1)) - { - if (sector[tspr->sectnum].floorz < pos.z) - { - sf0 = (float)(sector[tspr->sectnum].floorz - globalposz) * ryp0 + ghoriz; - sf1 = (float)(sector[tspr->sectnum].floorz - globalposz) * ryp1 + ghoriz; - } - } - - if (sx0 > sx1) - { - if (globalorientation & 64) - goto _drawsprite_return; // 1-sided sprite - - std::swap(sx0, sx1); - std::swap(sc0, sc1); - std::swap(sf0, sf1); - } - - vec2f_t const pxy[4] = { { sx0, sc0 }, { sx1, sc1 }, { sx1, sf1 }, { sx0, sf0 } }; - - vec2_16_t tempsiz = { (int16_t)tsiz.x, (int16_t)tsiz.y }; - pow2xsplit = 0; - polymost_drawpoly(pxy, 4, method, tempsiz); - - drawpoly_srepeat = 0; - drawpoly_trepeat = 0; - } - break; - - case 2: // Floor sprite - else - - break; - - case 3: // Voxel sprite - break; } if (automapping == 1 && (unsigned)spritenum < MAXSPRITES) diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index 5b2a80499..cdd942b0f 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -1067,3 +1067,110 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec globalr = globalg = globalb = 255; } +void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sector) +{ + auto tex = tileGetTexture(spr->picnum); + if (!tex || !tex->isValid()) return; + + seg = nullptr; + sprite = spr; + vec2_t pos[2]; + int sprz = spr->pos.z; + + if (spr->cstat & CSTAT_SPRITE_ONE_SIDED) + { + DAngle sprang = buildang(spr->ang).asdeg(); + DAngle lookang = bamang(di->Viewpoint.RotAngle).asdeg(); + if ((sprang.ToVector() | lookang.ToVector()) >= 0.) return; + } + + vertindex = 0; + vertcount = 0; + type = RENDERWALL_M2S; + frontsector = sector; + backsector = sector; + texture = tex; + + flags = 0; + dynlightindex = -1; + shade = spr->shade; + palette = spr->pal; + fade = lookups.getFade(sector->floorpal); // fog is per sector. + visibility = sectorVisibility(sector); + + bool trans = (sprite->cstat & CSTAT_SPRITE_TRANSLUCENT); + if (trans) + { + RenderStyle = GetRenderStyle(0, !!(sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); + alpha = GetAlphaFromBlend((sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); + } + else + { + RenderStyle = LegacyRenderStyles[STYLE_Translucent]; + alpha = 1.f; + } + + + GetWallSpritePosition(spr, spr->pos.vec2, pos, true); + + int height, topofs; + if (hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize) + { + height = TileFiles.tiledata[spr->picnum].h_ysize; + topofs = (TileFiles.tiledata[spr->picnum].h_yoffs + spr->yoffset); + } + else + { + height = tex->GetTexelHeight(); + topofs = (tex->GetTexelTopOffset() + spr->yoffset); + } + + if (spr->cstat & CSTAT_SPRITE_YFLIP) + topofs = -topofs; + + sprz -= ((topofs * spr->yrepeat) << 2); + + if (spr->cstat & CSTAT_SPRITE_YCENTER) + { + sprz += ((height * spr->yrepeat) << 1); + if (height & 1) sprz += (spr->yrepeat << 1); // Odd yspans (taken from polymost as-is) + } + + glseg.fracleft = 0; + glseg.fracright = 1; + glseg.x1 = pos[0].x * (1 / 16.f); + glseg.y1 = pos[0].y * (1 / -16.f); + glseg.x2 = pos[1].x * (1 / 16.f); + glseg.y2 = pos[1].y * (1 / -16.f); + tcs[LOLFT].u = tcs[UPLFT].u = (spr->cstat & CSTAT_SPRITE_XFLIP) ? 1.f : 0.f; + tcs[LORGT].u = tcs[UPRGT].u = (spr->cstat & CSTAT_SPRITE_XFLIP) ? 0.f : 1.f; + tcs[UPLFT].v = tcs[UPRGT].u = (spr->cstat & CSTAT_SPRITE_YFLIP) ? 0.f : 1.f; + tcs[LOLFT].v = tcs[LORGT].u = (spr->cstat & CSTAT_SPRITE_YFLIP) ? 0.f : 1.f; + ztop[0] = ztop[1] = (sprz - height) * (1 / -256.); + zbottom[0] = zbottom[1] = (sprz) * (1 / -256.); + + + // Clip sprites to ceilings/floors + float origz = ztop[0]; + float polyh = (zbottom[0] - origz); + if (!(sector->ceilingstat & CSTAT_SECTOR_SKY)) + { + float ceilingz = sector->ceilingz * (1 / 256.f); + if (ceilingz < ztop[0] && ceilingz > zbottom[0]) + { + float newv = (ceilingz - origz) / polyh; + tcs[UPLFT].v = tcs[UPRGT].v = newv; + ztop[0] = ztop[1] = ceilingz; + } + } + if (!(sector->floorstat & CSTAT_SECTOR_SKY)) + { + float floorz = sector->floorz * (1 / 256.f); + if (floorz < ztop[0] && floorz > zbottom[0]) + { + float newv = (floorz - origz) / polyh; + tcs[LOLFT].v = tcs[LORGT].v = newv; + zbottom[0] = zbottom[1] = floorz; + } + } +} \ No newline at end of file