From d206a767b2c1ce9d45fef805e036671a64718ca7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 3 May 2021 17:48:35 +0200 Subject: [PATCH] - added render workaround for CP07. --- source/core/maphack.cpp | 11 ++ source/core/maploader.cpp | 3 +- source/core/rendering/hw_sections.cpp | 148 +++++++++++++++++- source/core/rendering/hw_sections.h | 1 + .../core/rendering/scene/hw_bunchdrawer.cpp | 33 ++-- source/core/savegamehelp.cpp | 2 + source/games/blood/src/db.cpp | 2 + .../c3bfb6a6e7cded2e5fe16cea86632d79.mhk | 2 + 8 files changed, 185 insertions(+), 17 deletions(-) create mode 100644 wadsrc/static/engine/compatibility/c3bfb6a6e7cded2e5fe16cea86632d79.mhk diff --git a/source/core/maphack.cpp b/source/core/maphack.cpp index 03a44431c..82187a799 100644 --- a/source/core/maphack.cpp +++ b/source/core/maphack.cpp @@ -37,6 +37,7 @@ #include "printf.h" #include "c_dispatch.h" #include "md4.h" +#include "hw_sections.h" static TArray usermaphacks; TArray blockingpairs[MAXWALLS]; @@ -173,6 +174,16 @@ static int32_t LoadMapHack(const char *filename) wall[currentwall].overpicnum = sc.Number; } } + else if (sc.Compare("split")) + { + int start = -1, end = -1; + if (sc.CheckNumber()) start = sc.Number; + if (sc.CheckNumber()) end = sc.Number; + if (end >= 0 && validateSector()) + { + hw_SetSplitSector(currentsector, start, end); + } + } else if (sc.Compare("clearflags")) { if (currentsector != -1 && validateSector()) diff --git a/source/core/maploader.cpp b/source/core/maploader.cpp index fd91152d5..ee6bf0d99 100644 --- a/source/core/maploader.cpp +++ b/source/core/maploader.cpp @@ -453,6 +453,8 @@ void engineLoadBoard(const char* filename, int flags, vec3_t* pos, int16_t* ang, G_LoadMapHack(filename, md4); setWallSectors(); hw_BuildSections(); + sectorGeometry.SetSize(numsections); + memcpy(wallbackup, wall, sizeof(wallbackup)); memcpy(sectorbackup, sector, sizeof(sectorbackup)); @@ -491,5 +493,4 @@ void setWallSectors() wall[sector[i].wallptr + w].sector = i; } } - sectorGeometry.SetSize(numsectors); } \ No newline at end of file diff --git a/source/core/rendering/hw_sections.cpp b/source/core/rendering/hw_sections.cpp index 8cb353d03..56a4030cc 100644 --- a/source/core/rendering/hw_sections.cpp +++ b/source/core/rendering/hw_sections.cpp @@ -48,6 +48,10 @@ TArray sectionspersector[MAXSECTORS]; // reverse map, mainly for the automa int numsections; int numsectionlines; +void hw_SplitSector(int sector, int startpos, int endpos); + +TArray splits; + void hw_BuildSections() { @@ -72,4 +76,146 @@ void hw_BuildSections() sectionspersector[i].Resize(1); sectionspersector[i][0] = i; } -} \ No newline at end of file + + for (unsigned i = 0; i < splits.Size(); i += 3) + hw_SplitSector(splits[i], splits[i + 1], splits[i + 2]); +} + + +static void SplitSection(int section, int start, int end) +{ + // note: to do this, the sector's lines must be well ordered and there must only be one outline and no holes. + // This also can only apply a single split to a given sector. + int firstsection = numsections++; + int secondsection = numsections++; + + auto& sect = sections[section]; + Section* sect1 = §ions[firstsection]; + Section* sect2 = §ions[secondsection]; + sect1->sector = sect.sector; + sect2->sector = sect.sector; + sect1->lines.Clear(); + sect2->lines.Clear(); + for (int aline : sect.lines) + { + int line = sectionLines[aline].wall; + if (line < start || line >= end) + { + sect1->lines.Push(aline); + } + if (line == start) + { + sect1->lines.Push(-1); + sect2->lines.Push(-1); + } + if (line >= start && line < end) + { + sect2->lines.Push(aline); + } + } + + int firstnewline = numsectionlines; + int thisline = numsectionlines; + int splitline1, splitline2; + //numsectionlines += sect1->lines.Size() + 1; + for (unsigned i = 0; i < sect1->lines.Size(); i++)// auto& sline : sect1->lines) + { + int sline = sect1->lines[i]; + sect1->lines[i] = thisline; + if (sline != -1) + { + SectionLine& newline = sectionLines[thisline]; + newline = sectionLines[sline]; + newline.section = int16_t(sect1 - sections); + if (i != sect1->lines.Size() - 1) newline.point2index = thisline + 1 - firstnewline; + else newline.point2index = 0; + assert(newline.point2index >= 0); + + // relink the partner + auto& partnerline = sectionLines[newline.partner]; + partnerline.partner = thisline; + partnerline.partnersection = newline.section; + thisline++; + } + else + { + splitline1 = thisline++; + sectionLines[splitline1].wall = -1; + sectionLines[splitline1].section = int16_t(sect1 - sections); + sectionLines[splitline1].partnersection = int16_t(sect2 - sections); + sectionLines[splitline1].startpoint = start; + sectionLines[splitline1].endpoint = end; + sectionLines[splitline1].point2index = splitline1 + 1 - firstnewline; + } + } + + firstnewline = thisline; + for (unsigned i = 0; i < sect2->lines.Size(); i++)// auto& sline : sect1->lines) + { + int sline = sect2->lines[i]; + sect2->lines[i] = thisline; + if (sline != -1) + { + SectionLine& newline = sectionLines[thisline]; + newline = sectionLines[sline]; + newline.section = int16_t(sect2 - sections); + if (i != sect2->lines.Size() - 1) newline.point2index = thisline + 1 - firstnewline; + else newline.point2index = 0; + assert(newline.point2index >= 0); + + // relink the partner + auto& partnerline = sectionLines[newline.partner]; + partnerline.partner = thisline; + partnerline.partnersection = newline.section; + thisline++; + } + else + { + splitline2 = thisline++; + sectionLines[splitline2].wall = -1; + sectionLines[splitline2].section = int16_t(sect2 - sections); + sectionLines[splitline2].partnersection = int16_t(sect1 - sections); + sectionLines[splitline2].startpoint = end; + sectionLines[splitline2].endpoint = start; + sectionLines[splitline2].point2index = splitline2 + 1 - firstnewline; + } + } + sectionLines[splitline1].partner = splitline2; + sectionLines[splitline2].partner = splitline1; + + sectionspersector[sect.sector].Resize(2); + sectionspersector[sect.sector][0] = int16_t(sect1 - sections); + sectionspersector[sect.sector][1] = int16_t(sect2 - sections); +} + +void hw_SplitSector(int sectnum, int start, int end) +{ + int wallstart = sector[sectnum].wallptr; + int wallend = wallstart + sector[sectnum].wallnum; + if (start < wallstart || start >= wallend || end < wallstart || end >= wallend || end < start) return; + + for (unsigned i = 0; i < sectionspersector[sectnum].Size(); i++) + { + int sect = sectionspersector[sectnum][i]; + bool foundstart = false, foundend = false; + for (int aline : sections[sect].lines) + { + int line = sectionLines[aline].wall; + if (line == start) foundstart = true; + if (line == end) foundend = true; + } + if (foundstart && foundend) + { + sectionspersector->Delete(i); + SplitSection(sect, start, end); + return; + } + } +} + +void hw_SetSplitSector(int sectnum, int start, int end) +{ + splits.Push(sectnum); + splits.Push(start); + splits.Push(end); +} diff --git a/source/core/rendering/hw_sections.h b/source/core/rendering/hw_sections.h index e95424beb..645d0e6e6 100644 --- a/source/core/rendering/hw_sections.h +++ b/source/core/rendering/hw_sections.h @@ -29,3 +29,4 @@ extern int numsectionlines; void hw_BuildSections(); +void hw_SetSplitSector(int sector, int startpos, int endpos); diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index e6299e618..50ef2995a 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -283,24 +283,27 @@ void BunchDrawer::ProcessBunch(int bnch) if (clipped & CL_Draw) { - for (auto p : blockingpairs[i]) blockwall.Set(sectionLines[p].wall); - show2dwall.Set(sectionLines[i].wall); - - if (!gotwall[i]) + int ww = sectionLines[i].wall; + if (ww != -1) { - gotwall.Set(i); - ClipWall.Unclock(); - Bsp.Unclock(); - SetupWall.Clock(); + for (auto p : blockingpairs[ww]) blockwall.Set(sectionLines[p].wall); + show2dwall.Set(ww); - HWWall hwwall; - int j = sectionLines[i].wall; - hwwall.Process(di, &wall[j], §or[bunch->sectnum], wall[j].nextsector < 0 ? nullptr : §or[wall[j].nextsector]); - rendered_lines++; + if (!gotwall[i]) + { + gotwall.Set(i); + ClipWall.Unclock(); + Bsp.Unclock(); + SetupWall.Clock(); - SetupWall.Unclock(); - Bsp.Clock(); - ClipWall.Clock(); + HWWall hwwall; + hwwall.Process(di, &wall[ww], §or[bunch->sectnum], wall[ww].nextsector < 0 ? nullptr : §or[wall[ww].nextsector]); + rendered_lines++; + + SetupWall.Unclock(); + Bsp.Clock(); + ClipWall.Clock(); + } } } diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index 9b8a9ae16..a0fd0dc87 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -58,6 +58,7 @@ #include "gamefuncs.h" #include "render.h" #include "hw_sections.h" +#include "sectorgeometry.h" #include @@ -641,6 +642,7 @@ void SerializeMap(FSerializer& arc) { setWallSectors(); hw_BuildSections(); + sectorGeometry.SetSize(numsections); } } diff --git a/source/games/blood/src/db.cpp b/source/games/blood/src/db.cpp index c1826cd4e..cb6a53c9c 100644 --- a/source/games/blood/src/db.cpp +++ b/source/games/blood/src/db.cpp @@ -33,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "raze_sound.h" #include "gamefuncs.h" #include "hw_sections.h" +#include "sectorgeometry.h" #include "blood.h" @@ -1069,6 +1070,7 @@ void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, shor setWallSectors(); hw_BuildSections(); + sectorGeometry.SetSize(numsections); memcpy(wallbackup, wall, sizeof(wallbackup)); memcpy(sectorbackup, sector, sizeof(sectorbackup)); } diff --git a/wadsrc/static/engine/compatibility/c3bfb6a6e7cded2e5fe16cea86632d79.mhk b/wadsrc/static/engine/compatibility/c3bfb6a6e7cded2e5fe16cea86632d79.mhk new file mode 100644 index 000000000..5d24c10b7 --- /dev/null +++ b/wadsrc/static/engine/compatibility/c3bfb6a6e7cded2e5fe16cea86632d79.mhk @@ -0,0 +1,2 @@ +// CP07 sector bleeds into another area. +sector 33 split 192 196