From 30b1b046e47e5e4da5d60c28be525da5539c7cec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 3 May 2021 00:04:36 +0200 Subject: [PATCH] - added an intermediate data structure to decouple the rendering from the immediate map data. This will be needed for sectors consisting of disjoint parts and for providing some help with addressing rendering anomalies --- source/CMakeLists.txt | 1 + source/core/maploader.cpp | 2 + source/core/rendering/hw_sections.cpp | 75 +++++++++++++++++++++++++++ source/core/rendering/hw_sections.h | 31 +++++++++++ source/core/savegamehelp.cpp | 2 + source/core/sectorgeometry.cpp | 70 ++++++++++++++----------- source/games/blood/src/db.cpp | 2 + 7 files changed, 152 insertions(+), 31 deletions(-) create mode 100644 source/core/rendering/hw_sections.cpp create mode 100644 source/core/rendering/hw_sections.h 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)); }