From 66feee616f5d07688ee2b03d116a0db5b81019d4 Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Fri, 22 Feb 2013 10:43:05 +1030 Subject: [PATCH] qbsp: maintain proper precendence ordering of brushes Need to be a little more careful to order brushes correctly when adding detail to the worldspawn. CSGFaces assumes that the brushes are ordered such that earlier brushes have chunks carved out of them by any later brushes that intersect them. Signed-off-by: Kevin Shanahan --- qbsp/brush.c | 39 +++++++++++++++++++++++++++++---------- qbsp/csg4.c | 24 +++++++++++------------- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/qbsp/brush.c b/qbsp/brush.c index 9323d8e2..135506df 100644 --- a/qbsp/brush.c +++ b/qbsp/brush.c @@ -837,14 +837,24 @@ void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum) { const char *classname; - brush_t *brush, *next, *water, *other; + brush_t *brush, *next, *water, *solid; mapbrush_t *mapbrush; vec3_t rotate_offset; int i, contents, cflags = 0; + /* + * The brush list need to be ordered: + * 1. detail water + * 2. water + * 3. detail solid + * 4. solid + * + * We can always just put water on the head of the list, but will need to + * insert solid brushes between any existing water and solids on the list. + */ + solid = NULL; + water = dst->brushes; classname = ValueForKey(src, "classname"); - other = dst->brushes; - water = NULL; /* Hipnotic rotation */ VectorCopy(vec3_origin, rotate_offset); @@ -887,8 +897,8 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum) brush->next = water; water = brush; } else { - brush->next = other; - other = brush; + brush->next = solid; + solid = brush; } AddToBounds(dst, brush->mins); @@ -897,13 +907,22 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum) Message(msgPercent, i + 1, src->nummapbrushes); } - // add all of the water textures at the start + /* Insert the solid brushes after the water */ for (brush = water; brush; brush = next) { next = brush->next; - brush->next = other; - other = brush; + if (!next || next->contents == CONTENTS_SOLID) + break; } + if (!brush) { + dst->brushes = solid; /* No water */ + return; + } + brush->next = solid; + dst->brushes = water; + if (!solid) + return; - // Store the brushes away - dst->brushes = other; + while (solid->next) + solid = solid->next; + solid->next = next; } diff --git a/qbsp/csg4.c b/qbsp/csg4.c index ca04238b..ee7cacdd 100644 --- a/qbsp/csg4.c +++ b/qbsp/csg4.c @@ -431,33 +431,31 @@ CSGFaces(const mapentity_t *ent) Message(msgProgress, "CSGFaces"); - if (validfaces == NULL) - validfaces = AllocMem(OTHER, sizeof(face_t *) * map.maxplanes, true); - else - memset(validfaces, 0, sizeof(face_t *) * map.maxplanes); + if (!validfaces) + validfaces = AllocMem(OTHER, sizeof(face_t *) * map.maxplanes, false); + + memset(validfaces, 0, sizeof(face_t *) * map.maxplanes); csgfaces = brushfaces = csgmergefaces = 0; // do the solid faces for (b1 = ent->brushes; b1; b1 = b1->next) { // set outside to a copy of the brush's faces CopyFacesToOutside(b1); - - // Why is this necessary? overwrite = false; - for (b2 = ent->brushes; b2; b2 = b2->next) { - // check bounding box first + if (b1 == b2) { + /* Brushes further down the list overried earlier ones */ + overwrite = true; + continue; + } + + /* check bounding box first */ for (i = 0; i < 3; i++) if (b1->mins[i] > b2->maxs[i] || b1->maxs[i] < b2->mins[i]) break; if (i < 3) continue; - // see if b2 needs to clip a chunk out of b1 - if (b1 == b2) { - overwrite = true; - continue; - } // divide faces by the planes of the new brush inside = outside; outside = NULL;