mirror of https://github.com/ZDoom/zdbsp.git
- Added code to explicitly handle outputting overlapping segs when
building GL nodes with ZDBSP, removing the check that discarded them early on. SVN r157 (trunk)
This commit is contained in:
parent
938f25e39b
commit
8617f499d5
169
nodebuild.cpp
169
nodebuild.cpp
|
@ -65,6 +65,7 @@ void FNodeBuilder::BuildTree ()
|
||||||
|
|
||||||
fprintf (stderr, " BSP: 0.0%%\r");
|
fprintf (stderr, " BSP: 0.0%%\r");
|
||||||
HackSeg = DWORD_MAX;
|
HackSeg = DWORD_MAX;
|
||||||
|
HackMate = DWORD_MAX;
|
||||||
CreateNode (0, bbox);
|
CreateNode (0, bbox);
|
||||||
CreateSubsectorsForReal ();
|
CreateSubsectorsForReal ();
|
||||||
fprintf (stderr, " BSP: 100.0%%\n");
|
fprintf (stderr, " BSP: 100.0%%\n");
|
||||||
|
@ -195,7 +196,8 @@ void FNodeBuilder::CreateSubsectorsForReal ()
|
||||||
D(printf ("Output subsector %d:\n", Subsectors.Size()));
|
D(printf ("Output subsector %d:\n", Subsectors.Size()));
|
||||||
for (unsigned int i = sub.firstline; i < SegList.Size(); ++i)
|
for (unsigned int i = sub.firstline; i < SegList.Size(); ++i)
|
||||||
{
|
{
|
||||||
D(printf (" Seg %5d (%5d,%5d)-(%5d,%5d)\n", SegList[i].SegPtr - &Segs[0],
|
D(printf (" Seg %5d%c(%5d,%5d)-(%5d,%5d)\n", SegList[i].SegPtr - &Segs[0],
|
||||||
|
SegList[i].SegPtr->linedef == -1 ? '+' : ' ',
|
||||||
Vertices[SegList[i].SegPtr->v1].x>>16,
|
Vertices[SegList[i].SegPtr->v1].x>>16,
|
||||||
Vertices[SegList[i].SegPtr->v1].y>>16,
|
Vertices[SegList[i].SegPtr->v1].y>>16,
|
||||||
Vertices[SegList[i].SegPtr->v2].x>>16,
|
Vertices[SegList[i].SegPtr->v2].x>>16,
|
||||||
|
@ -293,7 +295,8 @@ bool FNodeBuilder::CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
D(Printf (" - seg %d(%d,%d)-(%d,%d) line %d front %d back %d\n", seg,
|
D(Printf (" - seg %d%c(%d,%d)-(%d,%d) line %d front %d back %d\n", seg,
|
||||||
|
Segs[seg].linedef == -1 ? '+' : ' ',
|
||||||
Vertices[Segs[seg].v1].x>>16, Vertices[Segs[seg].v1].y>>16,
|
Vertices[Segs[seg].v1].x>>16, Vertices[Segs[seg].v1].y>>16,
|
||||||
Vertices[Segs[seg].v2].x>>16, Vertices[Segs[seg].v2].y>>16,
|
Vertices[Segs[seg].v2].x>>16, Vertices[Segs[seg].v2].y>>16,
|
||||||
Segs[seg].linedef, Segs[seg].frontsector, Segs[seg].backsector));
|
Segs[seg].linedef, Segs[seg].frontsector, Segs[seg].backsector));
|
||||||
|
@ -322,7 +325,11 @@ bool FNodeBuilder::CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int
|
||||||
} while (seg != DWORD_MAX);
|
} while (seg != DWORD_MAX);
|
||||||
|
|
||||||
if (seg == DWORD_MAX)
|
if (seg == DWORD_MAX)
|
||||||
{ // It's a valid subsector
|
{ // It's a valid non-GL subsector, and probably a valid GL subsector too.
|
||||||
|
if (GLNodes)
|
||||||
|
{
|
||||||
|
return CheckSubsectorOverlappingSegs (set, node, splitseg);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,20 +340,60 @@ bool FNodeBuilder::CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int
|
||||||
// from multiple sectors, and it seems ZenNode does something
|
// from multiple sectors, and it seems ZenNode does something
|
||||||
// similar. It is the only technique I could find that makes the
|
// similar. It is the only technique I could find that makes the
|
||||||
// "transparent water" in nb_bmtrk.wad work properly.
|
// "transparent water" in nb_bmtrk.wad work properly.
|
||||||
//
|
return ShoveSegBehind (set, node, seg, DWORD_MAX);
|
||||||
// The seg is marked to indicate that it should be forced to the
|
}
|
||||||
// back of the splitter. Because these segs already form a convex
|
|
||||||
// set, all the other segs will be in front of the splitter. Since
|
|
||||||
// the splitter is formed from this seg, the back of the splitter
|
|
||||||
// will have a one-dimensional subsector. SplitSegs() will add two
|
|
||||||
// new minisegs to close it: one seg replaces this one on the front
|
|
||||||
// of the splitter, and the other is its partner on the back.
|
|
||||||
//
|
|
||||||
// Old code that will actually create valid two-dimensional sectors
|
|
||||||
// is included below for reference but is not likely to be used again.
|
|
||||||
|
|
||||||
|
// When creating GL nodes, we need to check for segs with the same start and
|
||||||
|
// end vertices and split them into two subsectors.
|
||||||
|
|
||||||
|
bool FNodeBuilder::CheckSubsectorOverlappingSegs (DWORD set, node_t &node, DWORD &splitseg)
|
||||||
|
{
|
||||||
|
int v1, v2;
|
||||||
|
DWORD seg1, seg2;
|
||||||
|
|
||||||
|
for (seg1 = set; seg1 != DWORD_MAX; seg1 = Segs[seg1].next)
|
||||||
|
{
|
||||||
|
if (Segs[seg1].linedef == -1)
|
||||||
|
{ // Do not check minisegs.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
v1 = Segs[seg1].v1;
|
||||||
|
v2 = Segs[seg1].v2;
|
||||||
|
for (seg2 = Segs[seg1].next; seg2 != DWORD_MAX; seg2 = Segs[seg2].next)
|
||||||
|
{
|
||||||
|
if (Segs[seg2].v1 == v1 && Segs[seg2].v2 == v2)
|
||||||
|
{
|
||||||
|
if (Segs[seg2].linedef == -1)
|
||||||
|
{ // Do not put minisegs into a new subsector.
|
||||||
|
swap (seg1, seg2);
|
||||||
|
}
|
||||||
|
D(Printf("Need to synthesize a splitter for set %d on seg %d (ov)\n", set, seg2));
|
||||||
|
splitseg = DWORD_MAX;
|
||||||
|
|
||||||
|
return ShoveSegBehind (set, node, seg2, seg1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// It really is a good subsector.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The seg is marked to indicate that it should be forced to the
|
||||||
|
// back of the splitter. Because these segs already form a convex
|
||||||
|
// set, all the other segs will be in front of the splitter. Since
|
||||||
|
// the splitter is formed from this seg, the back of the splitter
|
||||||
|
// will have a one-dimensional subsector. SplitSegs() will add one
|
||||||
|
// or two new minisegs to close it: If mate is DWORD_MAX, then a
|
||||||
|
// new seg is created to replace this one on the front of the
|
||||||
|
// splitter. Otherwise, mate takes its place. In either case, the
|
||||||
|
// seg in front of the splitter is partnered with a new miniseg on
|
||||||
|
// the back so that the back will have two segs.
|
||||||
|
|
||||||
|
bool FNodeBuilder::ShoveSegBehind (DWORD set, node_t &node, DWORD seg, DWORD mate)
|
||||||
|
{
|
||||||
SetNodeFromSeg (node, &Segs[seg]);
|
SetNodeFromSeg (node, &Segs[seg]);
|
||||||
HackSeg = seg;
|
HackSeg = seg;
|
||||||
|
HackMate = mate;
|
||||||
if (!Segs[seg].planefront)
|
if (!Segs[seg].planefront)
|
||||||
{
|
{
|
||||||
node.x += node.dx;
|
node.x += node.dx;
|
||||||
|
@ -355,79 +402,6 @@ bool FNodeBuilder::CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int
|
||||||
node.dy = -node.dy;
|
node.dy = -node.dy;
|
||||||
}
|
}
|
||||||
return Heuristic (node, set, false) != 0;
|
return Heuristic (node, set, false) != 0;
|
||||||
|
|
||||||
#if 0
|
|
||||||
// If there are only two segs in the set, and they form two sides
|
|
||||||
// of a triangle, the splitter should pass through their shared
|
|
||||||
// point and the (imaginary) third side of the triangle
|
|
||||||
if (setsize == 2)
|
|
||||||
{
|
|
||||||
FPrivVert *v1, *v2, *v3;
|
|
||||||
|
|
||||||
if (Vertices[Segs[set].v2] == Vertices[Segs[seg].v1])
|
|
||||||
{
|
|
||||||
v1 = &Vertices[Segs[set].v1];
|
|
||||||
v2 = &Vertices[Segs[seg].v2];
|
|
||||||
v3 = &Vertices[Segs[set].v2];
|
|
||||||
}
|
|
||||||
else if (Vertices[Segs[set].v1] == Vertices[Segs[seg].v2])
|
|
||||||
{
|
|
||||||
v1 = &Vertices[Segs[seg].v1];
|
|
||||||
v2 = &Vertices[Segs[set].v2];
|
|
||||||
v3 = &Vertices[Segs[seg].v2];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v1 = v2 = v3 = NULL;
|
|
||||||
}
|
|
||||||
if (v1 != NULL)
|
|
||||||
{
|
|
||||||
node.x = v3->x;
|
|
||||||
node.y = v3->y;
|
|
||||||
node.dx = v1->x + (v2->x-v1->x)/2 - node.x;
|
|
||||||
node.dy = v1->y + (v2->y-v1->y)/2 - node.y;
|
|
||||||
return Heuristic (node, set, false) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nosplit = true;
|
|
||||||
int firsthit = seg;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
seg = firsthit;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (Segs[seg].linedef != -1 &&
|
|
||||||
Segs[seg].frontsector != sec &&
|
|
||||||
Segs[seg].frontsector == Segs[seg].backsector)
|
|
||||||
{
|
|
||||||
node.x = Vertices[Segs[set].v1].x;
|
|
||||||
node.y = Vertices[Segs[set].v1].y;
|
|
||||||
node.dx = Vertices[Segs[seg].v2].x - node.x;
|
|
||||||
node.dy = Vertices[Segs[seg].v2].y - node.y;
|
|
||||||
|
|
||||||
if (Heuristic (node, set, nosplit) != 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
node.dx = Vertices[Segs[seg].v1].x - node.x;
|
|
||||||
node.dy = Vertices[Segs[seg].v1].y - node.y;
|
|
||||||
|
|
||||||
if (Heuristic (node, set, nosplit) != 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
seg = Segs[seg].next;
|
|
||||||
} while (seg != DWORD_MAX);
|
|
||||||
} while ((nosplit ^= 1) == 0);
|
|
||||||
|
|
||||||
// Give up.
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Splitters are chosen to coincide with segs in the given set. To reduce the
|
// Splitters are chosen to coincide with segs in the given set. To reduce the
|
||||||
|
@ -474,7 +448,9 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int
|
||||||
|
|
||||||
int value = Heuristic (node, set, nosplit);
|
int value = Heuristic (node, set, nosplit);
|
||||||
|
|
||||||
D(Printf ("Seg %5d (%5d,%5d)-(%5d,%5d) scores %d\n", seg, node.x>>16, node.y>>16,
|
D(Printf ("Seg %5d%c(%5d,%5d)-(%5d,%5d) scores %d\n", seg,
|
||||||
|
Segs[seg].linedef == -1 ? '+' : ' ',
|
||||||
|
node.x>>16, node.y>>16,
|
||||||
(node.x+node.dx)>>16, (node.y+node.dy)>>16, value));
|
(node.x+node.dx)>>16, (node.y+node.dy)>>16, value));
|
||||||
|
|
||||||
if (value > bestvalue)
|
if (value > bestvalue)
|
||||||
|
@ -919,15 +895,24 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou
|
||||||
DWORD newback, newfront;
|
DWORD newback, newfront;
|
||||||
|
|
||||||
newback = AddMiniseg (seg->v2, seg->v1, DWORD_MAX, set, splitseg);
|
newback = AddMiniseg (seg->v2, seg->v1, DWORD_MAX, set, splitseg);
|
||||||
|
if (HackMate == DWORD_MAX)
|
||||||
|
{
|
||||||
newfront = AddMiniseg (Segs[set].v1, Segs[set].v2, newback, set, splitseg);
|
newfront = AddMiniseg (Segs[set].v1, Segs[set].v2, newback, set, splitseg);
|
||||||
|
Segs[newfront].next = outset0;
|
||||||
|
outset0 = newfront;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newfront = HackMate;
|
||||||
|
Segs[newfront].partner = newback;
|
||||||
|
Segs[newback].partner = newfront;
|
||||||
|
}
|
||||||
Segs[newback].frontsector = Segs[newback].backsector =
|
Segs[newback].frontsector = Segs[newback].backsector =
|
||||||
Segs[newfront].frontsector = Segs[newfront].backsector =
|
Segs[newfront].frontsector = Segs[newfront].backsector =
|
||||||
Segs[set].frontsector;
|
Segs[set].frontsector;
|
||||||
|
|
||||||
Segs[newback].next = outset1;
|
Segs[newback].next = outset1;
|
||||||
outset1 = newback;
|
outset1 = newback;
|
||||||
Segs[newfront].next = outset0;
|
|
||||||
outset0 = newfront;
|
|
||||||
}
|
}
|
||||||
set = next;
|
set = next;
|
||||||
}
|
}
|
||||||
|
@ -1115,7 +1100,9 @@ void FNodeBuilder::PrintSet (int l, DWORD set)
|
||||||
Printf ("set %d:\n", l);
|
Printf ("set %d:\n", l);
|
||||||
for (; set != DWORD_MAX; set = Segs[set].next)
|
for (; set != DWORD_MAX; set = Segs[set].next)
|
||||||
{
|
{
|
||||||
Printf ("\t%lu(%d):%d(%d,%d)-%d(%d,%d)\n", set, Segs[set].frontsector,
|
Printf ("\t%lu(%d)%c%d(%d,%d)-%d(%d,%d)\n", set,
|
||||||
|
Segs[set].frontsector,
|
||||||
|
Segs[set].linedef == -1 ? '+' : ':',
|
||||||
Segs[set].v1,
|
Segs[set].v1,
|
||||||
Vertices[Segs[set].v1].x>>16, Vertices[Segs[set].v1].y>>16,
|
Vertices[Segs[set].v1].x>>16, Vertices[Segs[set].v1].y>>16,
|
||||||
Segs[set].v2,
|
Segs[set].v2,
|
||||||
|
|
|
@ -140,6 +140,7 @@ private:
|
||||||
TArray<FSplitSharer> SplitSharers; // Segs collinear with the current splitter
|
TArray<FSplitSharer> SplitSharers; // Segs collinear with the current splitter
|
||||||
|
|
||||||
DWORD HackSeg; // Seg to force to back of splitter
|
DWORD HackSeg; // Seg to force to back of splitter
|
||||||
|
DWORD HackMate; // Seg to use in front of hack seg
|
||||||
FLevel &Level;
|
FLevel &Level;
|
||||||
bool GLNodes;
|
bool GLNodes;
|
||||||
|
|
||||||
|
@ -151,7 +152,7 @@ private:
|
||||||
int SelectVertexExact (FPrivVert &vertex);
|
int SelectVertexExact (FPrivVert &vertex);
|
||||||
void BuildTree ();
|
void BuildTree ();
|
||||||
void MakeSegsFromSides ();
|
void MakeSegsFromSides ();
|
||||||
FPrivSeg *CheckSegForDuplicate (const FPrivSeg *check);
|
int CreateSeg (int linenum, int sidenum);
|
||||||
void GroupSegPlanes ();
|
void GroupSegPlanes ();
|
||||||
void FindPolyContainers (TArray<FPolyStart> &spots, TArray<FPolyStart> &anchors);
|
void FindPolyContainers (TArray<FPolyStart> &spots, TArray<FPolyStart> &anchors);
|
||||||
bool GetPolyExtents (int polynum, fixed_t bbox[4]);
|
bool GetPolyExtents (int polynum, fixed_t bbox[4]);
|
||||||
|
@ -161,6 +162,8 @@ private:
|
||||||
DWORD CreateSubsector (DWORD set, fixed_t bbox[4]);
|
DWORD CreateSubsector (DWORD set, fixed_t bbox[4]);
|
||||||
void CreateSubsectorsForReal ();
|
void CreateSubsectorsForReal ();
|
||||||
bool CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int setsize);
|
bool CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int setsize);
|
||||||
|
bool CheckSubsectorOverlappingSegs (DWORD set, node_t &node, DWORD &splitseg);
|
||||||
|
bool ShoveSegBehind (DWORD set, node_t &node, DWORD seg, DWORD mate);
|
||||||
int SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int step, bool nosplit);
|
int SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int step, bool nosplit);
|
||||||
void SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &outset0, DWORD &outset1);
|
void SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &outset0, DWORD &outset1);
|
||||||
DWORD SplitSeg (DWORD segnum, int splitvert, int v1InFront);
|
DWORD SplitSeg (DWORD segnum, int splitvert, int v1InFront);
|
||||||
|
|
|
@ -132,7 +132,8 @@ int FNodeBuilder::CloseSubsector (TArray<MapSegGLEx> &segs, int subsector)
|
||||||
{
|
{
|
||||||
seg = &Segs[SegList[j].SegNum];
|
seg = &Segs[SegList[j].SegNum];
|
||||||
angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy);
|
angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy);
|
||||||
printf ("%d: %5d(%5d,%5d)->%5d(%5d,%5d) - %3.3f %d,%d\n", j,
|
printf ("%d%c %5d(%5d,%5d)->%5d(%5d,%5d) - %3.3f %d,%d\n", j,
|
||||||
|
seg->linedef == -1 ? '+' : ':',
|
||||||
seg->v1, Vertices[seg->v1].x>>16, Vertices[seg->v1].y>>16,
|
seg->v1, Vertices[seg->v1].x>>16, Vertices[seg->v1].y>>16,
|
||||||
seg->v2, Vertices[seg->v2].x>>16, Vertices[seg->v2].y>>16,
|
seg->v2, Vertices[seg->v2].x>>16, Vertices[seg->v2].y>>16,
|
||||||
double(ang/2)*180/(1<<30),
|
double(ang/2)*180/(1<<30),
|
||||||
|
@ -208,17 +209,6 @@ int FNodeBuilder::CloseSubsector (TArray<MapSegGLEx> &segs, int subsector)
|
||||||
|
|
||||||
D(printf("degenerate subsector\n"));
|
D(printf("degenerate subsector\n"));
|
||||||
|
|
||||||
#if 0
|
|
||||||
for (j = first + 1; j < max; ++j)
|
|
||||||
{
|
|
||||||
seg = &Segs[SegList[j].SegNum];
|
|
||||||
dx2 = Vertices[seg->v1].x - x1;
|
|
||||||
dy2 = Vertices[seg->v1].y - y1;
|
|
||||||
dot = dx*dx2 + dy*dy2;
|
|
||||||
|
|
||||||
printf ("Seg %d: dot %g\n", j, dot);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Stage 1. Go forward.
|
// Stage 1. Go forward.
|
||||||
count += OutputDegenerateSubsector (segs, subsector, true, 0, prev);
|
count += OutputDegenerateSubsector (segs, subsector, true, 0, prev);
|
||||||
|
|
||||||
|
|
|
@ -92,46 +92,13 @@ int FNodeBuilder::SelectVertexExact (FPrivVert &vertex)
|
||||||
|
|
||||||
void FNodeBuilder::MakeSegsFromSides ()
|
void FNodeBuilder::MakeSegsFromSides ()
|
||||||
{
|
{
|
||||||
FPrivSeg *share1, *share2;
|
|
||||||
FPrivSeg seg;
|
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
seg.next = DWORD_MAX;
|
|
||||||
seg.loopnum = 0;
|
|
||||||
seg.offset = 0;
|
|
||||||
seg.partner = DWORD_MAX;
|
|
||||||
|
|
||||||
for (i = 0; i < Level.NumLines; ++i)
|
for (i = 0; i < Level.NumLines; ++i)
|
||||||
{
|
{
|
||||||
share1 = NULL;
|
|
||||||
if (Level.Lines[i].sidenum[0] != NO_INDEX)
|
if (Level.Lines[i].sidenum[0] != NO_INDEX)
|
||||||
{
|
{
|
||||||
WORD backside;
|
CreateSeg (i, 0);
|
||||||
|
|
||||||
seg.linedef = i;
|
|
||||||
seg.sidedef = Level.Lines[i].sidenum[0];
|
|
||||||
backside = Level.Lines[i].sidenum[1];
|
|
||||||
seg.frontsector = Level.Sides[seg.sidedef].sector;
|
|
||||||
seg.backsector = backside != NO_INDEX ? Level.Sides[backside].sector : -1;
|
|
||||||
seg.v1 = Level.Lines[i].v1;
|
|
||||||
seg.v2 = Level.Lines[i].v2;
|
|
||||||
seg.nextforvert = Vertices[seg.v1].segs;
|
|
||||||
seg.nextforvert2 = Vertices[seg.v2].segs2;
|
|
||||||
share1 = CheckSegForDuplicate (&seg);
|
|
||||||
if (share1 == NULL)
|
|
||||||
{
|
|
||||||
seg.angle = PointToAngle (Vertices[seg.v2].x-Vertices[seg.v1].x,
|
|
||||||
Vertices[seg.v2].y-Vertices[seg.v1].y);
|
|
||||||
j = (int)Segs.Push (seg);
|
|
||||||
Vertices[seg.v1].segs = j;
|
|
||||||
Vertices[seg.v2].segs2 = j;
|
|
||||||
D(printf("Seg %4d: From line %d, side front (%5d,%5d)-(%5d,%5d)\n", j, i, Vertices[seg.v1].x>>16,
|
|
||||||
Vertices[seg.v1].y>>16, Vertices[seg.v2].x>>16, Vertices[seg.v2].y>>16));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf ("Linedefs %d and %d share endpoints.\n", i, share1->linedef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -140,62 +107,54 @@ void FNodeBuilder::MakeSegsFromSides ()
|
||||||
|
|
||||||
if (Level.Lines[i].sidenum[1] != NO_INDEX)
|
if (Level.Lines[i].sidenum[1] != NO_INDEX)
|
||||||
{
|
{
|
||||||
WORD backside;
|
j = CreateSeg (i, 1);
|
||||||
|
if (Level.Lines[i].sidenum[0] != NO_INDEX)
|
||||||
seg.linedef = i;
|
|
||||||
seg.sidedef = Level.Lines[i].sidenum[1];
|
|
||||||
backside = Level.Lines[i].sidenum[0];
|
|
||||||
seg.frontsector = Level.Sides[seg.sidedef].sector;
|
|
||||||
seg.backsector = backside != NO_INDEX ? Level.Sides[backside].sector : -1;
|
|
||||||
seg.v1 = Level.Lines[i].v2;
|
|
||||||
seg.v2 = Level.Lines[i].v1;
|
|
||||||
seg.nextforvert = Vertices[seg.v1].segs;
|
|
||||||
seg.nextforvert2 = Vertices[seg.v2].segs2;
|
|
||||||
seg.angle = PointToAngle (Vertices[seg.v2].x-Vertices[seg.v1].x,
|
|
||||||
Vertices[seg.v2].y-Vertices[seg.v1].y);
|
|
||||||
share2 = CheckSegForDuplicate (&seg);
|
|
||||||
if (share2 == NULL)
|
|
||||||
{
|
|
||||||
j = (int)Segs.Push (seg);
|
|
||||||
Vertices[seg.v1].segs = j;
|
|
||||||
Vertices[seg.v2].segs2 = j;
|
|
||||||
|
|
||||||
if (Level.Lines[i].sidenum[0] != NO_INDEX && share1 == NULL)
|
|
||||||
{
|
{
|
||||||
Segs[j-1].partner = j;
|
Segs[j-1].partner = j;
|
||||||
Segs[j].partner = j-1;
|
Segs[j].partner = j-1;
|
||||||
}
|
}
|
||||||
D(printf("Seg %4d: From line %d, side back (%5d,%5d)-(%5d,%5d)\n", j, i, Vertices[seg.v1].x>>16,
|
|
||||||
Vertices[seg.v1].y>>16, Vertices[seg.v2].x>>16, Vertices[seg.v2].y>>16));
|
|
||||||
}
|
|
||||||
else if (share2->linedef != share1->linedef)
|
|
||||||
{
|
|
||||||
printf ("Linedefs %d and %d share endpoints.\n", i, share2->linedef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for another seg with the same start and end vertices as this one.
|
int FNodeBuilder::CreateSeg (int linenum, int sidenum)
|
||||||
// Combined with its use above, this will find two-sided lines that are shadowed
|
|
||||||
// by another one- or two-sided line, and it will also find one-sided lines that
|
|
||||||
// shadow each other. It will not find one-sided lines that share endpoints but
|
|
||||||
// face opposite directions. Although they should probably be a single two-sided
|
|
||||||
// line, leaving them in will not generate bad nodes.
|
|
||||||
|
|
||||||
FNodeBuilder::FPrivSeg *FNodeBuilder::CheckSegForDuplicate (const FNodeBuilder::FPrivSeg *check)
|
|
||||||
{
|
{
|
||||||
DWORD segnum;
|
FPrivSeg seg;
|
||||||
|
WORD backside;
|
||||||
|
int segnum;
|
||||||
|
|
||||||
// Check for segs facing the same direction
|
seg.next = DWORD_MAX;
|
||||||
for (segnum = check->nextforvert; segnum != DWORD_MAX; segnum = Segs[segnum].nextforvert)
|
seg.loopnum = 0;
|
||||||
{
|
seg.offset = 0;
|
||||||
if (Segs[segnum].v2 == check->v2)
|
seg.partner = DWORD_MAX;
|
||||||
{
|
|
||||||
return &Segs[segnum];
|
if (sidenum == 0)
|
||||||
|
{ // front
|
||||||
|
seg.v1 = Level.Lines[linenum].v1;
|
||||||
|
seg.v2 = Level.Lines[linenum].v2;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{ // back
|
||||||
|
seg.v2 = Level.Lines[linenum].v1;
|
||||||
|
seg.v1 = Level.Lines[linenum].v2;
|
||||||
}
|
}
|
||||||
return NULL;
|
seg.linedef = linenum;
|
||||||
|
seg.sidedef = Level.Lines[linenum].sidenum[sidenum];
|
||||||
|
backside = Level.Lines[linenum].sidenum[!sidenum];
|
||||||
|
seg.frontsector = Level.Sides[seg.sidedef].sector;
|
||||||
|
seg.backsector = backside != NO_INDEX ? Level.Sides[backside].sector : -1;
|
||||||
|
seg.nextforvert = Vertices[seg.v1].segs;
|
||||||
|
seg.nextforvert2 = Vertices[seg.v2].segs2;
|
||||||
|
seg.angle = PointToAngle (Vertices[seg.v2].x-Vertices[seg.v1].x,
|
||||||
|
Vertices[seg.v2].y-Vertices[seg.v1].y);
|
||||||
|
|
||||||
|
segnum = (int)Segs.Push (seg);
|
||||||
|
Vertices[seg.v1].segs = segnum;
|
||||||
|
Vertices[seg.v2].segs2 = segnum;
|
||||||
|
D(printf("Seg %4d: From line %d, side %s (%5d,%5d)-(%5d,%5d)\n", segnum, linenum, sidenum ? "back " : "front",
|
||||||
|
Vertices[seg.v1].x>>16, Vertices[seg.v1].y>>16, Vertices[seg.v2].x>>16, Vertices[seg.v2].y>>16));
|
||||||
|
|
||||||
|
return segnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group colinear segs together so that only one seg per line needs to be checked
|
// Group colinear segs together so that only one seg per line needs to be checked
|
||||||
|
|
Loading…
Reference in New Issue