- removed SectorGeometry class.

This commit is contained in:
Christoph Oelckers 2021-12-15 12:26:38 +01:00
parent 7a9596ae81
commit bb9313454d
6 changed files with 1 additions and 415 deletions

View file

@ -491,7 +491,6 @@ void engineLoadBoard(const char* filename, int flags, vec3_t* pos, int16_t* ang,
setWallSectors();
hw_BuildSections();
hw_CreateSections2();
sectorGeometry.SetSize(Sections.Size());
sectionGeometry.SetSize(sections2.Size());

View file

@ -372,378 +372,3 @@ public:
}
};
// moved out of the way
//==========================================================================
//
//
//
//==========================================================================
bool SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2& offset)
{
auto sec = &Sections[secnum];
auto sectorp = &sector[sec->sector];
int numvertices = sec->lines.Size();
TArray<FVector3> points(numvertices, true);
using Point = std::pair<float, float>;
std::vector<std::vector<Point>> polygon;
std::vector<Point>* curPoly;
polygon.resize(1);
curPoly = &polygon.back();
FixedBitArray<MAXWALLSB> done;
int fz = sectorp->floorz, cz = sectorp->ceilingz;
int vertstoadd = numvertices;
done.Zero();
while (vertstoadd > 0)
{
int start = 0;
while (done[start] && start < numvertices) start++;
int s = start;
if (start >= 0 && start < numvertices)
{
while (start >= 0 && start < numvertices && !done[start])
{
auto sline = &sectionLines[sec->lines[start]];
auto wallp = &wall[sline->startpoint];
float X = float(WallStartX(wallp));
float Y = float(WallStartY(wallp));
if (fabs(X) > 32768.f || fabs(Y) > 32768.f)
{
// If we get here there's some fuckery going around with the coordinates. Let's better abort and wait for things to realign.
// Do not try alternative methods if this happens.
return true;
}
curPoly->push_back(std::make_pair(X, Y));
done.Set(start);
vertstoadd--;
start = sline->point2index;
}
polygon.resize(polygon.size() + 1);
curPoly = &polygon.back();
if (start != s) return false; // means the sector is badly defined. RRRA'S E1L3 triggers this.
}
}
// Now make sure that the outer boundary is the first polygon by picking a point that's as much to the outside as possible.
int outer = 0;
float minx = FLT_MAX;
float miny = FLT_MAX;
for (size_t a = 0; a < polygon.size(); a++)
{
for (auto& pt : polygon[a])
{
if (pt.first < minx || (pt.first == minx && pt.second < miny))
{
minx = pt.first;
miny = pt.second;
outer = int(a);
}
}
}
if (outer != 0) std::swap(polygon[0], polygon[outer]);
auto indices = mapbox::earcut(polygon);
if (indices.size() < 3 * (sec->lines.Size() - 2))
{
// this means that full triangulation failed.
return false;
}
sectorp->floorz = sectorp->ceilingz = 0;
int p = 0;
for (size_t a = 0; a < polygon.size(); a++)
{
for (auto& pt : polygon[a])
{
float planez = 0;
PlanesAtPoint(sectorp, (pt.first * 16), (pt.second * -16), plane ? &planez : nullptr, !plane ? &planez : nullptr);
FVector3 point = { pt.first, pt.second, planez };
points[p++] = point;
}
}
auto& entry = data[secnum].planes[plane];
entry.vertices.Resize((unsigned)indices.size());
entry.texcoords.Resize((unsigned)indices.size());
entry.normal = CalcNormal(sectorp, plane);
auto texture = tileGetTexture(plane ? sectorp->ceilingpicnum : sectorp->floorpicnum);
UVCalculator1 uvcalc(sectorp, plane, texture, offset);
for(unsigned i = 0; i < entry.vertices.Size(); i++)
{
auto& pt = points[indices[i]];
entry.vertices[i] = pt;
entry.texcoords[i] = uvcalc.GetUV(int(pt.X * 16), int(pt.Y * -16), pt.Z);
}
sectorp->floorz = fz;
sectorp->ceilingz = cz;
return true;
}
//==========================================================================
//
// Use ZDoom's node builder if the simple approach fails.
// This will create something usable in the vast majority of cases,
// even if the result is less efficient.
//
//==========================================================================
bool SectorGeometry::MakeVertices2(unsigned int secnum, int plane, const FVector2& offset)
{
auto sec = &Sections[secnum];
auto sectorp = &sector[sec->sector];
int numvertices = sec->lines.Size();
// Convert our sector into something the node builder understands
TArray<vertex_t> vertexes(sectorp->wallnum, true);
TArray<line_t> lines(numvertices, true);
TArray<side_t> sides(numvertices, true);
int j = 0;
for (int i = 0; i < numvertices; i++)
{
auto sline = &sectionLines[sec->lines[i]];
if (sline->point2index < 0) continue; // Exhumed LEV14 triggers this on sector 169.
auto wallp = &wall[sline->startpoint];
vertexes[j].p = { wallp->x * (1 / 16.), wallp->y * (1 / -16.) };
if (fabs(vertexes[j].p.X) > 32768.f || fabs(vertexes[j].p.Y) > 32768.f)
{
// If we get here there's some fuckery going around with the coordinates. Let's better abort and wait for things to realign.
return true;
}
lines[j].backsector = nullptr;
lines[j].frontsector = sectorp;
lines[j].linenum = j;
lines[j].wallnum = sline->wall;
lines[j].sidedef[0] = &sides[j];
lines[j].sidedef[1] = nullptr;
lines[j].v1 = &vertexes[j];
lines[j].v2 = &vertexes[sline->point2index + j - i];
sides[j].sidenum = j;
sides[j].sector = sectorp;
j++;
}
vertexes.Clamp(j);
lines.Clamp(j);
sides.Clamp(j);
// Weed out any overlaps. These often happen with door setups and can lead to bad subsectors
for (unsigned i = 0; i < lines.Size(); i++)
{
auto p1 = lines[i].v1->p, p2 = lines[i].v2->p;
// Throw out any line with zero length.
if (p1 == p2)
{
lines.Delete(i);
i--;
continue;
}
for (unsigned j = i + 1; j < lines.Size(); j++)
{
auto pp1 = lines[j].v1->p, pp2 = lines[j].v2->p;
if (pp1 == p2 && pp2 == p1)
{
// handle the simple case first, i.e. line j is the inverse of line i.
// in this case both lines need to be deleted.
lines.Delete(j);
lines.Delete(i);
i--;
goto nexti;
}
else if (pp1 == p2)
{
// only the second line's start point matches.
// In this case we have to delete the shorter line and truncate the other one.
// check if the second line's end point is on the line we are checking
double d1 = PointOnLineSide(pp2, p1, p2);
if (fabs(d1) > FLT_EPSILON) continue; // not colinear
bool vert = p1.X == p2.X;
double p1x = vert ? p1.X : p1.Y;
double p2x = vert ? p2.X : p2.Y;
double pp1x = vert ? pp1.X : pp1.Y;
double pp2x = vert ? pp2.X : pp2.Y;
if (pp2x > min(p1x, p2x) && pp2x < max(p1x, p2x))
{
// pp2 is on line i.
lines[i].v2 = lines[j].v2;
lines.Delete(j);
continue;
}
else if (p1x > min(pp1x, pp2x) && p1x < max(pp1x, pp2x))
{
// p1 is on line j
lines[j].v1 = lines[j].v2;
lines.Delete(i);
goto nexti;
}
}
else if (pp2 == p1)
{
// only the second line's start point matches.
// In this case we have to delete the shorter line and truncate the other one.
// check if the second line's end point is on the line we are checking
double d1 = PointOnLineSide(pp1, p1, p2);
if (fabs(d1) > FLT_EPSILON) continue; // not colinear
bool vert = p1.X == p2.X;
double p1x = vert ? p1.X : p1.Y;
double p2x = vert ? p2.X : p2.Y;
double pp1x = vert ? pp1.X : pp1.Y;
double pp2x = vert ? pp2.X : pp2.Y;
if (pp1x > min(p1x, p2x) && pp1x < max(p1x, p2x))
{
// pp1 is on line i.
lines[i].v1 = lines[j].v1;
lines.Delete(j);
continue;
}
else if (p2x > min(pp1x, pp2x) && p2x < max(pp1x, pp2x))
{
// p2 is on line j
lines[j].v2 = lines[j].v1;
lines.Delete(i);
goto nexti;
}
}
else
{
// no idea if we should do further checks here. Blood's doors do not need them. We'll see.
}
}
nexti:;
}
if (lines.Size() < 4)
{
// nothing to generate. If line count is < 4 this sector is degenerate and should not be processed further.
auto& entry = data[secnum].planes[plane];
entry.vertices.Clear();
entry.texcoords.Clear();
return true;
}
FNodeBuilder::FLevel leveldata =
{
&vertexes[0], (int)vertexes.Size(),
&sides[0], (int)sides.Size(),
&lines[0], (int)lines.Size(),
0, 0, 0, 0
};
leveldata.FindMapBounds();
FNodeBuilder builder(leveldata);
FLevelLocals Level;
builder.Extract(Level);
// Now turn the generated subsectors into triangle meshes
auto& entry = data[secnum].planes[plane];
entry.vertices.Clear();
entry.texcoords.Clear();
int fz = sectorp->floorz, cz = sectorp->ceilingz;
sectorp->floorz = sectorp->ceilingz = 0;
for (auto& sub : Level.subsectors)
{
if (sub.numlines <= 2) continue;
auto v0 = sub.firstline->v1;
for (unsigned i = 1; i < sub.numlines - 1; i++)
{
auto v1 = sub.firstline[i].v1;
auto v2 = sub.firstline[i].v2;
entry.vertices.Push({ (float)v0->fX(), (float)v0->fY(), 0 });
entry.vertices.Push({ (float)v1->fX(), (float)v1->fY(), 0 });
entry.vertices.Push({ (float)v2->fX(), (float)v2->fY(), 0 });
}
}
// calculate the rest.
auto texture = tileGetTexture(plane ? sectorp->ceilingpicnum : sectorp->floorpicnum);
UVCalculator1 uvcalc(sectorp, plane, texture, offset);
entry.texcoords.Resize(entry.vertices.Size());
for (unsigned i = 0; i < entry.vertices.Size(); i++)
{
auto& pt = entry.vertices[i];
float planez = 0;
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(sectorp, plane);
sectorp->floorz = fz;
sectorp->ceilingz = cz;
return true;
}
//==========================================================================
//
//
//
//==========================================================================
void SectorGeometry::ValidateSector(unsigned int secnum, int plane, const FVector2& offset)
{
auto sec = &sector[Sections[secnum].sector];
auto compare = &data[secnum].compare[plane];
if (plane == 0)
{
if (sec->floorheinum == compare->floorheinum &&
sec->floorpicnum == compare->floorpicnum &&
((sec->floorstat ^ compare->floorstat) & (CSTAT_SECTOR_ALIGN | CSTAT_SECTOR_YFLIP | CSTAT_SECTOR_XFLIP | CSTAT_SECTOR_TEXHALF | CSTAT_SECTOR_SWAPXY)) == 0 &&
sec->floorxpan_ == compare->floorxpan_ &&
sec->floorypan_ == compare->floorypan_ &&
sec->firstWall()->pos == data[secnum].poscompare[0] &&
sec->firstWall()->point2Wall()->pos == data[secnum].poscompare2[0] &&
!(sec->dirty & 1) && data[secnum].planes[plane].vertices.Size() ) return;
sec->dirty &= ~1;
}
else
{
if (sec->ceilingheinum == compare->ceilingheinum &&
sec->ceilingpicnum == compare->ceilingpicnum &&
((sec->ceilingstat ^ compare->ceilingstat) & (CSTAT_SECTOR_ALIGN | CSTAT_SECTOR_YFLIP | CSTAT_SECTOR_XFLIP | CSTAT_SECTOR_TEXHALF | CSTAT_SECTOR_SWAPXY)) == 0 &&
sec->ceilingxpan_ == compare->ceilingxpan_ &&
sec->ceilingypan_ == compare->ceilingypan_ &&
sec->firstWall()->pos == data[secnum].poscompare[1] &&
sec->firstWall()->point2Wall()->pos == data[secnum].poscompare2[1] &&
!(sec->dirty & 2) && data[secnum].planes[1].vertices.Size()) return;
sec->dirty &= ~2;
}
*compare = *sec;
data[secnum].poscompare[plane] = sec->firstWall()->pos;
data[secnum].poscompare2[plane] = sec->firstWall()->point2Wall()->pos;
if (data[secnum].degenerate || !MakeVertices(secnum, plane, offset))
{
data[secnum].degenerate = true;
//Printf(TEXTCOLOR_YELLOW "Normal triangulation failed for sector %d. Retrying with alternative approach\n", secnum);
MakeVertices2(secnum, plane, offset);
}
}

View file

@ -727,7 +727,7 @@ void SerializeMap(FSerializer& arc)
setWallSectors();
hw_BuildSections();
hw_CreateSections2();
sectorGeometry.SetSize(Sections.Size());
sectionGeometry.SetSize(sections2.Size());
}
}

View file

@ -43,7 +43,6 @@
#include "hw_sections2.h"
#include "tesselator.h"
SectorGeometry sectorGeometry;
SectionGeometry sectionGeometry;
//==========================================================================

View file

@ -13,41 +13,6 @@ struct SectorGeometryPlane
FVector3 normal{};
};
struct SectorGeometryData
{
SectorGeometryPlane planes[2];
sectortype compare[2] = {};
vec2_t poscompare[2] = {};
vec2_t poscompare2[2] = {};
bool degenerate = false;
};
class SectorGeometry
{
TArray<SectorGeometryData> data;
void ValidateSector(unsigned sectnum, int plane, const FVector2& offset);
bool MakeVertices(unsigned sectnum, int plane, const FVector2& offset);
bool MakeVertices2(unsigned sectnum, int plane, const FVector2& offset);
public:
SectorGeometryPlane* get(unsigned sectnum, int plane, const FVector2& offset)
{
if (sectnum >= data.Size()) return nullptr;
ValidateSector(sectnum, plane, offset);
return &data[sectnum].planes[plane];
}
void SetSize(unsigned sectcount)
{
data.Clear(); // delete old content
data.Resize(sectcount);
}
};
extern SectorGeometry sectorGeometry;
enum GeomFlags
{
NoEarcut = 1,
@ -89,7 +54,6 @@ public:
}
};
extern SectorGeometry sectorGeometry;
extern SectionGeometry sectionGeometry;

View file

@ -730,7 +730,6 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect
setWallSectors();
hw_BuildSections();
hw_CreateSections2();
sectorGeometry.SetSize(Sections.Size());
sectionGeometry.SetSize(sections2.Size());
wallbackup = wall;
sectorbackup = sector;