- 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
|
|
@ -246,126 +246,16 @@ int FNodeBuilder::CloseSubsector (TArray<seg_t> &segs, int subsector, vertex_t *
|
|||
// to the start seg.
|
||||
// A dot product serves to determine distance from the start seg.
|
||||
|
||||
seg = &Segs[SegList[first].SegNum];
|
||||
double x1 = Vertices[seg->v1].x;
|
||||
double y1 = Vertices[seg->v1].y;
|
||||
double dx = Vertices[seg->v2].x - x1, dx2;
|
||||
double dy = Vertices[seg->v2].y - y1, dy2;
|
||||
double lastdot = 0, dot;
|
||||
bool firstside = seg->planefront;
|
||||
|
||||
// Stage 1. Go forward.
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
double bestdot = DBL_MAX;
|
||||
FPrivSeg *bestseg = NULL;
|
||||
for (j = first + 1; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
if (seg->planefront != firstside)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dx2 = Vertices[seg->v1].x - x1;
|
||||
dy2 = Vertices[seg->v1].y - y1;
|
||||
dot = dx*dx2 + dy*dy2;
|
||||
|
||||
if (dot < bestdot && dot > lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
if (prev->v2 != bestseg->v1)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[bestseg->v1]);
|
||||
count++;
|
||||
}
|
||||
seg->storedseg = PushGLSeg (segs, bestseg, outVerts);
|
||||
count++;
|
||||
prev = bestseg;
|
||||
lastdot = bestdot;
|
||||
}
|
||||
}
|
||||
count += OutputDegenerateSubsector (segs, subsector, true, 0, prev, outVerts);
|
||||
|
||||
// Stage 2. Go backward.
|
||||
lastdot = DBL_MAX;
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
double bestdot = -DBL_MAX;
|
||||
FPrivSeg *bestseg = NULL;
|
||||
for (j = first + 1; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
if (seg->planefront == firstside)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dx2 = Vertices[seg->v1].x - x1;
|
||||
dy2 = Vertices[seg->v1].y - y1;
|
||||
dot = dx*dx2 + dy*dy2;
|
||||
|
||||
if (dot > bestdot && dot < lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
if (prev->v2 != bestseg->v1)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[bestseg->v1]);
|
||||
count++;
|
||||
}
|
||||
seg->storedseg = PushGLSeg (segs, bestseg, outVerts);
|
||||
count++;
|
||||
prev = bestseg;
|
||||
lastdot = bestdot;
|
||||
}
|
||||
}
|
||||
count += OutputDegenerateSubsector (segs, subsector, false, DBL_MAX, prev, outVerts);
|
||||
|
||||
// Stage 3. Go forward again.
|
||||
lastdot = -DBL_MAX;
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
double bestdot = 0;
|
||||
FPrivSeg *bestseg = NULL;
|
||||
for (j = first + 1; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
if (seg->planefront != firstside)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dx2 = Vertices[seg->v1].x - x1;
|
||||
dy2 = Vertices[seg->v1].y - y1;
|
||||
dot = dx*dx2 + dy*dy2;
|
||||
|
||||
if (dot < bestdot && dot > lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
if (prev->v2 != bestseg->v1)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[bestseg->v1]);
|
||||
count++;
|
||||
}
|
||||
seg->storedseg = PushGLSeg (segs, bestseg, outVerts);
|
||||
count++;
|
||||
prev = bestseg;
|
||||
lastdot = bestdot;
|
||||
}
|
||||
}
|
||||
count += OutputDegenerateSubsector (segs, subsector, true, -DBL_MAX, prev, outVerts);
|
||||
}
|
||||
|
||||
|
||||
if (prev->v2 != firstVert)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[firstVert]);
|
||||
|
|
@ -375,6 +265,73 @@ int FNodeBuilder::CloseSubsector (TArray<seg_t> &segs, int subsector, vertex_t *
|
|||
return count;
|
||||
}
|
||||
|
||||
int FNodeBuilder::OutputDegenerateSubsector (TArray<seg_t> &segs, int subsector, bool bForward, double lastdot, FPrivSeg *&prev, vertex_t *outVerts)
|
||||
{
|
||||
static const double bestinit[2] = { -DBL_MAX, DBL_MAX };
|
||||
FPrivSeg *seg;
|
||||
int i, j, first, max, count;
|
||||
double dot, x1, y1, dx, dy, dx2, dy2;
|
||||
bool wantside;
|
||||
|
||||
first = Subsectors[subsector].firstline;
|
||||
max = first + Subsectors[subsector].numlines;
|
||||
count = 0;
|
||||
|
||||
seg = &Segs[SegList[first].SegNum];
|
||||
x1 = Vertices[seg->v1].x;
|
||||
y1 = Vertices[seg->v1].y;
|
||||
dx = Vertices[seg->v2].x - x1;
|
||||
dy = Vertices[seg->v2].y - y1;
|
||||
wantside = seg->planefront ^ !bForward;
|
||||
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
double bestdot = bestinit[bForward];
|
||||
FPrivSeg *bestseg = NULL;
|
||||
for (j = first + 1; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
if (seg->planefront != wantside)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dx2 = Vertices[seg->v1].x - x1;
|
||||
dy2 = Vertices[seg->v1].y - y1;
|
||||
dot = dx*dx2 + dy*dy2;
|
||||
|
||||
if (bForward)
|
||||
{
|
||||
if (dot < bestdot && dot > lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dot > bestdot && dot < lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
if (prev->v2 != bestseg->v1)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[bestseg->v1]);
|
||||
count++;
|
||||
}
|
||||
seg->storedseg = PushGLSeg (segs, bestseg, outVerts);
|
||||
count++;
|
||||
prev = bestseg;
|
||||
lastdot = bestdot;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
DWORD FNodeBuilder::PushGLSeg (TArray<seg_t> &segs, const FPrivSeg *seg, vertex_t *outVerts)
|
||||
{
|
||||
seg_t newseg;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue