diff --git a/source/core/gamestruct.h b/source/core/gamestruct.h index d176c1870..f32c9ac1d 100644 --- a/source/core/gamestruct.h +++ b/source/core/gamestruct.h @@ -103,7 +103,6 @@ struct GameInterface virtual int chaseCamY(binangle ang) { return 0; } virtual int chaseCamZ(fixedhoriz horiz) { return 0; } virtual void processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio) {} - virtual int SetupPortal(FRenderViewpoint& vp) { return -1; } virtual FString statFPS() { diff --git a/source/core/rendering/render.h b/source/core/rendering/render.h index f089a8c47..89eb28477 100644 --- a/source/core/rendering/render.h +++ b/source/core/rendering/render.h @@ -26,7 +26,7 @@ inline int portalAdd(int type, int target, int dx = 0, int dy = 0, int dz = 0) { auto& pt = allPortals[allPortals.Reserve(1)]; pt.type = type; - pt.targets.Push(target); + if (target >= 0) pt.targets.Push(target); pt.dx = dx; pt.dy = dy; pt.dz = dz; diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 117095b2d..9ab483aba 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -120,15 +120,6 @@ void BunchDrawer::DeleteBunch(int index) bool BunchDrawer::CheckClip(walltype* wal) { -#ifdef _DEBUG - if (wal - wall == 843 || wal - wall == 847) - { - int a = 0; - } -#endif - - - auto pt2 = &wall[wal->point2]; sectortype* backsector = §or[wal->nextsector]; sectortype* frontsector = §or[wall[wal->nextwall].nextsector]; @@ -137,10 +128,6 @@ bool BunchDrawer::CheckClip(walltype* wal) if (frontsector->ceilingstat & backsector->ceilingstat & CSTAT_SECTOR_SKY) return false; if (frontsector->floorstat & backsector->floorstat & CSTAT_SECTOR_SKY) return false; - // if we are in a sector portal, no two sided line may clip. - // originally this was achieved by temporarily altering the map geometry in the portal sectors. - if (portalState.insectorportal) return false; - float bs_floorheight1; float bs_floorheight2; float bs_ceilingheight1; diff --git a/source/core/rendering/scene/hw_portal.cpp b/source/core/rendering/scene/hw_portal.cpp index 165c72aef..70bad241f 100644 --- a/source/core/rendering/scene/hw_portal.cpp +++ b/source/core/rendering/scene/hw_portal.cpp @@ -814,20 +814,10 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c auto portal = origin; auto &vp = di->Viewpoint; - if (portal) - { - vp.Pos += DVector3(portal->dx / 16., portal->dy / -16., portal->dz / -256.); - vp.SectNums = portal->targets.Data(); - vp.SectCount = portal->targets.Size(); - type = origin->type; - } - else - { - if (state->renderdepth > 1) return false; // there is no way to make these portals recursive. - // Shadow Warrior's portals are too poorly defined so that the static approach won't work. - type = gi->SetupPortal(vp); - if (type == -1) return false; - } + vp.Pos += DVector3(portal->dx / 16., portal->dy / -16., portal->dz / -256.); + vp.SectNums = portal->targets.Data(); + vp.SectCount = portal->targets.Size(); + type = origin->type; state->insectorportal = true; // avoid recursions! diff --git a/source/core/rendering/scene/hw_sky.cpp b/source/core/rendering/scene/hw_sky.cpp index 01049b3aa..523657396 100644 --- a/source/core/rendering/scene/hw_sky.cpp +++ b/source/core/rendering/scene/hw_sky.cpp @@ -84,7 +84,7 @@ void HWWall::SkyPlane(HWDrawInfo *di, sectortype *sector, int plane, bool allowr if ((sector->portalflags == PORTAL_SECTOR_CEILING && plane == plane_ceiling) || (sector->portalflags == PORTAL_SECTOR_FLOOR && plane == plane_floor)) { if (screen->instack[1 - plane] || sector->portalnum >= (int)allPortals.Size()) return; - portal = sector->portalnum < 0? nullptr : &allPortals[sector->portalnum]; + portal = &allPortals[sector->portalnum]; PutPortal(di, PORTALTYPE_SECTORSTACK, plane); } else if ((sector->portalflags == PORTAL_SECTOR_CEILING_REFLECT && plane == plane_ceiling) || (sector->portalflags == PORTAL_SECTOR_FLOOR_REFLECT && plane == plane_floor)) diff --git a/source/games/sw/src/draw.cpp b/source/games/sw/src/draw.cpp index cac77fcba..38a0ae41a 100644 --- a/source/games/sw/src/draw.cpp +++ b/source/games/sw/src/draw.cpp @@ -1438,26 +1438,6 @@ void UpdateWallPortalState() } } } - - // The entire setup here is so catastrophically bad that we have to completely rely on the original information. - for (int i = 0; i < numsectors; i++) - { - if (sector[i].ceilingpicnum == FAF_MIRROR_PIC) - { - sector[i].portalflags = PORTAL_SECTOR_CEILING; - sector[i].portalnum = -1; - } - else if (sector[i].floorpicnum == FAF_MIRROR_PIC) - { - sector[i].portalflags = PORTAL_SECTOR_FLOOR; - sector[i].portalnum = -1; - } - else - { - sector[i].portalflags = 0; - sector[i].portalnum = -1; - } - } } diff --git a/source/games/sw/src/game.cpp b/source/games/sw/src/game.cpp index ec39e50a8..0a50d29a6 100644 --- a/source/games/sw/src/game.cpp +++ b/source/games/sw/src/game.cpp @@ -408,6 +408,7 @@ void InitLevel(MapRecord *maprec) PostSetupSectorObject(); SetupMirrorTiles(); initlava(); + CollectPortals(); // reset NewGame NewGame = false; diff --git a/source/games/sw/src/game.h b/source/games/sw/src/game.h index 0d70bd1a8..9d9c1115d 100644 --- a/source/games/sw/src/game.h +++ b/source/games/sw/src/game.h @@ -1969,21 +1969,14 @@ void SetOwner(short, short); void SetAttach(short, short); void analyzesprites(int,int,int,bool); void ChangeState(short SpriteNum, STATEp statep); +void CollectPortals(); -void UpdateSectorFAF_Connect(short SpriteNum, int newz); -#if 0 -bool FAF_ConnectCeiling(short sectnum); -bool FAF_ConnectFloor(short sectnum); -#else #define FAF_PLACE_MIRROR_PIC 341 #define FAF_MIRROR_PIC 2356 #define FAF_ConnectCeiling(sectnum) (sector[(sectnum)].ceilingpicnum == FAF_MIRROR_PIC) #define FAF_ConnectFloor(sectnum) (sector[(sectnum)].floorpicnum == FAF_MIRROR_PIC) #define FAF_ConnectArea(sectnum) (FAF_ConnectCeiling(sectnum) || FAF_ConnectFloor(sectnum)) -#endif -//void updatesectorz(int, int, int, short *); -void FAF_ConnectPlayerCeiling(PLAYERp pp); -void FAF_ConnectPlayerFloor(PLAYERp pp); + bool PlayerCeilingHit(PLAYERp pp, int zlimit); bool PlayerFloorHit(PLAYERp pp, int zlimit); @@ -2255,8 +2248,7 @@ struct GameInterface : ::GameInterface int chaseCamX(binangle ang) { return -ang.bcos(-3); } int chaseCamY(binangle ang) { return -ang.bsin(-3); } int chaseCamZ(fixedhoriz horiz) { return horiz.asq16() >> 8; } - int SetupPortal(FRenderViewpoint& vp) override; - + GameStats getStats() override; }; diff --git a/source/games/sw/src/rooms.cpp b/source/games/sw/src/rooms.cpp index 4f9d890b2..2d18da39a 100644 --- a/source/games/sw/src/rooms.cpp +++ b/source/games/sw/src/rooms.cpp @@ -689,7 +689,7 @@ GetUpperLowerSector(short match, int x, int y, short *upper, short *lower) int sln = 0; int SpriteNum; SPRITEp sp; - +#if 0 // keep a list of the last stacked sectors the view was in and // check those fisrt sln = 0; @@ -720,12 +720,13 @@ GetUpperLowerSector(short match, int x, int y, short *upper, short *lower) sln++; } } +#endif // didn't find it yet so test ALL sectors if (sln < 2) { sln = 0; - for (i = numsectors - 1; i >= 0; i--) + for (i = 0; i < numsectors; i++)// - 1; i >= 0; i--) { if (inside(x, y, (short) i) == 1) { @@ -1020,45 +1021,179 @@ FindViewSectorInScene(short cursectnum, short level) return -1; } -int GameInterface::SetupPortal(FRenderViewpoint &vp) +struct PortalGroup { - short i; - short match; + TArray sectors; + int othersector = -1; + vec3_t offset = { 0,0,0 }; +}; - save.zcount = 0; - int16_t tsectnum = int16_t(vp.SectNums == nullptr ? vp.SectCount : vp.SectNums[0]); - int tx = vp.Pos.X * 16; - int ty = vp.Pos.Y * -16; - int tz = vp.Pos.Z * -128; - int type = -1; - int looktype = -1; + // This is very messy because some portals are linked outside the actual portal sectors, so we have to use the complicated original linking logic to find the connection. :? +void CollectPortals() +{ + int t = testnewrenderer; + testnewrenderer = true; + TArray floorportals; + TArray ceilingportals; + FixedBitArray floordone, ceilingdone; - match = FindViewSectorInScene(tsectnum, VIEW_LEVEL1); - if (match != -1) + floordone.Zero(); + ceilingdone.Zero(); + + for (int i = 0; i < numsectors; i++) { - FindCeilingView(match, &tx, &ty, tz, &tsectnum); - type = PORTAL_SECTOR_CEILING; - - if (tsectnum < 0) - return -1; - } - else - { - match = FindViewSectorInScene(tsectnum, VIEW_LEVEL2); - if (match != -1) + if (sector[i].floorpicnum == FAF_MIRROR_PIC && !floordone[i]) { - FindFloorView(match, &tx, &ty, tz, &tsectnum); - type = PORTAL_SECTOR_FLOOR; - - if (tsectnum < 0) - return -1; - + auto& fp = floorportals[floorportals.Reserve(1)]; + fp.sectors.Push(i); + floordone.Set(i); + for (unsigned ii = 0; ii < fp.sectors.Size(); ii++) + { + auto sec = §or[fp.sectors[ii]]; + for (int w = 0; w < sec->wallnum; w++) + { + auto ns = wall[sec->wallptr + w].nextsector; + if (ns < 0 || floordone[ns] || sector[ns].floorpicnum != FAF_MIRROR_PIC) continue; + fp.sectors.Push(ns); + floordone.Set(ns); + } + } + } + if (sector[i].ceilingpicnum == FAF_MIRROR_PIC && !ceilingdone[i]) + { + auto& fp = ceilingportals[ceilingportals.Reserve(1)]; + fp.sectors.Push(i); + ceilingdone.Set(i); + for (unsigned ii = 0; ii < fp.sectors.Size(); ii++) + { + auto sec = §or[fp.sectors[ii]]; + for (int w = 0; w < sec->wallnum; w++) + { + auto ns = wall[sec->wallptr + w].nextsector; + if (ns < 0 || ceilingdone[ns] || sector[ns].ceilingpicnum != FAF_MIRROR_PIC) continue; + fp.sectors.Push(ns); + ceilingdone.Set(ns); + } + } } } - vp.Pos = { tx / 16.f, ty / -16.f, tz / -128.f }; - vp.SectNums = nullptr; - vp.SectCount = tsectnum; - return type; + // now try to find connections. + for (auto& fp : ceilingportals) + { + // pick one sprite out of the sectors, repeat until we get a valid connection + for (auto sec : fp.sectors) + { + SectIterator it(sec); + int spr; + while ((spr = it.NextIndex()) >= 0) + { + int tx = sprite[spr].x; + int ty = sprite[spr].y; + int tz = sprite[spr].z; + int16_t tsectnum = sec; + + int match = FindViewSectorInScene(tsectnum, VIEW_LEVEL1); + if (match != -1) + { + FindCeilingView(match, &tx, &ty, tz, &tsectnum); + if (tsectnum >= 0 && sector[tsectnum].floorpicnum == FAF_MIRROR_PIC) + { + // got something! + fp.othersector = tsectnum; + fp.offset = { tx, ty, tz }; + fp.offset -= sprite[spr].pos; + goto nextfg; + } + } + } + } + nextfg:; + } + + for (auto& fp : floorportals) + { + for (auto sec : fp.sectors) + { + SectIterator it(sec); + int spr; + while ((spr = it.NextIndex()) >= 0) + { + int tx = sprite[spr].x; + int ty = sprite[spr].y; + int tz = sprite[spr].z; + int16_t tsectnum = sec; + + int match = FindViewSectorInScene(tsectnum, VIEW_LEVEL2); + if (match != -1) + { + FindFloorView(match, &tx, &ty, tz, &tsectnum); + if (tsectnum >= 0 && sector[tsectnum].ceilingpicnum == FAF_MIRROR_PIC) + { + // got something! + fp.othersector = tsectnum; + fp.offset = { tx, ty, tz }; + fp.offset -= sprite[spr].pos; + goto nextcg; + } + } + } + } + nextcg:; + } + for (auto& pt : floorportals) + { + if (pt.othersector > -1) + { + auto findother = [&](int other) -> PortalGroup* + { + for (auto& pt2 : ceilingportals) + { + if (pt2.sectors.Find(other) != pt2.sectors.Size()) return &pt2; + } + return nullptr; + }; + + auto pt2 = findother(pt.othersector); + if (pt2) + { + int pnum = portalAdd(PORTAL_SECTOR_FLOOR, -1, pt.offset.x, pt.offset.y, 0); + allPortals[pnum].targets = pt2->sectors; // do not move! We still need the original. + for (auto sec : pt.sectors) + { + sector[sec].portalflags = PORTAL_SECTOR_FLOOR; + sector[sec].portalnum = pnum; + } + } + } + } + for (auto& pt : ceilingportals) + { + if (pt.othersector > -1) + { + auto findother = [&](int other) -> PortalGroup* + { + for (auto& pt2 : floorportals) + { + if (pt2.sectors.Find(other) != pt2.sectors.Size()) return &pt2; + } + return nullptr; + }; + + auto pt2 = findother(pt.othersector); + if (pt2) + { + int pnum = portalAdd(PORTAL_SECTOR_FLOOR, -1, pt.offset.x, pt.offset.y, 0); + allPortals[pnum].targets = std::move(pt2->sectors); + for (auto sec : pt.sectors) + { + sector[sec].portalflags = PORTAL_SECTOR_CEILING; + sector[sec].portalnum = pnum; + } + } + } + } + testnewrenderer = false; } + END_SW_NS