From 44e1eccca609c6b82b5eda72392c5707a4c80ffc Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 18 Oct 2015 00:42:15 -0600 Subject: [PATCH] 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. --- qbsp/qbsp.h | 2 ++ qbsp/solidbsp.c | 78 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/qbsp/qbsp.h b/qbsp/qbsp.h index 343b21fe..b201c9d4 100644 --- a/qbsp/qbsp.h +++ b/qbsp/qbsp.h @@ -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; diff --git a/qbsp/solidbsp.c b/qbsp/solidbsp.c index e5d6ae1e..ed0a807f 100644 --- a/qbsp/solidbsp.c +++ b/qbsp/solidbsp.c @@ -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])