diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 185bbe62b..ffc0ebcb7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1060,6 +1060,7 @@ set (PCH_SOURCES common/utility/r_memory.cpp common/utility/bounds.cpp common/utility/writezip.cpp + common/utility/vga2ansi.cpp common/thirdparty/base64.cpp common/thirdparty/md5.cpp common/thirdparty/superfasthash.cpp diff --git a/src/common/console/c_enginecmds.cpp b/src/common/console/c_enginecmds.cpp index d6a2e027e..36a27cadf 100644 --- a/src/common/console/c_enginecmds.cpp +++ b/src/common/console/c_enginecmds.cpp @@ -58,13 +58,16 @@ extern FILE* Logfile; +void ConsoleEndoom(); CCMD (quit) { + ConsoleEndoom(); throw CExitEvent(0); } CCMD (exit) { + ConsoleEndoom(); throw CExitEvent(0); } diff --git a/src/common/engine/st_start.h b/src/common/engine/st_start.h index 9db728e33..11d07849d 100644 --- a/src/common/engine/st_start.h +++ b/src/common/engine/st_start.h @@ -50,7 +50,7 @@ public: virtual ~FStartupScreen() = default; - virtual void Progress() {} + virtual void Progress(int advance = 1) {} virtual void AppendStatusLine(const char* status) {} virtual void LoadingStatus(const char* message, int colors) {} @@ -77,7 +77,7 @@ public: FBasicStartupScreen(int max_progress); ~FBasicStartupScreen(); - void Progress() override; + void Progress(int advance = 1) override; void NetInit(const char* message, bool host) override; void NetMessage(const char* message) override; diff --git a/src/common/platform/posix/cocoa/st_start.mm b/src/common/platform/posix/cocoa/st_start.mm index 87eae4b4f..fe1d0df68 100644 --- a/src/common/platform/posix/cocoa/st_start.mm +++ b/src/common/platform/posix/cocoa/st_start.mm @@ -84,13 +84,9 @@ FBasicStartupScreen::~FBasicStartupScreen() } -void FBasicStartupScreen::Progress() +void FBasicStartupScreen::Progress(int advance) { - if (CurPos < MaxPos) - { - ++CurPos; - } - + CurPos = min(CurPos + advance, MaxPos); FConsoleWindow::GetInstance().Progress(CurPos, MaxPos); } diff --git a/src/common/platform/posix/sdl/i_system.cpp b/src/common/platform/posix/sdl/i_system.cpp index 5999c96af..897808158 100644 --- a/src/common/platform/posix/sdl/i_system.cpp +++ b/src/common/platform/posix/sdl/i_system.cpp @@ -220,10 +220,15 @@ void CleanProgressBar() } static int ProgressBarCurPos, ProgressBarMaxPos; +static bool ProgressBarComplete; void RedrawProgressBar(int CurPos, int MaxPos) { if (!isatty(STDOUT_FILENO)) return; + + if (ProgressBarComplete && CurPos >= MaxPos) return; + ProgressBarComplete = CurPos >= MaxPos; // draw once + CleanProgressBar(); struct winsize sizeOfWindow; ioctl(STDOUT_FILENO, TIOCGWINSZ, &sizeOfWindow); diff --git a/src/common/platform/posix/sdl/st_start.cpp b/src/common/platform/posix/sdl/st_start.cpp index b1f0914a6..4653f4ff9 100644 --- a/src/common/platform/posix/sdl/st_start.cpp +++ b/src/common/platform/posix/sdl/st_start.cpp @@ -53,7 +53,7 @@ class FTTYStartupScreen : public FStartupScreen FTTYStartupScreen(int max_progress); ~FTTYStartupScreen(); - void Progress() override; + void Progress(int amount = 1) override; void NetInit(const char* message, bool host) override; void NetMessage(const char* message) override; @@ -137,12 +137,9 @@ FTTYStartupScreen::~FTTYStartupScreen() // //=========================================================================== -void FTTYStartupScreen::Progress() +void FTTYStartupScreen::Progress(int advance) { - if (CurPos < MaxPos) - { - ++CurPos; - } + CurPos = min(CurPos + advance, MaxPos); RedrawProgressBar(CurPos, MaxPos); } @@ -240,6 +237,7 @@ void FTTYStartupScreen::NetProgress(int cur, int limit) void FTTYStartupScreen::NetDone() { + CurPos = MaxPos; CleanProgressBar(); // Restore stdin settings if (DidNetInit) diff --git a/src/common/platform/win32/st_start.cpp b/src/common/platform/win32/st_start.cpp index 99e2d050c..f74aca3ae 100644 --- a/src/common/platform/win32/st_start.cpp +++ b/src/common/platform/win32/st_start.cpp @@ -115,12 +115,9 @@ FBasicStartupScreen::~FBasicStartupScreen() // //========================================================================== -void FBasicStartupScreen::Progress() +void FBasicStartupScreen::Progress(int advance) { - if (CurPos < MaxPos) - { - CurPos++; - } + CurPos = min(CurPos + advance, MaxPos); } //========================================================================== diff --git a/src/common/startscreen/endoom.cpp b/src/common/startscreen/endoom.cpp index 649c1362d..b4e8a4026 100644 --- a/src/common/startscreen/endoom.cpp +++ b/src/common/startscreen/endoom.cpp @@ -73,6 +73,12 @@ CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) else if (self > 2) self=2; } +CVAR(Bool, consoleendoom, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) + +#ifdef _WIN32 +extern bool FancyStdOut; +#endif + // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- @@ -192,9 +198,36 @@ int RunEndoom() return 0; } +void vga_to_ansi(const uint8_t *buf); + +void ConsoleEndoom() +{ +#ifdef _WIN32 + // old versions of Windows don't get an ansi endoom + if (!FancyStdOut) + return; +#endif + + if (!consoleendoom || endoomName.Len() == 0) + return; + + uint8_t buffer[4000]; + + int endoom_lump = fileSystem.CheckNumForFullName (endoomName.GetChars(), true); + + if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000) + { + return; + } + fileSystem.ReadFile(endoom_lump, buffer); + + vga_to_ansi(buffer); +} + [[noreturn]] void ST_Endoom() { + ConsoleEndoom(); int code = RunEndoom(); throw CExitEvent(code); } diff --git a/src/common/startscreen/startscreen.cpp b/src/common/startscreen/startscreen.cpp index 40c8589aa..f65b3664e 100644 --- a/src/common/startscreen/startscreen.cpp +++ b/src/common/startscreen/startscreen.cpp @@ -765,3 +765,33 @@ void FStartScreen::ValidateTexture() } } +void unicode_to_utf8(char* result, uint16_t code_point) +{ + if (code_point <= 0x7F) + { + // 1-byte sequence (ASCII) + result[0] = (unsigned char)code_point; + result[1] = 0; + } + else if (code_point <= 0x7FF) + { + // 2-byte sequence + result[0] = (unsigned char)(0xC0 | ((code_point >> 6) & 0x1F)); + result[1] = (unsigned char)(0x80 | (code_point & 0x3F)); + result[2] = 0; + } + else + { + // 3-byte sequence (up to U+FFFF) + result[0] = (unsigned char)(0xE0 | ((code_point >> 12) & 0x0F)); + result[1] = (unsigned char)(0x80 | ((code_point >> 6) & 0x3F)); + result[2] = (unsigned char)(0x80 | (code_point & 0x3F)); + result[3] = 0; + } +} + +void ibm437_to_utf8(char* result, char in) +{ + unicode_to_utf8(result, IBM437ToUnicode[(unsigned char)in]); +} + diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h index 148b7e31a..2ab989280 100644 --- a/src/common/utility/tarray.h +++ b/src/common/utility/tarray.h @@ -405,7 +405,7 @@ public: // exact = false returns the closest match, to be used for, ex., insertions, exact = true returns Size() when no match, like Find does unsigned int SortedFind(const T& item, bool exact = true) const { - unsigned int index = (std::lower_bound(begin(), end(), item) - begin()); + unsigned int index = (unsigned int)(std::lower_bound(begin(), end(), item) - begin()); if(exact) { return (index < Count && Array[index] == item) ? index : Count; diff --git a/src/common/utility/vga2ansi.cpp b/src/common/utility/vga2ansi.cpp new file mode 100644 index 000000000..6553e6e3b --- /dev/null +++ b/src/common/utility/vga2ansi.cpp @@ -0,0 +1,158 @@ +// Copyright (c) 2025 Rachael Alexanderson +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include + +#ifdef _WIN32 +// windows platform code uses special stdout handling, let's make sure to use that +#include +extern HANDLE StdOut; +static void CPrint(const char* in) +{ + DWORD bytes_written; + if (!StdOut) + return; + WriteFile(StdOut, in, strlen(in), &bytes_written, NULL); +} +#else +static void CPrint(const char* in) +{ + fputs(in, stdout); +} +#endif + +static const char *ansi_esc[2] = {"\x1b[", ";"}; +static const char *ansi_end[2] = {"", "m"}; + +// Map DOS color to ANSI escape code +static const char *ansi_fg[16] = +{ + "30", "34", "32", "36", "31", "35", "33", "37", + "90", "94", "92", "96", "91", "95", "93", "97" +}; +// Only standard backgrounds (no bright backgrounds in classic ANSI) +static const char *ansi_bg[8] = +{ + "40", "44", "42", "46", + "41", "45", "43", "47" +}; +// ANSI codes for truecolor DOS colors +static const char *ansi_tc_fg[16] = +{ + "38;2;0;0;0", "38;2;0;0;170", "38;2;0;170;0", "38;2;0;170;170", + "38;2;170;0;0", "38;2;170;0;170", "38;2;170;85;0", "38;2;170;170;170", + "38;2;85;85;85", "38;2;85;85;255", "38;2;85;255;0", "38;2;85;255;255", + "38;2;255;85;85", "38;2;255;85;255", "38;2;255;255;85", "38;2;255;255;255" +}; +static const char *ansi_tc_bg[8] = +{ + "48;2;0;0;0", "48;2;0;0;170", "48;2;0;170;0", "48;2;0;170;170", + "48;2;170;0;0", "48;2;170;0;170", "48;2;170;85;0", "48;2;170;170;170" +}; + +static const char *ansi_flash[2] = { "25", "5" }; + +inline void ansi_ctrl(bool open) +{ + static bool is_ansi_open = false; + if (open) + CPrint(ansi_esc[is_ansi_open]); + else + CPrint(ansi_end[is_ansi_open]); + is_ansi_open = open; +} + +void ibm437_to_utf8(char* result, char in); + +void vga_to_ansi(const uint8_t *buf) +{ +#ifdef _WIN32 + bool truecolor = true; +#else + const char *ct = getenv("COLORTERM"); + bool truecolor = ct && (strcmp(ct, "truecolor") || strcmp(ct, "24bit")); +#endif + + for (int row = 0; row < 25; ++row) + { + int last_fg = -1, last_bg = -1; + bool last_blink = false; + for (int col = 0; col < 80; ++col) + { + int off = (row * 80 + col) * 2; + uint8_t ch = buf[off]; + uint8_t attr = buf[off + 1]; + int fg = attr & 0x0F; + int bg = (attr >> 4) & 0x07; + bool blink = !!(attr & 0x80); + bool spacer = (ch == 0) || (ch == 32) || (ch == 255); + + // Output color if changed + if ((fg != last_fg) && !spacer) + { + ansi_ctrl(1); + if (truecolor) + CPrint(ansi_tc_fg[fg]); + else + CPrint(ansi_fg[fg]); + last_fg = fg; + } + if (bg != last_bg) + { + ansi_ctrl(1); + if (truecolor) + CPrint(ansi_tc_bg[bg]); + else + CPrint(ansi_bg[bg]); + last_bg = bg; + } + if (blink != last_blink) + { + ansi_ctrl(1); + CPrint(ansi_flash[blink]); + last_blink = blink; + } + ansi_ctrl(0); + + // Output character, convert CP437 to UTF-8 + if (spacer) + CPrint(" "); + else + { + char result[4]; + ibm437_to_utf8(result, ch); + CPrint(result); + } + } + CPrint("\x1b[0m\n"); // Reset colors and end the line + } +} + diff --git a/src/d_main.cpp b/src/d_main.cpp index aaaeb13ce..7f4d57b2d 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -3420,7 +3420,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector& allw if (!batchrun && !RunningAsTool) Printf ("ST_Init: Init startup screen.\n"); if (!restart) { - StartWindow = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5); + StartWindow = FStartupScreen::CreateInstance(max_progress); } else { @@ -3635,10 +3635,12 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector& allw } S_Sound (CHAN_BODY, 0, "misc/startupdone", 1, ATTN_NONE); + if (!batchrun) Printf ("Init complete.\n"); if (RunningAsTool) return 0; + StartWindow->Progress(max_progress); if (StartScreen) { StartScreen->Progress(max_progress); // advance progress bar to the end. @@ -3916,7 +3918,7 @@ int D_DoomMain_Game() // Now that we have the IWADINFO, initialize the autoload ini sections. GameConfig->DoAutoloadSetup(iwad_man); - bool should_debug = vm_debug.get(); + bool should_debug = vm_debug; const char * debug_port_arg = Args->CheckValue("-debug"); if (debug_port_arg) { should_debug = true; diff --git a/src/g_dumpinfo.cpp b/src/g_dumpinfo.cpp index 73f7b9e1b..f8cadeaea 100644 --- a/src/g_dumpinfo.cpp +++ b/src/g_dumpinfo.cpp @@ -76,31 +76,12 @@ CCMD(listlights) if (dl->target) { FTextureID spr = sprites[dl->target->sprite].GetSpriteFrame(dl->target->frame, 0, nullAngle, nullptr); - Printf(", frame = %s ", TexMan.GetGameTexture(spr)->GetName().GetChars()); + Printf(", frame = %s\n", TexMan.GetGameTexture(spr)->GetName().GetChars()); } - - FLightNode * node; - - node=dl->touching_sides; - - while (node) - { - walls++; - allwalls++; - node = node->nextTarget; - } - - - node = dl->touching_sector; - - while (node) - { - allsectors++; - sectors++; - node = node->nextTarget; - } + /* Printf("- %d walls, %d sectors\n", walls, sectors); + */ } Printf("%i dynamic lights, %d shadowmapped, %d walls, %d sectors\n\n\n", i, shadowcount, allwalls, allsectors); diff --git a/src/g_level.cpp b/src/g_level.cpp index 417891b9f..78cb97138 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -583,6 +583,9 @@ void G_InitNew (const char *mapname, bool bTitleLevel) bool wantFast; unsigned int i; + primaryLevel->lightlists.wall_dlist.Clear(); + primaryLevel->lightlists.flat_dlist.Clear(); + // did we have any level before? if (primaryLevel->info != nullptr) staticEventManager.WorldUnloaded(FString()); // [MK] don't pass the new map, as it's not a level transition @@ -647,9 +650,6 @@ void G_InitNew (const char *mapname, bool bTitleLevel) primaryLevel->totaltime = 0; primaryLevel->spawnindex = 0; - primaryLevel->lightlists.wall_dlist.Clear(); - primaryLevel->lightlists.flat_dlist.Clear(); - if (!multiplayer || !deathmatch) { InitPlayerClasses (); diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 3fdac27bb..4a1b4983f 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -61,8 +61,9 @@ struct FGlobalDLightLists { - TMap>> flat_dlist; - TMap>> wall_dlist; + //TODO add TSet and switch from TMap to TSet + TArray>> flat_dlist; + TArray>> wall_dlist; }; #include "common/rendering/hwrenderer/data/hw_lightprobe.h" diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index 1926deb96..756d326cc 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -3517,12 +3517,6 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) SpawnThings(position); - // Load and link lightmaps - must be done after P_Spawn3DFloors (and SpawnThings? Potentially for baking static model actors?) - if (!ForceNodeBuild) - { - LoadLightmap(map); - } - for (unsigned int i = 0; i < MAXPLAYERS; ++i) { if (Level->PlayerInGame(i) && Level->Players[i]->mo != nullptr) diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 00724de8c..2728c321d 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -74,20 +74,22 @@ static FCRandom randLight; extern TArray StateLights; -static void MarkTilesForUpdate(FLevelLocals * Level, FLightNode * touching_sides, FLightNode * touching_sector) +void FDynamicLight::MarkTilesForUpdate() { if(Level->levelMesh) { - while(touching_sides) + for (int i = 0; i < touchlists.wall_tlist.SSize(); i++) { - LevelMeshUpdater->SideLightListChanged(touching_sides->targLine); - touching_sides = touching_sides->nextTarget; + auto sidedef = touchlists.wall_tlist[i]; + if (sidedef) + LevelMeshUpdater->SideLightListChanged(sidedef); } - - while(touching_sector) + + for (int i = 0; i < touchlists.flat_tlist.SSize(); i++) { - LevelMeshUpdater->SectorLightListChanged(touching_sector->targSection->sector); - touching_sector = touching_sector->nextTarget; + auto sec = touchlists.flat_tlist[i]; + if (sec) + LevelMeshUpdater->SectorLightListChanged(sec->sector); } } } @@ -315,7 +317,7 @@ void FDynamicLight::Tick() { if(markTiles && m_active != wasactive) { - MarkTilesForUpdate(Level, touching_sides, touching_sector); + MarkTilesForUpdate(); } wasactive = m_active; return; @@ -418,7 +420,7 @@ void FDynamicLight::Tick() { if(markTiles) { - MarkTilesForUpdate(Level, touching_sides, touching_sector); + MarkTilesForUpdate(); } updated = true; @@ -521,69 +523,48 @@ bool FDynamicLight::UpdateLocation() // //============================================================================= + +int FSection::Index() const +{ + return int(this - §or->Level->sections.allSections[0]); +} + void FDynamicLight::AddLightNode(FSection *section, side_t *sidedef) { - auto updateFlatTList = [&](FSection *sec) - { - touchlists.flat_tlist.TryEmplace(sec, sec); - }; - auto updateWallTList = [&](side_t *sidedef) - { - touchlists.wall_tlist.TryEmplace(sidedef, sidedef); - }; - if (section) { - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(section); - if (flatLightList) + if(Level->lightlists.flat_dlist.SSize() <= section->Index()) { - if (!flatLightList->CheckKey(this)) - { - FLightNode * node = new FLightNode; - node->lightsource = this; - node->targ = section; - - flatLightList->TryEmplace(this, node); - updateFlatTList(section); - } + Level->lightlists.flat_dlist.Resize(section->Index() + 1); } - else + + auto &flatLightList = Level->lightlists.flat_dlist[section->Index()]; + + if (!flatLightList.CheckKey(this)) { FLightNode * node = new FLightNode; node->lightsource = this; - node->targ = section; - TMap> u; - u.TryEmplace(this, node); - Level->lightlists.flat_dlist.TryEmplace(section, std::move(u)); - updateFlatTList(section); + flatLightList.TryEmplace(this, node); + touchlists.flat_tlist.SortedAddUnique(section); } } else if (sidedef) { - auto wallLightList = Level->lightlists.wall_dlist.CheckKey(sidedef); - if (wallLightList) + if(Level->lightlists.wall_dlist.SSize() <= sidedef->Index()) { - if (!wallLightList->CheckKey(this)) - { - FLightNode * node = new FLightNode; - node->lightsource = this; - node->targ = sidedef; - - wallLightList->TryEmplace(this, node); - updateWallTList(sidedef); - } + Level->lightlists.wall_dlist.Resize(sidedef->Index() + 1); } - else + + auto &wallLightList = Level->lightlists.wall_dlist[sidedef->Index()]; + + if (!wallLightList.CheckKey(this)) { FLightNode * node = new FLightNode; node->lightsource = this; - node->targ = sidedef; - TMap> u; - u.TryEmplace(this, node); - Level->lightlists.wall_dlist.TryEmplace(sidedef, std::move(u)); - updateWallTList(sidedef); + wallLightList.TryEmplace(this, node); + touchlists.wall_tlist.SortedAddUnique(sidedef); } } } @@ -768,7 +749,6 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, void FDynamicLight::LinkLight() { UnlinkLight(); - if (radius>0) { // passing in radius*radius allows us to do a distance check without any calls to sqrt @@ -786,35 +766,29 @@ void FDynamicLight::LinkLight() // Deletes the link lists // //========================================================================== -void FDynamicLight::UnlinkLight () +void FDynamicLight::UnlinkLight() { - TMap::Iterator wit(touchlists.wall_tlist); - TMap::Pair *wpair; - while (wit.NextPair(wpair)) + for(int i = 0; i < touchlists.wall_tlist.SSize(); i++) { - auto sidedef = wpair->Value; + auto sidedef = touchlists.wall_tlist[i]; if (!sidedef) continue; - auto wallLightList = Level->lightlists.wall_dlist.CheckKey(sidedef); - if (wallLightList) + if(Level->lightlists.wall_dlist.SSize() > sidedef->Index()) { LevelMeshUpdater->SideLightListChanged(sidedef); - wallLightList->Remove(this); + Level->lightlists.wall_dlist[sidedef->Index()].Remove(this); } } - TMap::Iterator fit(touchlists.flat_tlist); - TMap::Pair *fpair; - while (fit.NextPair(fpair)) + for(int i = 0; i < touchlists.flat_tlist.SSize(); i++) { - auto sec = fpair->Value; + auto sec = touchlists.flat_tlist[i]; if (!sec) continue; - - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sec); - if (flatLightList) + + if(Level->lightlists.flat_dlist.SSize() > sec->Index()) { LevelMeshUpdater->SectorLightListChanged(sec->sector); - flatLightList->Remove(this); + Level->lightlists.flat_dlist[sec->Index()].Remove(this); } } diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index 6dba1cf10..06fabff87 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -196,23 +196,13 @@ protected: struct FLightNode { - FLightNode ** prevTarget; - FLightNode * nextTarget; - FLightNode ** prevLight; - FLightNode * nextLight; FDynamicLight * lightsource; - union - { - side_t * targLine; - FSection* targSection; - void * targ; - }; }; struct FDynamicLightTouchLists { - TMap flat_tlist; - TMap wall_tlist; + TArray flat_tlist; + TArray wall_tlist; }; struct FDynamicLight @@ -279,6 +269,7 @@ struct FDynamicLight private: double DistToSeg(const DVector3 &pos, vertex_t *start, vertex_t *end); void CollectWithinRadius(const DVector3 &pos, FSection *section, float radius); + void MarkTilesForUpdate(); public: FCycler m_cycler; @@ -301,8 +292,7 @@ public: sector_t *Sector; FLevelLocals *Level; TObjPtr target; - FLightNode * touching_sides; - FLightNode * touching_sector; + float radius; // The maximum size the light can be with its current settings. float m_currentRadius; // The current light size. int m_tickCount; diff --git a/src/r_data/r_sections.h b/src/r_data/r_sections.h index d844d2d18..9de145615 100644 --- a/src/r_data/r_sections.h +++ b/src/r_data/r_sections.h @@ -120,6 +120,8 @@ struct FSection short mapsection; char hacked; // 1: is part of a render hack char flags; + + int Index() const; }; class FSectionContainer diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 19aa2c93f..bcb64f434 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -1046,7 +1046,7 @@ void DoomLevelMesh::UpdateLightShadows(sector_t* sector) { for (FSection& section : level.sections.SectionsForSector(sector)) { - auto flatLightList = level.lightlists.flat_dlist.CheckKey(§ion); + auto flatLightList = level.lightlists.flat_dlist.SSize() > section.Index() ? &level.lightlists.flat_dlist[section.Index()] : nullptr; if (flatLightList) { TMap>::Iterator it(*flatLightList); @@ -1066,18 +1066,18 @@ void DoomLevelMesh::UpdateLightShadows(sector_t* sector) void DoomLevelMesh::UpdateLightShadows(FDynamicLight* light) { - auto touching_sector = light->touching_sector; - while (touching_sector) + for (int i = 0; i < light->touchlists.flat_tlist.SSize(); i++) { - UpdateFlat(touching_sector->targSection->sector->Index(), SurfaceUpdateType::LightList); - touching_sector = touching_sector->nextTarget; + auto sec = light->touchlists.flat_tlist[i]; + if (sec) + UpdateFlat(sec->sector->Index(), SurfaceUpdateType::LightList); } - auto touching_sides = light->touching_sides; - while (touching_sides) + for (int i = 0; i < light->touchlists.wall_tlist.SSize(); i++) { - UpdateSide(touching_sides->targLine->Index(), SurfaceUpdateType::LightList); - touching_sides = touching_sides->nextTarget; + auto sidedef = light->touchlists.wall_tlist[i]; + if (sidedef) + UpdateSide(sidedef->Index(), SurfaceUpdateType::LightList); } } @@ -1315,9 +1315,13 @@ void DoomLevelMesh::UpdateFlat(unsigned int sectorIndex, SurfaceUpdateType updat LightListAllocInfo DoomLevelMesh::CreateLightList(FSection* section, side_t* side, int portalgroup) { - int lightcount = 0; + TMap>* srcLightList = nullptr; + if (section && level.lightlists.flat_dlist.SSize() > section->Index()) + srcLightList = &level.lightlists.flat_dlist[section->Index()]; + else if (side && level.lightlists.wall_dlist.SSize() > side->Index()) + srcLightList = &level.lightlists.wall_dlist[side->Index()]; - auto srcLightList = section ? level.lightlists.flat_dlist.CheckKey(section) : level.lightlists.wall_dlist.CheckKey(side); + int lightcount = 0; if (srcLightList) { TMap>::Iterator it(*srcLightList); diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index aaf7098e0..4f4243f59 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -270,6 +270,8 @@ void HWDrawInfo::UnclipSubsector(subsector_t *sub) void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) { + const bool doOob = Viewpoint.bDoOob; + #ifdef _DEBUG if (seg->linedef && seg->linedef->Index() == 38) { @@ -293,7 +295,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) angle_t endAngleR = 0; angle_t paddingR = 0x00200000; // Make radar clipping more aggressive (reveal less) - if(Viewpoint.IsAllowedOoB() && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR)) + if(doOob && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR)) { startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY()); endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); @@ -321,11 +323,11 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) { if (!(currentsubsector->flags & SSECMF_DRAWN)) { - if (clipper.SafeCheckRange(startAngle, endAngle) && !Viewpoint.IsAllowedOoB()) + if (clipper.SafeCheckRange(startAngle, endAngle) && !doOob) { currentsubsector->flags |= SSECMF_DRAWN; } - if (Viewpoint.IsAllowedOoB() && (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR)) && clipperr.SafeCheckRange(startAngleR, endAngleR)) + if (doOob && (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR)) && clipperr.SafeCheckRange(startAngleR, endAngleR)) { currentsubsector->flags |= SSECMF_DRAWN; } @@ -338,14 +340,14 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) return; } - if (!Viewpoint.IsAllowedOoB() || (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR))) + if (!doOob || (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR))) currentsubsector->flags |= SSECMF_DRAWN; uint8_t ispoly = uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ); if (!seg->backsector) { - if(!Viewpoint.IsAllowedOoB()) + if(!doOob) if (!(seg->sidedef->Flags & WALLF_DITHERTRANS_MID)) clipper.SafeAddClipRange(startAngle, endAngle); } else if (!ispoly) // Two-sided polyobjects never obstruct the view @@ -373,7 +375,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) if (hw_CheckClip(seg->sidedef, currentsector, backsector, !outer ? &ClipFrustum : nullptr)) { - if(!Viewpoint.IsAllowedOoB() && !(seg->sidedef->Flags & WALLF_DITHERTRANS_MID)) + if(!doOob && !(seg->sidedef->Flags & WALLF_DITHERTRANS_MID)) clipper.SafeAddClipRange(startAngle, endAngle); } } @@ -590,7 +592,7 @@ void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector, FRenderState if (thing->validcount == validcount) continue; thing->validcount = validcount; - if(Viewpoint.IsAllowedOoB() && thing->Sector->isSecret() && thing->Sector->wasSecret() && !r_radarclipper) continue; // This covers things that are touching non-secret sectors + if(Viewpoint.bDoOob && thing->Sector->isSecret() && thing->Sector->wasSecret() && !r_radarclipper) continue; // This covers things that are touching non-secret sectors FIntCVar *cvar = thing->GetInfo()->distancecheck; if (cvar != nullptr && *cvar >= 0) { @@ -695,6 +697,7 @@ void HWDrawInfo::RenderParticles(subsector_t *sub, sector_t *front, FRenderState void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) { + const bool doOob = Viewpoint.bDoOob; sector_t * sector; sector_t * fakesector; @@ -723,10 +726,10 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) fakesector=hw_FakeFlat(drawctx, sector, in_area, false); - if(Viewpoint.IsAllowedOoB() && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return; + if(doOob && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return; // cull everything if subsector outside all relevant clippers - if (Viewpoint.IsAllowedOoB() && (sub->polys == nullptr)) + if (doOob && (sub->polys == nullptr)) { auto &clipper = *mClipper; auto &clipperv = *vClipper; @@ -734,11 +737,10 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) int count = sub->numlines; seg_t * seg = sub->firstline; bool anglevisible = false; - bool pitchvisible = !(Viewpoint.IsAllowedOoB()); // No vertical clipping if viewpoint is not allowed out of bounds - bool radarvisible = !(Viewpoint.IsAllowedOoB()) || !r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch); - bool ceilreflect = (mCurrentPortal && strcmp(mCurrentPortal->GetName(), "Planemirror ceiling")); - bool floorreflect = (mCurrentPortal && strcmp(mCurrentPortal->GetName(), "Planemirror floor")); - double planez = (ceilreflect ? sector->ceilingplane.ZatPoint(Viewpoint.Pos) : sector->floorplane.ZatPoint(Viewpoint.Pos)); + bool pitchvisible = false; + bool radarvisible = !r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch); + const int reflect = mCurrentPortal ? mCurrentPortal->GetMirrorSide() : 0; // -1 = ceiling, 1 = floor, 0 = none + const double planez = (reflect < 0 ? sector->ceilingplane.ZatPoint(Viewpoint.Pos) : sector->floorplane.ZatPoint(Viewpoint.Pos)); angle_t pitchtemp; angle_t pitchmin = ANGLE_90; angle_t pitchmax = 0; @@ -763,11 +765,11 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) if (!pitchvisible) { pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), - (ceilreflect || floorreflect) ? + (reflect != 0) ? 2 * planez - sector->floorplane.ZatPoint(seg->v1) : sector->floorplane.ZatPoint(seg->v1)); pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), - (ceilreflect || floorreflect) ? + (reflect != 0) ? 2 * planez - sector->ceilingplane.ZatPoint(seg->v1) : sector->ceilingplane.ZatPoint(seg->v1)); pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax); @@ -776,12 +778,12 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) if (!pitchvisible) { pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), - (ceilreflect || floorreflect) ? + (reflect != 0) ? 2 * planez - sector->floorplane.ZatPoint(seg->v2) : sector->floorplane.ZatPoint(seg->v2)); if (int(pitchmin) > int(pitchtemp)) pitchmin = pitchtemp; pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), - (ceilreflect || floorreflect) ? + (reflect != 0) ? 2 * planez - sector->ceilingplane.ZatPoint(seg->v2) : sector->ceilingplane.ZatPoint(seg->v2)); if (int(pitchmax) < int(pitchtemp)) pitchmax = pitchtemp; @@ -852,7 +854,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) SetupSprite.Unclock(); } } - if (r_dithertransparency && Viewpoint.IsAllowedOoB() && (RTnum < MAXDITHERACTORS) && mCurrentPortal == nullptr) + if (r_dithertransparency && doOob && (RTnum < MAXDITHERACTORS) && mCurrentPortal == nullptr) { // [DVR] Not parallelizable due to variables RTnum and RenderedTargets[] for (auto p = sector->touching_renderthings; p != nullptr; p = p->m_snext) @@ -999,7 +1001,7 @@ void HWDrawInfo::RenderBSPNode (void *node, FRenderState& state) if (!(no_renderflags[bsp->Index()] & SSRF_SEEN)) return; } - if (Viewpoint.IsOrtho()) + if (Viewpoint.bDoOrtho) { if (!vClipper->CheckBoxOrthoPitch(bsp->bbox[side])) { @@ -1016,7 +1018,7 @@ void HWDrawInfo::RenderBSPNode (void *node, FRenderState& state) // No need for clipping inside frustum if no fog of war (How is this faster!) void HWDrawInfo::RenderOrthoNoFog(FRenderState& state) { - if (Viewpoint.IsOrtho() && ((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper)) + if (Viewpoint.bDoOrtho && ((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper)) { double vxdbl = Viewpoint.OffPos.X; double vydbl = Viewpoint.OffPos.Y; @@ -1042,7 +1044,7 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites, FRenderState& state) // Give the DrawInfo the viewpoint in fixed point because that's what the nodes are. viewx = FLOAT2FIXED(Viewpoint.Pos.X); viewy = FLOAT2FIXED(Viewpoint.Pos.Y); - if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && Viewpoint.IsAllowedOoB()) + if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && Viewpoint.bDoOob) { viewx = FLOAT2FIXED(Viewpoint.OffPos.X); viewy = FLOAT2FIXED(Viewpoint.OffPos.Y); @@ -1068,7 +1070,7 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites, FRenderState& state) auto future = renderPool.push([&](int id) { WorkerThread(); }); - if (Viewpoint.IsOrtho() && ((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper)) RenderOrthoNoFog(state); + if (Viewpoint.bDoOrtho && ((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper)) RenderOrthoNoFog(state); else RenderBSPNode(node, state); jobQueue.AddJob(RenderJob::TerminateJob, nullptr, nullptr); @@ -1079,7 +1081,7 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites, FRenderState& state) } else { - if (Viewpoint.IsOrtho() && ((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper)) RenderOrthoNoFog(state); + if (Viewpoint.bDoOrtho && ((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper)) RenderOrthoNoFog(state); else RenderBSPNode(node, state); Bsp.Unclock(); } diff --git a/src/rendering/hwrenderer/scene/hw_clipper.cpp b/src/rendering/hwrenderer/scene/hw_clipper.cpp index 50780002d..a21be950b 100644 --- a/src/rendering/hwrenderer/scene/hw_clipper.cpp +++ b/src/rendering/hwrenderer/scene/hw_clipper.cpp @@ -397,7 +397,7 @@ angle_t Clipper::PointToPseudoAngle(double x, double y) { return 0; } - else if (!amRadar && viewpoint->IsOrtho()) + else if (!amRadar && viewpoint->bDoOrtho) { return PointToPseudoOrthoAngle(x, y); } @@ -424,7 +424,7 @@ angle_t Clipper::PointToPseudoPitch(double x, double y, double z) { return 0; } - else if (viewpoint->IsOrtho()) + else if (viewpoint->bDoOrtho) { return PointToPseudoOrthoPitch(x, y, z); } @@ -538,7 +538,7 @@ bool Clipper::CheckBox(const float *bspcoord) angle1 = PointToPseudoAngle (bspcoord[check[0]], bspcoord[check[1]]); angle2 = PointToPseudoAngle (bspcoord[check[2]], bspcoord[check[3]]); - if (vp->IsOrtho()) + if (vp->bDoOrtho) { if (angle2 != angle1) return true; switch (boxpos) // Check if the closer corner is poking into the view area @@ -563,7 +563,7 @@ bool Clipper::CheckBoxOrthoPitch(const float *bspcoord) { angle_t pitchmin, pitchmax; auto &vp = viewpoint; - if (!vp->IsOrtho()) return true; + if (!vp->bDoOrtho) return true; angle_t pitchtemp; double padding = 1.0/viewpoint->ScreenProj/viewpoint->PitchCos; diff --git a/src/rendering/hwrenderer/scene/hw_decal.cpp b/src/rendering/hwrenderer/scene/hw_decal.cpp index bfd092262..a185c13a1 100644 --- a/src/rendering/hwrenderer/scene/hw_decal.cpp +++ b/src/rendering/hwrenderer/scene/hw_decal.cpp @@ -762,7 +762,7 @@ int HWDecalCreateInfo::SetupLights(HWDrawInfo* di, FRenderState& state, FDynLigh p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1); // Iterate through all dynamic lights which touch this wall and render them - auto wallLightList = di->Level->lightlists.wall_dlist.CheckKey(side); + auto wallLightList = di->Level->lightlists.flat_dlist.SSize() > side->Index() ? &di->Level->lightlists.wall_dlist[side->Index()] : nullptr; if (wallLightList) { diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index a996aa490..fcac81107 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -242,7 +242,7 @@ void HWDrawInfo::ClearBuffers() void HWDrawInfo::UpdateCurrentMapSection() { int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection; - if (Viewpoint.IsAllowedOoB() || Viewpoint.IsOrtho()) + if (Viewpoint.bDoOob || Viewpoint.bDoOrtho) mapsection = Level->PointInRenderSubsector(Viewpoint.OffPos)->mapsection; CurrentMapSections.Set(mapsection); } @@ -259,8 +259,8 @@ void HWDrawInfo::SetViewArea() auto &vp = Viewpoint; // The render_sector is better suited to represent the current position in GL vp.sector = Level->PointInRenderSubsector(vp.Pos)->render_sector; - if (Viewpoint.IsAllowedOoB()) - vp.sector = Level->PointInRenderSubsector(vp.camera->Pos())->render_sector; + if (Viewpoint.bDoOob) + vp.sector = Level->PointInRenderSubsector(vp.camera->Pos())->render_sector; // Get the heightsec state from the render sector, not the current one! if (vp.sector->GetHeightSec()) @@ -359,7 +359,7 @@ angle_t OoBFrustumAngle(FRenderViewpoint* Viewpoint) angle_t HWDrawInfo::FrustumAngle() { - if (Viewpoint.IsAllowedOoB()) + if (Viewpoint.bDoOob) { return OoBFrustumAngle(&Viewpoint); } @@ -610,7 +610,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) angle_t a1 = FrustumAngle(); mClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + a1, vp.Angles.Yaw.BAMs() - a1); Viewpoint.FrustAngle = a1; - if (Viewpoint.IsAllowedOoB()) // No need for vertical clipper if viewpoint not allowed out of bounds + if (Viewpoint.bDoOob) // No need for vertical clipper if viewpoint not allowed out of bounds { double a2 = 20.0 + 0.5*Viewpoint.FieldOfView.Degrees(); // FrustumPitch for vertical clipping if (a2 > 179.0) a2 = 179.0; @@ -1253,7 +1253,7 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor) double horiy = Viewpoint.Cos * actor->radius; DVector3 actorpos = actor->Pos(); DVector3 vvec = actorpos - Viewpoint.Pos; - if (Viewpoint.IsOrtho()) + if (Viewpoint.bDoOrtho) { vvec = 5.0 * Viewpoint.camera->ViewPos->Offset.Length() * Viewpoint.ViewVector3D; // Should be 4.0? (since zNear is behind screen by 3*dist in VREyeInfo::GetProjection()) } @@ -1448,7 +1448,7 @@ void HWDrawInfo::DrawScene(int drawmode, FRenderState& state) { ssao_portals_available = gl_ssao_portals; applySSAO = true; - if (r_dithertransparency && vp.IsAllowedOoB()) + if (r_dithertransparency && vp.bDoOob) { if (vp.camera->tracer) SetDitherTransFlags(vp.camera->tracer); @@ -1526,7 +1526,7 @@ void HWDrawInfo::ProcessScene(bool toscreen, FRenderState& state) drawctx->portalState.BeginScene(); int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection; - if (Viewpoint.IsAllowedOoB() || Viewpoint.IsOrtho()) + if (Viewpoint.bDoOob || Viewpoint.bDoOrtho) mapsection = Level->PointInRenderSubsector(Viewpoint.OffPos)->mapsection; CurrentMapSections.Set(mapsection); DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN, state); diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index 045bb8711..d02502ba5 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -176,11 +176,9 @@ void HWFlat::SetupLights(HWFlatDispatcher *di, FRenderState& state, FDynLightDat return; // no lights on additively blended surfaces. } - auto flatLightList = di->Level->lightlists.flat_dlist.CheckKey(section); - - if (flatLightList) + if (di->Level->lightlists.flat_dlist.SSize() > section->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(di->Level->lightlists.flat_dlist[section->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { @@ -579,7 +577,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t * // // // - if ((which & SSRF_RENDERFLOOR) && ((di->di && vp->IsOrtho()) ? vp->ViewVector3D.dot(frontsector->floorplane.Normal()) < 0.0 : (!di->di || (frontsector->floorplane.ZatPoint(vp->Pos) <= vp->Pos.Z))) && (!section || !(section->flags & FSection::DONTRENDERFLOOR))) + if ((which & SSRF_RENDERFLOOR) && (vp && vp->bDoOrtho ? vp->ViewVector3D.dot(frontsector->floorplane.Normal()) < 0.0 : (!vp || frontsector->floorplane.ZatPoint(vp->Pos) <= vp->Pos.Z)) && (!section || !(section->flags & FSection::DONTRENDERFLOOR))) { // process the original floor first. @@ -637,7 +635,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t * // // // - if ((which & SSRF_RENDERCEILING) && ((di->di && vp->IsOrtho()) ? vp->ViewVector3D.dot(frontsector->ceilingplane.Normal()) < 0.0 : (!di->di || (frontsector->ceilingplane.ZatPoint(vp->Pos) >= vp->Pos.Z))) && (!section || !(section->flags & FSection::DONTRENDERCEILING))) + if ((which & SSRF_RENDERCEILING) && (vp && vp->bDoOrtho ? vp->ViewVector3D.dot(frontsector->ceilingplane.Normal()) < 0.0 : !vp || frontsector->ceilingplane.ZatPoint(vp->Pos) >= vp->Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERCEILING))) { // process the original ceiling first. @@ -722,7 +720,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t * double ff_top = rover->top.plane->ZatPoint(sector->centerspot); if (ff_top < lastceilingheight) { - if (!di->di || (vp->IsOrtho() ? vp->ViewVector3D.dot(rover->top.plane->Normal()) > 0.0 : vp->Pos.Z <= rover->top.plane->ZatPoint(vp->Pos))) + if (!vp || ((vp->bDoOrtho ? vp->ViewVector3D.dot(rover->top.plane->Normal()) > 0.0 : vp->Pos.Z <= rover->top.plane->ZatPoint(vp->Pos)))) { SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; @@ -736,7 +734,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t * double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); if (ff_bottom < lastceilingheight) { - if (!di->di || (vp->IsOrtho() ? vp->ViewVector3D.dot(rover->bottom.plane->Normal()) > 0.0 : vp->Pos.Z <= rover->bottom.plane->ZatPoint(vp->Pos))) + if (!vp || (vp->bDoOrtho ? vp->ViewVector3D.dot(rover->bottom.plane->Normal()) > 0.0 : vp->Pos.Z <= rover->bottom.plane->ZatPoint(vp->Pos))) { SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; @@ -762,7 +760,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t * double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX)) { - if (!di->di || (vp->IsOrtho() ? vp->ViewVector3D.dot(rover->bottom.plane->Normal()) > 0.0 : vp->Pos.Z >= rover->bottom.plane->ZatPoint(vp->Pos))) + if (!vp || (vp->bDoOrtho ? vp->ViewVector3D.dot(rover->bottom.plane->Normal()) > 0.0 : vp->Pos.Z >= rover->bottom.plane->ZatPoint(vp->Pos))) { SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; @@ -783,7 +781,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t * double ff_top = rover->top.plane->ZatPoint(sector->centerspot); if (ff_top > lastfloorheight) { - if (!di->di || (vp->IsOrtho() ? vp->ViewVector3D.dot(rover->top.plane->Normal()) > 0.0 : vp->Pos.Z >= rover->top.plane->ZatPoint(vp->Pos))) + if (!vp || (vp->bDoOrtho ? vp->ViewVector3D.dot(rover->top.plane->Normal()) > 0.0 : vp->Pos.Z >= rover->top.plane->ZatPoint(vp->Pos))) { SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 06e4683a6..09af371bd 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -125,7 +125,7 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di { HWPortal * best = nullptr; unsigned bestindex = 0; - bool usestencil = outer_di->Viewpoint.IsAllowedOoB(); + bool usestencil = outer_di->Viewpoint.bDoOob; // Find the one with the highest amount of lines. // Normally this is also the one that saves the largest amount @@ -504,7 +504,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe } auto &vp = di->Viewpoint; - state->vpIsAllowedOoB = vp.IsAllowedOoB(); + state->vpIsAllowedOoB = vp.bDoOob; di->UpdateCurrentMapSection(); di->mClipPortal = this; @@ -573,7 +573,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe angle_t af = di->FrustumAngle(); if (af < ANGLE_180) clipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + af, vp.Angles.Yaw.BAMs() - af); - if (!di->Viewpoint.IsAllowedOoB()) + if(!di->Viewpoint.bDoOob) clipper->SafeAddClipRange(linedef->v1, linedef->v2); return true; } @@ -609,7 +609,7 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl return false; } auto &vp = di->Viewpoint; - state->vpIsAllowedOoB = vp.IsAllowedOoB(); + state->vpIsAllowedOoB = vp.bDoOob; di->mClipPortal = this; line_t *origin = glport->lines[0]->mOrigin; @@ -689,7 +689,7 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe return false; } auto &vp = di->Viewpoint; - state->vpIsAllowedOoB = vp.IsAllowedOoB(); + state->vpIsAllowedOoB = vp.bDoOob; state->skyboxrecursion++; state->PlaneMirrorMode = 0; @@ -801,7 +801,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c FSectorPortalGroup *portal = origin; auto &vp = di->Viewpoint; - state->vpIsAllowedOoB = vp.IsAllowedOoB(); + state->vpIsAllowedOoB = vp.bDoOob; vp.Pos += origin->mDisplacement; vp.ActorPos += origin->mDisplacement; @@ -810,7 +810,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c // avoid recursions! if (origin->plane != -1) screen->instack[origin->plane]++; - if (vp.IsAllowedOoB() && lines.Size() > 0) + if (vp.bDoOob && lines.Size() > 0) { flat.plane.GetFromSector(lines[0].sub->sector, origin->plane); di->SetClipHeight(flat.plane.plane.ZatPoint(vp.Pos), @@ -823,7 +823,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c // If the viewpoint is not within the portal, we need to invalidate the entire clip area. // The portal will re-validate the necessary parts when its subsectors get traversed. subsector_t *sub = di->Level->PointInRenderSubsector(vp.Pos); - if (vp.IsAllowedOoB()) sub = di->Level->PointInRenderSubsector(vp.OffPos); + if (vp.bDoOob) sub = di->Level->PointInRenderSubsector(vp.OffPos); if (!(di->ss_renderflags[sub->Index()] & SSRF_SEEN)) { clipper->SafeAddClipRange(0, ANGLE_MAX); @@ -891,7 +891,7 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]); auto &vp = di->Viewpoint; - state->vpIsAllowedOoB = vp.IsAllowedOoB(); + state->vpIsAllowedOoB = vp.bDoOob; old_pm = state->PlaneMirrorMode; // the player is always visible in a mirror. @@ -947,6 +947,8 @@ void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) const char *HWPlaneMirrorPortal::GetName() { return origin->fC() < 0? "Planemirror ceiling" : "Planemirror floor"; } +int HWPlaneMirrorPortal::GetMirrorSide() const { return origin->fC() < 0 ? -1 : 1; }; + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index 2523fc6b3..0c75d50db 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -71,6 +71,7 @@ public: { } virtual ~HWPortal() {} + virtual int GetMirrorSide() const { return 0; }; virtual int ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; } virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; } virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; } @@ -148,7 +149,7 @@ public: virtual bool NeedDepthBuffer() { return true; } virtual void DrawContents(HWDrawInfo *di, FRenderState &state) { - if (Setup(di, state, (di->Viewpoint.IsAllowedOoB() ? di->rClipper : di->mClipper))) + if (Setup(di, state, (di->Viewpoint.bDoOob ? di->rClipper : di->mClipper))) { di->DrawScene(DM_PORTAL, state); Shutdown(di, state); @@ -304,6 +305,8 @@ protected: public: + int GetMirrorSide() const override; + HWPlaneMirrorPortal(FPortalSceneState *state, secplane_t * pt) : HWScenePortalBase(state) { origin = pt; diff --git a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp index fb90e714d..d50ea4b55 100644 --- a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp @@ -121,11 +121,9 @@ int HWDrawInfo::SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &light lightdata.Clear(); - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sub->section); - - if (flatLightList) + if (Level->lightlists.flat_dlist.SSize() > sub->section->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(Level->lightlists.flat_dlist[sub->section->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 00a074be0..c4ca28b2a 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -157,10 +157,10 @@ void HWWall::SkyPlane(HWWallDispatcher *di, FRenderState& state, sector_t *secto case PORTS_PORTAL: case PORTS_LINKEDPORTAL: { - if (di->di && di->di->Viewpoint.IsAllowedOoB()) + if (di->di && di->di->Viewpoint.bDoOob) { secplane_t myplane = plane ? sector->ceilingplane : sector->floorplane; - if (di->di->Viewpoint.IsOrtho() && di->di->Viewpoint.ViewVector3D.dot(myplane.Normal()) > 0.0) return; + if (di->di->Viewpoint.bDoOrtho && di->di->Viewpoint.ViewVector3D.dot(myplane.Normal()) > 0.0) return; else if (plane==1 && di->di->Viewpoint.Pos.Z >= myplane.ZatPoint(di->di->Viewpoint.Pos)) return; else if (plane==0 && di->di->Viewpoint.Pos.Z <= myplane.ZatPoint(di->di->Viewpoint.Pos)) return; } @@ -323,7 +323,7 @@ void HWWall::SkyTop(HWWallDispatcher *di, FRenderState& state, seg_t * seg,secto // if (backreflect > 0 && bs->ceilingplane.fD() == fs->ceilingplane.fD() && !bs->isClosed()) // { // Don't add intra-portal line to the portal. - // if (!(di->di && di->di->Viewpoint.IsAllowedOoB())) + // if (!(di->di && di->di->Viewpoint.bDoOob)) // { // return; // } @@ -406,7 +406,7 @@ void HWWall::SkyBottom(HWWallDispatcher *di, FRenderState& state, seg_t * seg,se // if (backreflect > 0 && bs->floorplane.fD() == fs->floorplane.fD() && !bs->isClosed()) // { // // Don't add intra-portal line to the portal. - // if (!(di->di && di->di->Viewpoint.IsAllowedOoB())) + // if (!(di->di && di->di->Viewpoint.bDoOob)) // { // return; // } diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index 32512cd83..97909fb33 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -158,12 +158,10 @@ void HWDrawInfo::GetDynSpriteLight(AActor* self, sun_trace_cache_t* traceCache, } // Go through both light lists - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sec); - - if (flatLightList) + if (Level->lightlists.flat_dlist.SSize() > sec->Index()) { - TMap>::Iterator it(*flatLightList); - TMap>::Pair* pair; + TMap>::Iterator it(Level->lightlists.flat_dlist[sec->Index()]); + TMap>::Pair *pair; while (it.NextPair(pair)) { auto node = pair->Value.get(); @@ -312,11 +310,10 @@ void HWDrawInfo::GetDynSpriteLightList(AActor *self, double x, double y, double auto section = subsector->section; if (section->validcount == dl_validcount) return; // already done from a previous subsector. - auto flatLightList = level.lightlists.flat_dlist.CheckKey(subsector->section); - if (flatLightList) + if (level.lightlists.flat_dlist.SSize() > subsector->section->Index()) { - TMap>::Iterator it(*flatLightList); - TMap>::Pair* pair; + TMap>::Iterator it(level.lightlists.flat_dlist[subsector->section->Index()]); + TMap>::Pair *pair; while (it.NextPair(pair)) { // check all lights touching a subsector auto node = pair->Value.get(); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index a80d2f6a8..c44e55ab9 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -651,7 +651,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) mat.Translate(-center.X, -center.Z, -center.Y); } - if (actor && (actor->renderflags2 & RF2_ISOMETRICSPRITES) && di->Viewpoint.IsOrtho()) + if (actor && (actor->renderflags2 & RF2_ISOMETRICSPRITES) && di->Viewpoint.bDoOrtho) { float angleRad = (FAngle::fromDeg(270.) - HWAngles.Yaw).Radians(); mat.Translate(center.X, center.Z, center.Y); @@ -1063,7 +1063,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto bool mirror = false; bool backfaced = false; DAngle ang = (thingpos - vp.Pos).Angle(); - if (di->Viewpoint.IsOrtho()) ang = vp.Angles.Yaw; + if (di->Viewpoint.bDoOrtho) ang = vp.Angles.Yaw; else if (actor && thing->renderflags2 & RF2_ANGLEDROLL) { Matrix3x4 rolltilt; diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 67b5cdf02..7e259106f 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -430,11 +430,9 @@ void HWWall::SetupLights(HWDrawInfo*di, FRenderState& state, FDynLightData &ligh if ((seg->sidedef->Flags & WALLF_POLYOBJ) && sub) { // Polobject segs cannot be checked per sidedef so use the subsector instead. - auto flatLightList = di->Level->lightlists.flat_dlist.CheckKey(sub->section); - - if (flatLightList) + if (di->Level->lightlists.flat_dlist.SSize() > sub->section->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(di->Level->lightlists.flat_dlist[sub->section->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { @@ -495,11 +493,9 @@ void HWWall::SetupLights(HWDrawInfo*di, FRenderState& state, FDynLightData &ligh } else { - auto wallLightList = di->Level->lightlists.wall_dlist.CheckKey(seg->sidedef); - - if (wallLightList) + if (di->Level->lightlists.wall_dlist.SSize() > seg->sidedef->Index()) { - TMap>::Iterator it(*wallLightList); + TMap>::Iterator it(di->Level->lightlists.wall_dlist[seg->sidedef->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { @@ -694,7 +690,7 @@ void HWWall::PutPortal(HWWallDispatcher *di, FRenderState& state, int ptype, int break; case PORTALTYPE_PLANEMIRROR: - if (ddi->Viewpoint.IsOrtho() ? (ddi->Viewpoint.ViewVector3D.dot(planemirror->Normal()) < 0) + if (ddi->Viewpoint.bDoOrtho ? (ddi->Viewpoint.ViewVector3D.dot(planemirror->Normal()) < 0) : (ddi->drawctx->portalState.PlaneMirrorMode * planemirror->fC() <= 0)) { planemirror = ddi->drawctx->portalState.UniquePlaneMirrors.Get(planemirror); diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index 7fe1a66ee..1df164692 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -550,7 +550,7 @@ void R_InterpolateView(FRenderViewpoint& viewPoint, const player_t* const player const int prevPortalGroup = viewLvl->PointInRenderSubsector(iView->Old.Pos)->sector->PortalGroup; const int curPortalGroup = viewLvl->PointInRenderSubsector(iView->New.Pos)->sector->PortalGroup; - if (viewPoint.IsAllowedOoB() && prevPortalGroup != curPortalGroup) viewPoint.Pos = iView->New.Pos; + if (viewPoint.bDoOob && prevPortalGroup != curPortalGroup) viewPoint.Pos = iView->New.Pos; else { const DVector2 portalOffset = viewLvl->Displacements.getOffset(prevPortalGroup, curPortalGroup); @@ -567,7 +567,7 @@ void R_InterpolateView(FRenderViewpoint& viewPoint, const player_t* const player // Due to interpolation this is not necessarily the same as the sector the camera is in. viewPoint.sector = viewLvl->PointInRenderSubsector(viewPoint.Pos)->sector; - if (!viewPoint.IsAllowedOoB() || !V_IsHardwareRenderer()) + if (!viewPoint.bDoOob || !V_IsHardwareRenderer()) { bool moved = false; while (!viewPoint.sector->PortalBlocksMovement(sector_t::ceiling)) @@ -712,7 +712,7 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow) ViewVector3D.Y = v.Y * PitchCos; ViewVector3D.Z = -PitchSin; - if (IsOrtho() || IsAllowedOoB()) // These auto-ensure that camera and camera->ViewPos exist + if (bDoOrtho || bDoOob) // These auto-ensure that camera and camera->ViewPos exist { if (camera->tracer != NULL) { @@ -724,7 +724,7 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow) } } - if (IsOrtho() && (camera->ViewPos->Offset.XY().Length() > 0.0)) + if (bDoOrtho && (camera->ViewPos->Offset.XY().Length() > 0.0)) { ScreenProj = 1.34396 / camera->ViewPos->Offset.Length() / tan (FieldOfView.Radians()*0.5); // [DVR] Estimated. +/-1 should be top/bottom of screen. ScreenProjX = ScreenProj * 0.5 / viewWindow.WidescreenRatio; @@ -953,6 +953,9 @@ void R_SetupFrame(FRenderViewpoint& viewPoint, const FViewWindow& viewWindow, AA if (viewPoint.camera == nullptr) I_Error("You lost your body. Bad dehacked work is likely to blame."); + viewPoint.bDoOob = viewPoint.IsAllowedOoB(); + viewPoint.bDoOrtho = viewPoint.IsOrtho(); + InterpolationViewer* const iView = FindPastViewer(viewPoint.camera); // Always reset these back to zero. iView->ViewOffset.Zero(); @@ -1136,14 +1139,14 @@ void R_SetupFrame(FRenderViewpoint& viewPoint, const FViewWindow& viewWindow, AA // Keep the view within the sector's floor and ceiling // But allow VPSF_ALLOWOUTOFBOUNDS camera viewpoints to go out of bounds when using hardware renderer - if (viewPoint.sector->PortalBlocksMovement(sector_t::ceiling) && (!viewPoint.IsAllowedOoB() || !V_IsHardwareRenderer())) + if (viewPoint.sector->PortalBlocksMovement(sector_t::ceiling) && (!viewPoint.bDoOob || !V_IsHardwareRenderer())) { const double z = viewPoint.sector->ceilingplane.ZatPoint(viewPoint.Pos) - 4.0; if (viewPoint.Pos.Z > z) viewPoint.Pos.Z = z; } - if (viewPoint.sector->PortalBlocksMovement(sector_t::floor) && (!viewPoint.IsAllowedOoB() || !V_IsHardwareRenderer())) + if (viewPoint.sector->PortalBlocksMovement(sector_t::floor) && (!viewPoint.bDoOob || !V_IsHardwareRenderer())) { const double z = viewPoint.sector->floorplane.ZatPoint(viewPoint.Pos) + 4.0; if (viewPoint.Pos.Z < z) diff --git a/src/rendering/r_utility.h b/src/rendering/r_utility.h index f6346c853..aa4615411 100644 --- a/src/rendering/r_utility.h +++ b/src/rendering/r_utility.h @@ -53,6 +53,8 @@ struct FRenderViewpoint int extralight; // extralight to be added to this viewpoint bool showviewer; // show the camera actor? bool bForceNoViewer; // Never show the camera Actor. + bool bDoOob; + bool bDoOrtho; void SetViewAngle(const FViewWindow& viewWindow); bool IsAllowedOoB(); // Checks if camera actor exists, has viewpos, and viewpos has VPSF_ALLOWOUTOFBOUNDS flag set bool IsOrtho(); // Checks if camera actor exists, has viewpos, and viewpos has VPSF_ORTHOGRAPHIC flag set diff --git a/src/rendering/swrenderer/drawers/r_draw.cpp b/src/rendering/swrenderer/drawers/r_draw.cpp index 4e8a66732..ff3f56bb8 100644 --- a/src/rendering/swrenderer/drawers/r_draw.cpp +++ b/src/rendering/swrenderer/drawers/r_draw.cpp @@ -241,46 +241,48 @@ namespace swrenderer drawerargs.dc_num_lights = 0; - // Setup lights for column - FLightNode* cur_node = drawerargs.LightList(); - while (cur_node) + if(drawerargs.LightList()) { - if (cur_node->lightsource->IsActive()) + TMap>::Iterator it(*drawerargs.LightList()); + TMap>::Pair *pair; + while (it.NextPair(pair)) { - double lightX = cur_node->lightsource->X() - wallargs.ViewpointPos.X; - double lightY = cur_node->lightsource->Y() - wallargs.ViewpointPos.Y; - double lightZ = cur_node->lightsource->Z() - wallargs.ViewpointPos.Z; - - float lx = (float)(lightX * wallargs.Sin - lightY * wallargs.Cos) - drawerargs.dc_viewpos.X; - float ly = (float)(lightX * wallargs.TanCos + lightY * wallargs.TanSin) - drawerargs.dc_viewpos.Y; - float lz = (float)lightZ; - - // Precalculate the constant part of the dot here so the drawer doesn't have to. - bool is_point_light = cur_node->lightsource->IsAttenuated(); - float lconstant = lx * lx + ly * ly; - float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f; - - // Include light only if it touches this column - float radius = cur_node->lightsource->GetRadius(); - if (radius * radius >= lconstant && nlconstant >= 0.0f) + auto cur_node = pair->Value.get(); + if (cur_node->lightsource->IsActive()) { - uint32_t red = cur_node->lightsource->GetRed(); - uint32_t green = cur_node->lightsource->GetGreen(); - uint32_t blue = cur_node->lightsource->GetBlue(); + double lightX = cur_node->lightsource->X() - wallargs.ViewpointPos.X; + double lightY = cur_node->lightsource->Y() - wallargs.ViewpointPos.Y; + double lightZ = cur_node->lightsource->Z() - wallargs.ViewpointPos.Z; - auto& light = drawerargs.dc_lights[drawerargs.dc_num_lights++]; - light.x = lconstant; - light.y = nlconstant; - light.z = lz; - light.radius = 256.0f / cur_node->lightsource->GetRadius(); - light.color = (red << 16) | (green << 8) | blue; + float lx = (float)(lightX * wallargs.Sin - lightY * wallargs.Cos) - drawerargs.dc_viewpos.X; + float ly = (float)(lightX * wallargs.TanCos + lightY * wallargs.TanSin) - drawerargs.dc_viewpos.Y; + float lz = (float)lightZ; - if (drawerargs.dc_num_lights == WallColumnDrawerArgs::MAX_DRAWER_LIGHTS) - break; + // Precalculate the constant part of the dot here so the drawer doesn't have to. + bool is_point_light = cur_node->lightsource->IsAttenuated(); + float lconstant = lx * lx + ly * ly; + float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f; + + // Include light only if it touches this column + float radius = cur_node->lightsource->GetRadius(); + if (radius * radius >= lconstant && nlconstant >= 0.0f) + { + uint32_t red = cur_node->lightsource->GetRed(); + uint32_t green = cur_node->lightsource->GetGreen(); + uint32_t blue = cur_node->lightsource->GetBlue(); + + auto& light = drawerargs.dc_lights[drawerargs.dc_num_lights++]; + light.x = lconstant; + light.y = nlconstant; + light.z = lz; + light.radius = 256.0f / cur_node->lightsource->GetRadius(); + light.color = (red << 16) | (green << 8) | blue; + + if (drawerargs.dc_num_lights == WallColumnDrawerArgs::MAX_DRAWER_LIGHTS) + break; + } } } - - cur_node = cur_node->nextLight; } } diff --git a/src/rendering/swrenderer/drawers/r_draw_pal.h b/src/rendering/swrenderer/drawers/r_draw_pal.h index b3c54be18..5eaa7c87a 100644 --- a/src/rendering/swrenderer/drawers/r_draw_pal.h +++ b/src/rendering/swrenderer/drawers/r_draw_pal.h @@ -86,7 +86,7 @@ namespace swrenderer ShadeConstants ColormapConstants() const { return wallargs->ColormapConstants(); } fixed_t Light() const { return LIGHTSCALE(mLight, mShade); } - FLightNode* LightList() const { return wallargs->lightlist; } + TMap>* LightList() const { return wallargs->lightlist; } const WallDrawerArgs* wallargs; diff --git a/src/rendering/swrenderer/line/r_walldraw.cpp b/src/rendering/swrenderer/line/r_walldraw.cpp index 6f12b13fb..5c278bfe1 100644 --- a/src/rendering/swrenderer/line/r_walldraw.cpp +++ b/src/rendering/swrenderer/line/r_walldraw.cpp @@ -207,60 +207,23 @@ namespace swrenderer drawerargs.DrawWall(Thread); } - FLightNode* RenderWallPart::GetLightList() + TMap>* RenderWallPart::GetLightList() { - while (light_list) - { - // Clear out the wall part light list - FLightNode *next = nullptr; - if (light_list->nextLight) next = light_list->nextLight; - delete light_list; - if (next) light_list = next; - } - CameraLight* cameraLight = CameraLight::Instance(); if ((cameraLight->FixedLightLevel() >= 0) || cameraLight->FixedColormap()) + { return nullptr; // [SP] Don't draw dynlights if invul/lightamp active + } else if (curline && curline->sidedef) { auto Level = curline->Subsector->sector->Level; - auto wallLightList = Level->lightlists.wall_dlist.CheckKey(curline->sidedef); - if (wallLightList) + + if (Level->lightlists.wall_dlist.SSize() > curline->sidedef->Index()) { - TMap>::Iterator it(*wallLightList); - TMap>::Pair *pair; - while (it.NextPair(pair)) - { - auto node = pair->Value.get(); - if (!node) continue; - - if (node->lightsource->IsActive()) - { - bool found = false; - FLightNode *light_node = light_list; - while (light_node) - { - if (light_node->lightsource == node->lightsource) - { - found = true; - break; - } - light_node = light_node->nextLight; - } - if (!found) - { - FLightNode *newlight = new FLightNode; - newlight->nextLight = light_list; - newlight->lightsource = node->lightsource; - light_list = newlight; - } - } - } + return &Level->lightlists.wall_dlist[curline->sidedef->Index()]; } - - return light_list; } - else - return nullptr; + + return nullptr; } } diff --git a/src/rendering/swrenderer/line/r_walldraw.h b/src/rendering/swrenderer/line/r_walldraw.h index 4088e792e..bcbdc02a3 100644 --- a/src/rendering/swrenderer/line/r_walldraw.h +++ b/src/rendering/swrenderer/line/r_walldraw.h @@ -62,7 +62,7 @@ namespace swrenderer private: void ProcessStripedWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords); void ProcessNormalWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords); - FLightNode* GetLightList(); + TMap>* GetLightList(); RenderThread* Thread = nullptr; @@ -76,7 +76,7 @@ namespace swrenderer ProjectedWallLight mLight; - FLightNode *light_list = nullptr; + TMap> *light_list = nullptr; bool mask = false; bool additive = false; fixed_t alpha = 0; diff --git a/src/rendering/swrenderer/plane/r_visibleplane.cpp b/src/rendering/swrenderer/plane/r_visibleplane.cpp index c7d327191..3b20236ca 100644 --- a/src/rendering/swrenderer/plane/r_visibleplane.cpp +++ b/src/rendering/swrenderer/plane/r_visibleplane.cpp @@ -76,10 +76,10 @@ namespace swrenderer return; // [SP] no dynlights if invul or lightamp auto Level = sec->sector->Level; - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sec); - if (flatLightList) + + if (Level->lightlists.flat_dlist.SSize() > sec->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(Level->lightlists.flat_dlist[sec->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { diff --git a/src/rendering/swrenderer/things/r_sprite.cpp b/src/rendering/swrenderer/things/r_sprite.cpp index 102dc429e..2e1df8899 100644 --- a/src/rendering/swrenderer/things/r_sprite.cpp +++ b/src/rendering/swrenderer/things/r_sprite.cpp @@ -209,10 +209,10 @@ namespace swrenderer float lit_green = 0; float lit_blue = 0; auto Level = vis->sector->Level; - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(vis->section); - if (flatLightList) + + if (Level->lightlists.flat_dlist.SSize() > vis->section->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(Level->lightlists.flat_dlist[vis->section->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { diff --git a/src/rendering/swrenderer/viewport/r_walldrawer.h b/src/rendering/swrenderer/viewport/r_walldrawer.h index 567758073..7ecd2b24e 100644 --- a/src/rendering/swrenderer/viewport/r_walldrawer.h +++ b/src/rendering/swrenderer/viewport/r_walldrawer.h @@ -31,7 +31,7 @@ namespace swrenderer short* dwal; FWallCoords WallC; ProjectedWallTexcoords texcoords; - FLightNode* lightlist = nullptr; + TMap>* lightlist = nullptr; float lightpos; float lightstep;