From 057a5cc624495c68c697ca6251b6455e3b09a95d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 14 Mar 2013 14:01:26 +0900 Subject: [PATCH] Make BasePortalVis another 17% faster. I had forgotten to skip the refined tests when the sphere was entirely on the relevant side of the plane. Now BasePortalVis for gmsp3v2 takes 11s on my machine (it was 13 with the previous optimization and 15.9 before that). Also, write some comments describing how BasePortalVis works. --- tools/qfvis/source/base-vis.c | 65 ++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index ca96c66bc..3470f1300 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -106,6 +106,7 @@ BasePortalVis (void) portal_t *tp, *portal; winding_t *winding; int base_mightsee = 0; + int tp_side, portal_side; double start, end; start = Sys_DoubleTime (); @@ -119,30 +120,54 @@ BasePortalVis (void) if (j == i) continue; - if (test_sphere (&tp->sphere, &portal->plane) < 0) - continue; // entirely behind - if (test_sphere (&portal->sphere, &tp->plane) > 0) - continue; // entirely behind + // If the target portal is behind the portals's plane, then it + // can't possibly be seen by the portal. + // + // If the portal is in front of the target's plane, then the target + // is of no interest as it is facing counter to the flow of + // visibility. - winding = tp->winding; - for (k = 0; k < winding->numpoints; k++) { - d = DotProduct (winding->points[k], - portal->plane.normal) - portal->plane.dist; - if (d > ON_EPSILON) - break; + // First check using the bounding spheres of the two portals. + tp_side = test_sphere (&tp->sphere, &portal->plane); + if (tp_side < 0) { + // The test portal definitely is entirely behind the portal's + // plane. + continue; // entirely behind + } + portal_side = test_sphere (&portal->sphere, &tp->plane); + if (portal_side > 0) { + // The portal definitely is entirely in front of the test + // portal's plane. + continue; // entirely in front } - if (k == winding->numpoints) - continue; // no points on front - winding = portal->winding; - for (k = 0; k < winding->numpoints; k++) { - d = DotProduct (winding->points[k], - tp->plane.normal) - tp->plane.dist; - if (d < -ON_EPSILON) - break; + if (tp_side == 0) { + // The test portal's sphere touches the portal's plane, so + // do a more refined check. + winding = tp->winding; + for (k = 0; k < winding->numpoints; k++) { + d = DotProduct (winding->points[k], + portal->plane.normal) - portal->plane.dist; + if (d > ON_EPSILON) + break; + } + if (k == winding->numpoints) + continue; // no points on front + } + + if (portal_side == 0) { + // The portal's sphere touches the test portal's plane, so + // do a more refined check. + winding = portal->winding; + for (k = 0; k < winding->numpoints; k++) { + d = DotProduct (winding->points[k], + tp->plane.normal) - tp->plane.dist; + if (d < -ON_EPSILON) + break; + } + if (k == winding->numpoints) + continue; // no points on front } - if (k == winding->numpoints) - continue; // no points on front set_add (portalsee, j); }