- Merged in recent ZDBSP fixes:
- Added code to explicitly handle outputting overlapping segs when building GL nodes with ZDBSP, removing the check that discarded them early on. - AddIntersection() should convert to doubles before subtracting the vertex from the node, not after, to avoid integer overflow. (See cah.wad, MAP12 and MAP13.) A simpler dot product will also suffice for distance calculation. - Splitters that come too close to a vertex should be avoided. (See cata.wad.) - Red-Black Tree implementation was broken and colored every node red. - Moved most of the code for outputting degenerate GL subsectors into another function. SVN r160 (trunk)
This commit is contained in:
parent
fd1a239c66
commit
4325fb8993
7 changed files with 202 additions and 280 deletions
|
|
@ -125,14 +125,8 @@ int FNodeBuilder::SelectVertexExact (FPrivVert &vertex)
|
|||
|
||||
void FNodeBuilder::MakeSegsFromSides ()
|
||||
{
|
||||
FPrivSeg *share1, *share2;
|
||||
FPrivSeg seg;
|
||||
int i, j;
|
||||
|
||||
seg.next = DWORD_MAX;
|
||||
seg.loopnum = 0;
|
||||
seg.partner = DWORD_MAX;
|
||||
|
||||
if (Level.NumLines == 0)
|
||||
{
|
||||
I_Error ("Map is empty.\n");
|
||||
|
|
@ -140,28 +134,9 @@ void FNodeBuilder::MakeSegsFromSides ()
|
|||
|
||||
for (i = 0; i < Level.NumLines; ++i)
|
||||
{
|
||||
share1 = NULL;
|
||||
if (Level.Lines[i].sidenum[0] != NO_SIDE)
|
||||
{
|
||||
seg.linedef = i;
|
||||
seg.sidedef = Level.Lines[i].sidenum[0];
|
||||
seg.frontsector = Level.Lines[i].frontsector;
|
||||
seg.backsector = Level.Lines[i].backsector;
|
||||
seg.v1 = (int)(size_t)Level.Lines[i].v1;
|
||||
seg.v2 = (int)(size_t)Level.Lines[i].v2;
|
||||
seg.nextforvert = Vertices[seg.v1].segs;
|
||||
seg.nextforvert2 = Vertices[seg.v2].segs2;
|
||||
share1 = CheckSegForDuplicate (&seg);
|
||||
if (share1 == NULL)
|
||||
{
|
||||
j = (int)Segs.Push (seg);
|
||||
Vertices[seg.v1].segs = j;
|
||||
Vertices[seg.v2].segs2 = j;
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("Linedefs %d and %d share endpoints.\n", i, share1->linedef);
|
||||
}
|
||||
CreateSeg (i, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -170,55 +145,49 @@ void FNodeBuilder::MakeSegsFromSides ()
|
|||
|
||||
if (Level.Lines[i].sidenum[1] != NO_SIDE)
|
||||
{
|
||||
seg.linedef = i;
|
||||
seg.sidedef = Level.Lines[i].sidenum[1];
|
||||
seg.frontsector = Level.Lines[i].backsector;
|
||||
seg.backsector = Level.Lines[i].frontsector;
|
||||
seg.v1 = (int)(size_t)Level.Lines[i].v2;
|
||||
seg.v2 = (int)(size_t)Level.Lines[i].v1;
|
||||
seg.nextforvert = Vertices[seg.v1].segs;
|
||||
seg.nextforvert2 = Vertices[seg.v2].segs2;
|
||||
share2 = CheckSegForDuplicate (&seg);
|
||||
if (share2 == NULL)
|
||||
j = CreateSeg (i, 1);
|
||||
if (Level.Lines[i].sidenum[0] != NO_SIDE)
|
||||
{
|
||||
j = (int)Segs.Push (seg);
|
||||
Vertices[seg.v1].segs = j;
|
||||
Vertices[seg.v2].segs2 = j;
|
||||
|
||||
if (Level.Lines[i].sidenum[0] != NO_SIDE && share1 == NULL)
|
||||
{
|
||||
Segs[j-1].partner = j;
|
||||
Segs[j].partner = j-1;
|
||||
}
|
||||
}
|
||||
else if (share1 == NULL || share2->linedef != share1->linedef)
|
||||
{
|
||||
Printf ("Linedefs %d and %d share endpoints.\n", i, share2->linedef);
|
||||
Segs[j-1].partner = j;
|
||||
Segs[j].partner = j-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for another seg with the same start and end vertices as this one.
|
||||
// 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)
|
||||
int FNodeBuilder::CreateSeg (int linenum, int sidenum)
|
||||
{
|
||||
DWORD segnum;
|
||||
FPrivSeg seg;
|
||||
int segnum;
|
||||
|
||||
// Check for segs facing the same direction
|
||||
for (segnum = check->nextforvert; segnum != DWORD_MAX; segnum = Segs[segnum].nextforvert)
|
||||
{
|
||||
if (Segs[segnum].v2 == check->v2)
|
||||
{
|
||||
return &Segs[segnum];
|
||||
}
|
||||
seg.next = DWORD_MAX;
|
||||
seg.loopnum = 0;
|
||||
seg.partner = DWORD_MAX;
|
||||
|
||||
if (sidenum == 0)
|
||||
{ // front
|
||||
seg.frontsector = Level.Lines[linenum].frontsector;
|
||||
seg.backsector = Level.Lines[linenum].backsector;
|
||||
seg.v1 = (int)(size_t)Level.Lines[linenum].v1;
|
||||
seg.v2 = (int)(size_t)Level.Lines[linenum].v2;
|
||||
}
|
||||
return NULL;
|
||||
else
|
||||
{ // back
|
||||
seg.frontsector = Level.Lines[linenum].backsector;
|
||||
seg.backsector = Level.Lines[linenum].frontsector;
|
||||
seg.v2 = (int)(size_t)Level.Lines[linenum].v1;
|
||||
seg.v1 = (int)(size_t)Level.Lines[linenum].v2;
|
||||
}
|
||||
seg.linedef = linenum;
|
||||
seg.sidedef = Level.Lines[linenum].sidenum[sidenum];
|
||||
seg.nextforvert = Vertices[seg.v1].segs;
|
||||
seg.nextforvert2 = Vertices[seg.v2].segs2;
|
||||
|
||||
segnum = (int)Segs.Push (seg);
|
||||
Vertices[seg.v1].segs = segnum;
|
||||
Vertices[seg.v2].segs2 = segnum;
|
||||
|
||||
return segnum;
|
||||
}
|
||||
|
||||
// Group colinear segs together so that only one seg per line needs to be checked
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue