qbsp: change detail handling, from qbsp-xt.

MidSplit now does two passes (structural/detail), like ChoosePlaneFromList.
Now, the first pass will pick among planes that have at least one structural face, and zero or more detail faces.
The second pass will pick among planes that have no structural faces, and zero or more detail faces.

This fixes the hull 1 leak in telefragged.map introduced when I added txqbsp's maxNodeSize feature,
and also reduces the cluster and portal count in jam6_ericwtronyn.map a bit.
This commit is contained in:
Eric Wasylishen 2015-10-18 00:42:15 -06:00
parent ddfa2c7ad5
commit 44e1eccca6
2 changed files with 54 additions and 26 deletions

View File

@ -287,6 +287,8 @@ typedef struct surface_s {
// as a splitting node
bool detail_separator; // true if split generated by a detail brush
face_t *faces; // links to all faces on either side of the surf
bool has_detail; // 1 if the surface has detail brushes
bool has_struct; // 1 if the surface has non-detail brushes
} surface_t;

View File

@ -239,41 +239,57 @@ ChooseMidPlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
surface_t *surf, *bestsurface;
vec_t metric, bestmetric;
plane_t *plane;
int pass;
/* pick the plane that splits the least */
bestmetric = VECT_MAX;
bestsurface = NULL;
for (surf = surfaces; surf; surf = surf->next) {
if (surf->onnode)
continue;
/* check for axis aligned surfaces */
plane = &map.planes[surf->planenum];
if (!(plane->type < 3))
continue;
/* calculate the split metric, smaller values are better */
metric = SplitPlaneMetric(plane, mins, maxs);
if (metric < bestmetric) {
bestmetric = metric;
bestsurface = surf;
}
}
if (!bestsurface) {
/* Choose based on spatial subdivision only */
for (pass = 0; pass < 2; pass++) {
for (surf = surfaces; surf; surf = surf->next) {
if (surf->onnode)
continue;
if( surf->has_struct && pass )
continue;
if( !surf->has_struct && !pass )
continue;
/* check for axis aligned surfaces */
plane = &map.planes[surf->planenum];
if (!(plane->type < 3))
continue;
/* calculate the split metric, smaller values are better */
metric = SplitPlaneMetric(plane, mins, maxs);
if (metric < bestmetric) {
bestmetric = metric;
bestsurface = surf;
}
}
if (!bestsurface) {
/* Choose based on spatial subdivision only */
for (surf = surfaces; surf; surf = surf->next) {
if (surf->onnode)
continue;
if( surf->has_struct && pass )
continue;
if( !surf->has_struct && !pass )
continue;
plane = &map.planes[surf->planenum];
metric = SplitPlaneMetric(plane, mins, maxs);
if (metric < bestmetric) {
bestmetric = metric;
bestsurface = surf;
}
}
}
if (bestsurface)
break;
}
if (!bestsurface)
Error("No valid planes in surface list (%s)", __func__);
@ -294,7 +310,7 @@ static surface_t *
ChoosePlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
{
int pass, splits, minsplits;
bool hintsplit, detailtest;
bool hintsplit;
surface_t *surf, *surf2, *bestsurface;
vec_t distribution, bestdistribution;
const plane_t *plane, *plane2;
@ -316,17 +332,17 @@ ChoosePlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
* Check that the surface has a suitable face for the current pass
* and check whether this is a hint split.
*/
detailtest = hintsplit = false;
hintsplit = false;
for (face = surf->faces; face; face = face->next) {
if (pass && (face->cflags[1] & CFLAGS_DETAIL))
detailtest = true;
if (!pass && !(face->cflags[1] & CFLAGS_DETAIL))
detailtest = true;
if (texinfo[face->texinfo].flags & TEX_HINT)
hintsplit = true;
}
if (!detailtest)
if( surf->has_struct && pass )
continue;
if( !surf->has_struct && !pass )
continue;
plane = &map.planes[surf->planenum];
splits = 0;
@ -467,9 +483,19 @@ CalcSurfaceInfo(surface_t *surf)
surf->maxs[i] = -VECT_MAX;
}
surf->has_detail = false;
surf->has_struct = false;
for (f = surf->faces; f; f = f->next) {
if (f->contents[0] >= 0 || f->contents[1] >= 0)
Error("Bad contents in face (%s)", __func__);
if ((f->cflags[0] & CFLAGS_DETAIL)
|| (f->cflags[1] & CFLAGS_DETAIL))
surf->has_detail = true;
else
surf->has_struct = true;
for (i = 0; i < f->w.numpoints; i++)
for (j = 0; j < 3; j++) {
if (f->w.points[i][j] < surf->mins[j])