diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 55f5bcc6f..35c1265ca 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1082,6 +1082,7 @@ set (PCH_SOURCES core/rendering/hw_models.cpp core/rendering/hw_voxels.cpp core/rendering/hw_palmanager.cpp + core/rendering/hw_sections.cpp core/rendering/scene/hw_clipper.cpp core/rendering/scene/hw_walls.cpp core/rendering/scene/hw_flats.cpp diff --git a/source/core/maploader.cpp b/source/core/maploader.cpp index 0693975d4..fd91152d5 100644 --- a/source/core/maploader.cpp +++ b/source/core/maploader.cpp @@ -44,6 +44,7 @@ #include "gamefuncs.h" #include "sectorgeometry.h" #include "render.h" +#include "hw_sections.h" static void ReadSectorV7(FileReader& fr, sectortype& sect) { @@ -451,6 +452,7 @@ void engineLoadBoard(const char* filename, int flags, vec3_t* pos, int16_t* ang, md4once(buffer.Data(), buffer.Size(), md4); G_LoadMapHack(filename, md4); setWallSectors(); + hw_BuildSections(); memcpy(wallbackup, wall, sizeof(wallbackup)); memcpy(sectorbackup, sector, sizeof(sectorbackup)); diff --git a/source/core/rendering/hw_sections.cpp b/source/core/rendering/hw_sections.cpp new file mode 100644 index 000000000..8cb353d03 --- /dev/null +++ b/source/core/rendering/hw_sections.cpp @@ -0,0 +1,75 @@ +/* +** hw_sectiona.cpp +** For decoupling the renderer from internal Build structures +** +**--------------------------------------------------------------------------- +** Copyright 2021 Christoph Oelckers +** All rights reserved. +** +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +** The sole reason for existence of this file is that Build's sector setup +** does not allow for easy splitting of sectors, either for having disjoint parts +** or requiring partial rendering. So we need to add a superstructure +** where we can shuffle around some content without disturbing the original +** order... +** +*/ + + +#include "hw_sections.h" + + +SectionLine sectionLines[MAXWALLS + (MAXWALLS >> 2)]; +Section sections[MAXSECTORS + (MAXSECTORS >> 2)]; +TArray sectionspersector[MAXSECTORS]; // reverse map, mainly for the automap +int numsections; +int numsectionlines; + + +void hw_BuildSections() +{ + // Initial setup just creates a 1:1 mapping of walls to section lines and sectors to sections. + numsectionlines = numwalls; + numsections = numsectors; + for (int i = 0; i < numwalls; i++) + { + sectionLines[i].startpoint = sectionLines[i].wall = i; + sectionLines[i].endpoint = wall[i].point2; + sectionLines[i].partner = wall[i].nextwall; + sectionLines[i].section = wall[i].sector; + sectionLines[i].partnersection = wall[i].nextsector; + sectionLines[i].point2index = wall[i].point2 - sector[wall[i].sector].wallptr; + } + + for (int i = 0; i < numsectors; i++) + { + sections[i].sector = i; + sections[i].lines.Resize(sector[i].wallnum); + for (int j = 0; j < sector[i].wallnum; j++) sections[i].lines[j] = sector[i].wallptr + j; + sectionspersector[i].Resize(1); + sectionspersector[i][0] = i; + } +} \ No newline at end of file diff --git a/source/core/rendering/hw_sections.h b/source/core/rendering/hw_sections.h new file mode 100644 index 000000000..e95424beb --- /dev/null +++ b/source/core/rendering/hw_sections.h @@ -0,0 +1,31 @@ +#pragma once + +#include "build.h" + +struct SectionLine +{ + int16_t section; + int16_t partnersection; + int16_t startpoint; + int16_t endpoint; + int16_t wall; + int16_t partner; + int16_t point2index; +}; + +struct Section +{ + int sector; + // this is the whole point of sections - instead of just having a start index and count, we have an explicit list of lines that's a lot easier to change when needed. + TArray lines; +}; + +// giving 25% more may be a bit high as normally this should be small numbers only. +extern SectionLine sectionLines[MAXWALLS + (MAXWALLS >> 2)]; +extern Section sections[MAXSECTORS + (MAXSECTORS >> 2)]; +extern TArray sectionspersector[MAXSECTORS]; // reverse map, mainly for the automap +extern int numsections; +extern int numsectionlines; + + +void hw_BuildSections(); diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index abc75f30b..9b8a9ae16 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -57,6 +57,7 @@ #include "interpolate.h" #include "gamefuncs.h" #include "render.h" +#include "hw_sections.h" #include @@ -639,6 +640,7 @@ void SerializeMap(FSerializer& arc) if (arc.isReading()) { setWallSectors(); + hw_BuildSections(); } } diff --git a/source/core/sectorgeometry.cpp b/source/core/sectorgeometry.cpp index dad3e808b..4db5b3617 100644 --- a/source/core/sectorgeometry.cpp +++ b/source/core/sectorgeometry.cpp @@ -39,6 +39,7 @@ #include "gamefuncs.h" #include "texturemanager.h" #include "earcut.hpp" +#include "hw_sections.h" #include "nodebuilder/nodebuild.h" SectorGeometry sectorGeometry; @@ -217,8 +218,9 @@ public: bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2& offset) { - auto sec = §or[secnum]; - int numvertices = sec->wallnum; + auto sec = §ions[secnum]; + auto sectorp = §or[sec->sector]; + int numvertices = sec->lines.Size(); TArray points(numvertices, true); using Point = std::pair; @@ -229,7 +231,7 @@ bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2 curPoly = &polygon.back(); FixedBitArray done; - int fz = sec->floorz, cz = sec->ceilingz; + int fz = sectorp->floorz, cz = sectorp->ceilingz; int vertstoadd = numvertices; @@ -243,7 +245,8 @@ bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2 { while (!done[start]) { - auto wallp = &wall[sec->wallptr + start]; + auto sline = §ionLines[sec->lines[start]]; + auto wallp = &wall[sline->startpoint]; float X = WallStartX(wallp); float Y = WallStartY(wallp); if (fabs(X) > 32768. || fabs(Y) > 32768.) @@ -255,7 +258,7 @@ bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2 curPoly->push_back(std::make_pair(X, Y)); done.Set(start); vertstoadd--; - start = wallp->point2 - sec->wallptr; + start = sline->point2index; } polygon.resize(polygon.size() + 1); curPoly = &polygon.back(); @@ -280,12 +283,12 @@ bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2 } if (outer != 0) std::swap(polygon[0], polygon[outer]); auto indices = mapbox::earcut(polygon); - if (indices.size() < 3 * (sec->wallnum - 2)) + if (indices.size() < 3 * (sec->lines.Size() - 2)) { // this means that full triangulation failed. return false; } - sec->floorz = sec->ceilingz = 0; + sectorp->floorz = sectorp->ceilingz = 0; int p = 0; for (size_t a = 0; a < polygon.size(); a++) @@ -293,7 +296,7 @@ bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2 for (auto& pt : polygon[a]) { float planez; - PlanesAtPoint(sec, (pt.first * 16), (pt.second * -16), plane ? &planez : nullptr, !plane ? &planez : nullptr); + PlanesAtPoint(sectorp, (pt.first * 16), (pt.second * -16), plane ? &planez : nullptr, !plane ? &planez : nullptr); FVector3 point = { pt.first, pt.second, planez }; points[p++] = point; } @@ -302,11 +305,11 @@ bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2 auto& entry = data[secnum].planes[plane]; entry.vertices.Resize(indices.size()); entry.texcoords.Resize(indices.size()); - entry.normal = CalcNormal(sec, plane); + entry.normal = CalcNormal(sectorp, plane); - auto texture = tileGetTexture(plane ? sec->ceilingpicnum : sec->floorpicnum); + auto texture = tileGetTexture(plane ? sectorp->ceilingpicnum : sectorp->floorpicnum); - UVCalculator uvcalc(sec, plane, texture, offset); + UVCalculator uvcalc(sectorp, plane, texture, offset); for(unsigned i = 0; i < entry.vertices.Size(); i++) { @@ -315,8 +318,8 @@ bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2 entry.texcoords[i] = uvcalc.GetUV(int(pt.X * 16), int(pt.Y * -16), pt.Z); } - sec->floorz = fz; - sec->ceilingz = cz; + sectorp->floorz = fz; + sectorp->ceilingz = cz; return true; } @@ -330,26 +333,30 @@ bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2 bool SectorGeometry::MakeVertices2(unsigned int secnum, int plane, const FVector2& offset) { + auto sec = §ions[secnum]; + auto sectorp = §or[sec->sector]; + int numvertices = sec->lines.Size(); // Convert our sector into something the node builder understands - auto sect = §or[secnum]; - TArray vertexes(sect->wallnum, true); - TArray lines(sect->wallnum, true); - TArray sides(sect->wallnum, true); - for (int i = 0; i < sect->wallnum; i++) + TArray vertexes(sectorp->wallnum, true); + TArray lines(numvertices, true); + TArray sides(numvertices, true); + for (int i = 0; i < numvertices; i++) { - auto wal = &wall[sect->wallptr + i]; + auto sline = §ionLines[sec->lines[i]]; + auto wal = &wall[sline->startpoint]; vertexes[i].p = { wal->x * (1 / 16.), wal->y * (1 / -16.) }; + lines[i].backsector = nullptr; - lines[i].frontsector = sect; + lines[i].frontsector = sectorp; lines[i].linenum = i; lines[i].sidedef[0] = &sides[i]; lines[i].sidedef[1] = nullptr; lines[i].v1 = &vertexes[i]; - lines[i].v2 = &vertexes[wal->point2 - sect->wallptr]; + lines[i].v2 = &vertexes[sline->point2index]; sides[i].sidenum = i; - sides[i].sector = sect; + sides[i].sector = sectorp; } @@ -372,8 +379,8 @@ bool SectorGeometry::MakeVertices2(unsigned int secnum, int plane, const FVector entry.vertices.Clear(); entry.texcoords.Clear(); - int fz = sect->floorz, cz = sect->ceilingz; - sect->floorz = sect->ceilingz = 0; + int fz = sectorp->floorz, cz = sectorp->ceilingz; + sectorp->floorz = sectorp->ceilingz = 0; for (auto& sub : Level.subsectors) { @@ -391,9 +398,9 @@ bool SectorGeometry::MakeVertices2(unsigned int secnum, int plane, const FVector } // calculate the rest. - auto texture = tileGetTexture(plane ? sect->ceilingpicnum : sect->floorpicnum); + auto texture = tileGetTexture(plane ? sectorp->ceilingpicnum : sectorp->floorpicnum); - UVCalculator uvcalc(sect, plane, texture, offset); + UVCalculator uvcalc(sectorp, plane, texture, offset); entry.texcoords.Resize(entry.vertices.Size()); for (unsigned i = 0; i < entry.vertices.Size(); i++) @@ -401,13 +408,13 @@ bool SectorGeometry::MakeVertices2(unsigned int secnum, int plane, const FVector auto& pt = entry.vertices[i]; float planez; - PlanesAtPoint(sect, (pt.X * 16), (pt.Y * -16), plane ? &planez : nullptr, !plane ? &planez : nullptr); + PlanesAtPoint(sectorp, (pt.X * 16), (pt.Y * -16), plane ? &planez : nullptr, !plane ? &planez : nullptr); entry.vertices[i].Z = planez; entry.texcoords[i] = uvcalc.GetUV(int(pt.X * 16.), int(pt.Y * -16.), pt.Z); } - entry.normal = CalcNormal(sect, plane); - sect->floorz = fz; - sect->ceilingz = cz; + entry.normal = CalcNormal(sectorp, plane); + sectorp->floorz = fz; + sectorp->ceilingz = cz; return true; } @@ -419,7 +426,8 @@ bool SectorGeometry::MakeVertices2(unsigned int secnum, int plane, const FVector void SectorGeometry::ValidateSector(unsigned int secnum, int plane, const FVector2& offset) { - auto sec = §or[secnum]; + auto sec = §or[sections[secnum].sector]; + auto compare = &data[secnum].compare[plane]; if (plane == 0) { diff --git a/source/games/blood/src/db.cpp b/source/games/blood/src/db.cpp index 52c0f0273..c1826cd4e 100644 --- a/source/games/blood/src/db.cpp +++ b/source/games/blood/src/db.cpp @@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "automap.h" #include "raze_sound.h" #include "gamefuncs.h" +#include "hw_sections.h" #include "blood.h" @@ -1067,6 +1068,7 @@ void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, shor } setWallSectors(); + hw_BuildSections(); memcpy(wallbackup, wall, sizeof(wallbackup)); memcpy(sectorbackup, sector, sizeof(sectorbackup)); }