Split up separator finding and winding clipping.

Interesting, it makes very little (maybe faster) difference to find all the
separators for levels 3 and 4. This might be due to the higher levels using
most of the planes to fully clip source away. Anyway, it makes the code a
little clearer (one function, one task).
This commit is contained in:
Bill Currie 2013-03-15 16:00:39 +09:00
parent f80ae52828
commit 46d41ad9ac

View file

@ -87,37 +87,30 @@ delete_separator (threaddata_t *thread, sep_t *sep)
} }
static void static void
free_separators (threaddata_t *thread, pstack_t *stack) free_separators (threaddata_t *thread, sep_t *sep_list)
{ {
int i; while (sep_list) {
sep_t *sep = sep_list;
for (i = 2; i > 0; i--) { sep_list = sep->next;
while (stack->separators[i - 1]) {
sep_t *sep = stack->separators[i - 1];
stack->separators[i - 1] = sep->next;
delete_separator (thread, sep); delete_separator (thread, sep);
} }
}
} }
/* /*
ClipToSeparators Find the planes separating source from pass. The planes form a double
pyramid with source as the base (ie, source's edges will all be in one
plane each) and the vertex of the pyramid is between source and pass.
Edges from pass may or may not be in a plane, but each vertex will be in
at least one plane.
Source, pass, and target are an ordering of portals. If flip is false, the planes will be such that the space enclosed by the
planes and on the pass side of the vertex are on the front sides of the
Generates seperating planes candidates by taking two points from source and planes. If flip is true, then the space on the source side of the vertex
one point from pass, and clips target by them. and enclosed by the planes is on the front side of the planes.
If target is totally clipped away, that portal can not be seen through.
Normal clip keeps target on the same side as pass, which is correct if the
order goes source, pass, target. If the order goes pass, source, target
then test should be odd.
*/ */
static winding_t * static sep_t *
ClipToSeparators (threaddata_t *thread, pstack_t *stack, FindSeparators (threaddata_t *thread, winding_t *source, winding_t *pass,
winding_t *source, winding_t *pass, winding_t *target, int flip)
int test)
{ {
float d; float d;
int i, j, k, l; int i, j, k, l;
@ -127,15 +120,8 @@ ClipToSeparators (threaddata_t *thread, pstack_t *stack,
vec3_t v1, v2; vec3_t v1, v2;
vec_t length; vec_t length;
if (test < 2 && stack->separators[test]) { sep_t *separators = 0;
sep_t *sep;
for (sep = stack->separators[test]; target && sep; sep = sep->next) {
target = ClipWinding (target, &sep->plane, false);
}
return target;
}
// check all combinations
for (i = 0; i < source->numpoints; i++) { for (i = 0; i < source->numpoints; i++) {
l = (i + 1) % source->numpoints; l = (i + 1) % source->numpoints;
VectorSubtract (source->points[l], source->points[i], v1); VectorSubtract (source->points[l], source->points[i], v1);
@ -211,26 +197,29 @@ ClipToSeparators (threaddata_t *thread, pstack_t *stack,
} }
// flip the normal if we want the back side // flip the normal if we want the back side
if (test & 1) { if (flip) {
VectorNegate (plane.normal, plane.normal); VectorNegate (plane.normal, plane.normal);
plane.dist = -plane.dist; plane.dist = -plane.dist;
} }
// clip target by the seperating plane. If target is null, then
// we're pre-caching the rest of the separators
if (target)
target = ClipWinding (target, &plane, false);
if (test < 2) {
sep_t *sep = new_separator (thread); sep_t *sep = new_separator (thread);
sep->plane = plane; sep->plane = plane;
sep->next = stack->separators[test]; sep->next = separators;
stack->separators[test] = sep; separators = sep;
} else if (!target) {
return NULL; // target is not visible
}
break; break;
} }
} }
return separators;
}
static winding_t *
ClipToSeparators (const sep_t *separators, winding_t *target)
{
const sep_t *sep;
for (sep = separators; target && sep; sep = sep->next) {
target = ClipWinding (target, &sep->plane, false);
}
return target; return target;
} }
@ -362,8 +351,10 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
// pointing from the edges of source passing though the corners of // pointing from the edges of source passing though the corners of
// pass // pass
winding_t *old = target; winding_t *old = target;
target = ClipToSeparators (thread, &stack, source, prevstack->pass, if (!stack.separators[0])
target, 0); stack.separators[0] = FindSeparators (thread, source,
prevstack->pass, 0);
target = ClipToSeparators (stack.separators[0], target);
if (!target) { if (!target) {
thread->stats.targetclipped++; thread->stats.targetclipped++;
FreeWinding (source); FreeWinding (source);
@ -381,8 +372,10 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
// triangles rotated 60 (or 180) degrees relative to each other, // triangles rotated 60 (or 180) degrees relative to each other,
// parallel and in line, target will wind up being a hexagon. // parallel and in line, target will wind up being a hexagon.
winding_t *old = target; winding_t *old = target;
target = ClipToSeparators (thread, &stack, prevstack->pass, source, if (!stack.separators[1])
target, 1); stack.separators[1] = FindSeparators (thread, prevstack->pass,
source, 1);
target = ClipToSeparators (stack.separators[1], target);
if (!target) { if (!target) {
thread->stats.targetclipped++; thread->stats.targetclipped++;
FreeWinding (source); FreeWinding (source);
@ -397,8 +390,10 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
// the trimmed target // the trimmed target
if (options.level > 2) { if (options.level > 2) {
winding_t *old = source; winding_t *old = source;
source = ClipToSeparators (thread, &stack, target, prevstack->pass, sep_t *sep;
source, 2); sep = FindSeparators (thread, target, prevstack->pass, 0);
source = ClipToSeparators (sep, source);
free_separators (thread, sep);
if (!source) { if (!source) {
thread->stats.sourceclipped++; thread->stats.sourceclipped++;
FreeWinding (target); FreeWinding (target);
@ -410,8 +405,10 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
if (options.level > 3) { if (options.level > 3) {
winding_t *old = source; winding_t *old = source;
source = ClipToSeparators (thread, &stack, prevstack->pass, target, sep_t *sep;
source, 3); sep = FindSeparators (thread, prevstack->pass, target, 1);
source = ClipToSeparators (sep, source);
free_separators (thread, sep);
if (!source) { if (!source) {
thread->stats.sourceclipped++; thread->stats.sourceclipped++;
FreeWinding (target); FreeWinding (target);
@ -432,7 +429,8 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
FreeWinding (source); FreeWinding (source);
FreeWinding (target); FreeWinding (target);
} }
free_separators (thread, &stack); free_separators (thread, stack.separators[1]);
free_separators (thread, stack.separators[0]);
LOCK; LOCK;
set_delete (stack.mightsee); set_delete (stack.mightsee);