mirror of
https://github.com/ZDoom/zdbsp.git
synced 2024-11-28 14:41:59 +00:00
- Fixed: A splitter that cannot properly divide a seg into two pieces because it is too close
to an endpoint to produce a unique vertex must be rejected. SVN r2090 (trunk)
This commit is contained in:
parent
635603e210
commit
fdaa6547f6
3 changed files with 53 additions and 15 deletions
|
@ -32,7 +32,7 @@
|
||||||
#define Printf printf
|
#define Printf printf
|
||||||
#define STACK_ARGS
|
#define STACK_ARGS
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
#define D(x) x
|
#define D(x) x
|
||||||
#else
|
#else
|
||||||
#define D(x) do{}while(0)
|
#define D(x) do{}while(0)
|
||||||
|
@ -499,8 +499,8 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int
|
||||||
|
|
||||||
int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit)
|
int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit)
|
||||||
{
|
{
|
||||||
// Set the initial score above 0 so that near vertex anti-weighting does not automatically disqualify the vertex.
|
// Set the initial score above 0 so that near vertex anti-weighting is less likely to produce a negative score.
|
||||||
int score = 100000000;
|
int score = 1000000;
|
||||||
int segsInSet = 0;
|
int segsInSet = 0;
|
||||||
int counts[2] = { 0, 0 };
|
int counts[2] = { 0, 0 };
|
||||||
int realSegs[2] = { 0, 0 };
|
int realSegs[2] = { 0, 0 };
|
||||||
|
@ -605,17 +605,30 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit)
|
||||||
|
|
||||||
// Splitters that are too close to a vertex are bad.
|
// Splitters that are too close to a vertex are bad.
|
||||||
frac = InterceptVector (node, *test);
|
frac = InterceptVector (node, *test);
|
||||||
if (frac < 0.001)
|
if (frac < 0.001 || frac > 0.999)
|
||||||
{
|
{
|
||||||
|
FPrivVert *v1 = &Vertices[test->v1];
|
||||||
|
FPrivVert *v2 = &Vertices[test->v2];
|
||||||
|
double x = v1->x, y = v1->y;
|
||||||
|
x += frac * (v2->x - x);
|
||||||
|
y += frac * (v2->y - y);
|
||||||
|
if (fabs(x - v1->x) < VERTEX_EPSILON+1 && fabs(y - v1->y) < VERTEX_EPSILON+1)
|
||||||
|
{
|
||||||
|
D(Printf("Splitter will produce same start vertex as seg %d\n", i));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fabs(x - v2->x) < VERTEX_EPSILON+1 && fabs(y - v2->y) < VERTEX_EPSILON+1)
|
||||||
|
{
|
||||||
|
D(Printf("Splitter will produce same end vertex as seg %d\n", i));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (frac > 0.999)
|
||||||
|
{
|
||||||
|
frac = 1 - frac;
|
||||||
|
}
|
||||||
int penalty = int(1 / frac);
|
int penalty = int(1 / frac);
|
||||||
score = MAX(score - penalty, 1);
|
score = MAX(score - penalty, 1);
|
||||||
D(Printf ("Penalized splitter by %d for being too close to start vertex of seg %d.\n", penalty, i));
|
D(Printf ("Penalized splitter by %d for being near endpt of seg %d (%f).\n", penalty, i, frac));
|
||||||
}
|
|
||||||
else if (frac > 0.999)
|
|
||||||
{
|
|
||||||
int penalty = int(1 / (1 - frac));
|
|
||||||
score = MAX(score - penalty, 1);
|
|
||||||
D(Printf ("Penalized splitter by %d for being too close to end vertex of seg %d.\n", penalty, i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
counts[0]++;
|
counts[0]++;
|
||||||
|
@ -790,6 +803,28 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou
|
||||||
newvert.index = 0;
|
newvert.index = 0;
|
||||||
vertnum = VertexMap->SelectVertexClose (newvert);
|
vertnum = VertexMap->SelectVertexClose (newvert);
|
||||||
|
|
||||||
|
if (vertnum == seg->v1 || vertnum == seg->v2)
|
||||||
|
{
|
||||||
|
Printf("SelectVertexClose selected endpoint of seg %u\n", set);
|
||||||
|
// Check if the resulting split vertex matches one of the line's ends.
|
||||||
|
// In this case this seg must not be split
|
||||||
|
if ((vertnum == seg->v1 && sidev2 == -1) || (vertnum == seg->v2 && sidev1 == -1))
|
||||||
|
{
|
||||||
|
side = 0;
|
||||||
|
sidev1 = 0;
|
||||||
|
seg->next = outset0;
|
||||||
|
outset0 = set;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
side = 1;
|
||||||
|
sidev2 = 0;
|
||||||
|
seg->next = outset1;
|
||||||
|
outset1 = set;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
seg2 = SplitSeg (set, vertnum, sidev1);
|
seg2 = SplitSeg (set, vertnum, sidev1);
|
||||||
|
|
||||||
Segs[seg2].next = outset0;
|
Segs[seg2].next = outset0;
|
||||||
|
|
|
@ -250,6 +250,9 @@ private:
|
||||||
// Units are in fixed_ts.
|
// Units are in fixed_ts.
|
||||||
const double SIDE_EPSILON = 6.5536;
|
const double SIDE_EPSILON = 6.5536;
|
||||||
|
|
||||||
|
// Vertices within this distance of each other will be considered as the same vertex.
|
||||||
|
#define VERTEX_EPSILON 6 // This is a fixed_t value
|
||||||
|
|
||||||
inline int FNodeBuilder::PointOnSide (int x, int y, int x1, int y1, int dx, int dy)
|
inline int FNodeBuilder::PointOnSide (int x, int y, int x1, int y1, int dx, int dy)
|
||||||
{
|
{
|
||||||
// For most cases, a simple dot product is enough.
|
// For most cases, a simple dot product is enough.
|
||||||
|
|
|
@ -28,10 +28,6 @@
|
||||||
static const int PO_LINE_START = 1;
|
static const int PO_LINE_START = 1;
|
||||||
static const int PO_LINE_EXPLICIT = 5;
|
static const int PO_LINE_EXPLICIT = 5;
|
||||||
|
|
||||||
// Vertices within this distance of each other vertically and horizontally
|
|
||||||
// will be considered as the same vertex.
|
|
||||||
const fixed_t VERTEX_EPSILON = 6;
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define D(x) x
|
#define D(x) x
|
||||||
#else
|
#else
|
||||||
|
@ -503,8 +499,12 @@ int FNodeBuilder::FVertexMap::SelectVertexClose (FNodeBuilder::FPrivVert &vert)
|
||||||
|
|
||||||
for (i = 0; i < block.Size(); ++i)
|
for (i = 0; i < block.Size(); ++i)
|
||||||
{
|
{
|
||||||
|
#if VERTEX_EPSILON <= 1
|
||||||
|
if (vertices[block[i]].x == vert.x && vertices[block[i]].y == vert.y)
|
||||||
|
#else
|
||||||
if (abs(vertices[block[i]].x - vert.x) < VERTEX_EPSILON &&
|
if (abs(vertices[block[i]].x - vert.x) < VERTEX_EPSILON &&
|
||||||
abs(vertices[block[i]].y - vert.y) < VERTEX_EPSILON)
|
abs(vertices[block[i]].y - vert.y) < VERTEX_EPSILON)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return block[i];
|
return block[i];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue