Rework FindSeparators to make use of the winding direction.

This is the second part of the separator search optimization from tyrutils
vis. With this, qfvis is getting close to tyrutils vis when
running single threaded (qfvis is suffering some nasty thread contention
and thus can't get below about 350 seconds with 4 threads). 808s vs 707s.
This commit is contained in:
Bill Currie 2013-03-15 22:05:01 +09:00
parent 9b10304c2f
commit 195bdcb92f

View file

@ -109,12 +109,12 @@ free_separators (threaddata_t *thread, sep_t *sep_list)
and enclosed by the planes is on the front side of the planes. and enclosed by the planes is on the front side of the planes.
*/ */
static sep_t * static sep_t *
FindSeparators (threaddata_t *thread, winding_t *source, winding_t *pass, FindSeparators (threaddata_t *thread, winding_t *source, const plane_t src_pl,
int flip) winding_t *pass, int flip)
{ {
float d; float d;
int i, j, k, l; int i, j, k, l;
int counts[3]; int count;
qboolean fliptest; qboolean fliptest;
plane_t plane; plane_t plane;
vec3_t v1, v2; vec3_t v1, v2;
@ -130,11 +130,27 @@ FindSeparators (threaddata_t *thread, winding_t *source, winding_t *pass,
// vertexes of pass on the front side and all of the vertexes of // vertexes of pass on the front side and all of the vertexes of
// source on the back side // source on the back side
for (j = 0; j < pass->numpoints; j++) { for (j = 0; j < pass->numpoints; j++) {
d = DotProduct (pass->points[j], src_pl.normal) - src_pl.dist;
if (d < -ON_EPSILON)
fliptest = true;
else if (d > ON_EPSILON)
fliptest = false;
else
continue; // The point lies in the source plane
VectorSubtract (pass->points[j], source->points[i], v2); VectorSubtract (pass->points[j], source->points[i], v2);
plane.normal[0] = v1[1] * v2[2] - v1[2] * v2[1]; if (fliptest) {
plane.normal[1] = v1[2] * v2[0] - v1[0] * v2[2]; //CrossProduct (v2, v1, plane.normal);
plane.normal[2] = v1[0] * v2[1] - v1[1] * v2[0]; plane.normal[0] = v2[1] * v1[2] - v2[2] * v1[1];
plane.normal[1] = v2[2] * v1[0] - v2[0] * v1[2];
plane.normal[2] = v2[0] * v1[1] - v2[1] * v1[0];
} else {
//CrossProduct (v1, v2, plane.normal);
plane.normal[0] = v1[1] * v2[2] - v1[2] * v2[1];
plane.normal[1] = v1[2] * v2[0] - v1[0] * v2[2];
plane.normal[2] = v1[0] * v2[1] - v1[1] * v2[0];
}
length = DotProduct (plane.normal, plane.normal); length = DotProduct (plane.normal, plane.normal);
@ -147,37 +163,15 @@ FindSeparators (threaddata_t *thread, winding_t *source, winding_t *pass,
plane.dist = DotProduct (pass->points[j], plane.normal); plane.dist = DotProduct (pass->points[j], plane.normal);
// find out which side of the generated seperating plane has the
// source portal
fliptest = false;
for (k = 0; k < source->numpoints; k++) {
if (k == i || k == l)
continue;
d = DotProduct (source->points[k], plane.normal) - plane.dist;
if (d < -ON_EPSILON) {
// source is on the negative side, so we want all
// pass and target on the positive side
fliptest = false;
break;
} else if (d > ON_EPSILON) {
// source is on the positive side, so we want all
// pass and target on the negative side
fliptest = true;
break;
}
}
if (k == source->numpoints)
continue; // planar with source portal
// flip the normal if the source portal is backwards // flip the normal if the source portal is backwards
if (fliptest) { //if (fliptest) {
VectorNegate (plane.normal, plane.normal); // VectorNegate (plane.normal, plane.normal);
plane.dist = -plane.dist; // plane.dist = -plane.dist;
} //}
// if all of the pass portal points are now on the positive side, // if all of the pass portal points are now on the positive side,
// this is the seperating plane // this is the seperating plane
counts[0] = counts[1] = counts[2] = 0; count = 0;
for (k = 0; k < pass->numpoints; k++) { for (k = 0; k < pass->numpoints; k++) {
if (k == j) if (k == j)
continue; continue;
@ -185,14 +179,12 @@ FindSeparators (threaddata_t *thread, winding_t *source, winding_t *pass,
if (d < -ON_EPSILON) if (d < -ON_EPSILON)
break; break;
else if (d > ON_EPSILON) else if (d > ON_EPSILON)
counts[0]++; count++;
else
counts[2]++;
} }
if (k != pass->numpoints) if (k != pass->numpoints)
continue; // points on negative side, not a seperating plane continue; // points on negative side, not a seperating plane
if (!counts[0]) { if (!count) {
continue; // planar with seperating plane continue; // planar with seperating plane
} }
@ -353,6 +345,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
winding_t *old = target; winding_t *old = target;
if (!stack.separators[0]) if (!stack.separators[0])
stack.separators[0] = FindSeparators (thread, source, stack.separators[0] = FindSeparators (thread, source,
thread->pstack_head.portalplane,
prevstack->pass, 0); prevstack->pass, 0);
target = ClipToSeparators (stack.separators[0], target); target = ClipToSeparators (stack.separators[0], target);
if (!target) { if (!target) {
@ -374,6 +367,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
winding_t *old = target; winding_t *old = target;
if (!stack.separators[1]) if (!stack.separators[1])
stack.separators[1] = FindSeparators (thread, prevstack->pass, stack.separators[1] = FindSeparators (thread, prevstack->pass,
prevstack->portalplane,
source, 1); source, 1);
target = ClipToSeparators (stack.separators[1], target); target = ClipToSeparators (stack.separators[1], target);
if (!target) { if (!target) {
@ -391,7 +385,8 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
if (options.level > 2) { if (options.level > 2) {
winding_t *old = source; winding_t *old = source;
sep_t *sep; sep_t *sep;
sep = FindSeparators (thread, target, prevstack->pass, 0); sep = FindSeparators (thread, target, portal->plane,
prevstack->pass, 0);
source = ClipToSeparators (sep, source); source = ClipToSeparators (sep, source);
free_separators (thread, sep); free_separators (thread, sep);
if (!source) { if (!source) {
@ -406,7 +401,8 @@ 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;
sep_t *sep; sep_t *sep;
sep = FindSeparators (thread, prevstack->pass, target, 1); sep = FindSeparators (thread, prevstack->pass,
prevstack->portalplane, target, 1);
source = ClipToSeparators (sep, source); source = ClipToSeparators (sep, source);
free_separators (thread, sep); free_separators (thread, sep);
if (!source) { if (!source) {