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 <kmshanah@disenchant.net>
This commit is contained in:
Kevin Shanahan 2013-02-22 10:43:05 +10:30
parent 1b3a8b049f
commit 66feee616f
2 changed files with 40 additions and 23 deletions

View File

@ -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;
}

View File

@ -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;