qbsp: add func_group support

Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
Kevin Shanahan 2013-03-04 21:18:55 +10:30
parent 4063d8aade
commit 3426e7e8c2
4 changed files with 64 additions and 28 deletions

View File

@ -2,6 +2,7 @@
* qbsp: respect floating point texture rotation and shift in map files * qbsp: respect floating point texture rotation and shift in map files
* qbsp: support for Valve's 220 map format used in later Worldcraft/Hammer * qbsp: support for Valve's 220 map format used in later Worldcraft/Hammer
* qbsp: support func_group entities used by Radiant and similar editors
* light: fixed a race condition in multithreaded coloured light processing * light: fixed a race condition in multithreaded coloured light processing
* light: fixed bug preventing use of all 4 light styles in a common case * light: fixed bug preventing use of all 4 light styles in a common case
* light: implemented attenutation formulae "delay" 4+5, ala Bengt's tools * light: implemented attenutation formulae "delay" 4+5, ala Bengt's tools

View File

@ -849,8 +849,9 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
* 3. detail solid * 3. detail solid
* 4. solid * 4. solid
* *
* We can always just put water on the head of the list, but will need to * We will add func_group brushes first and detail brushes last, so we can
* insert solid brushes between any existing water and solids on the list. * 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; solid = NULL;
water = dst->brushes; water = dst->brushes;

View File

@ -556,6 +556,23 @@ PreParseFile(const char *buf)
texinfo->count = map.maxfaces; texinfo->count = map.maxfaces;
} }
/*
* Special world entities are entities which have their brushes added to the
* world before being removed from the map. Currently func_detail and
* func_group.
*/
static bool
IsWorldBrushEntity(const mapentity_t *entity)
{
const char *classname = ValueForKey(entity, "classname");
if (!strcmp(classname, "func_detail"))
return true;
if (!strcmp(classname, "func_group"))
return true;
return false;
}
void void
LoadMapFile(void) LoadMapFile(void)
@ -565,7 +582,7 @@ LoadMapFile(void)
int i, j, length, cAxis; int i, j, length, cAxis;
void *pTemp; void *pTemp;
struct lumpdata *texinfo; struct lumpdata *texinfo;
mapentity_t *ent; mapentity_t *entity;
mapbrush_t *brush; mapbrush_t *brush;
mapface_t *face, *face2; mapface_t *face, *face2;
@ -576,16 +593,15 @@ LoadMapFile(void)
ParserInit(&parser, buf); ParserInit(&parser, buf);
map.numfaces = map.numbrushes = map.numentities = 0; map.numfaces = map.numbrushes = map.numentities = 0;
ent = map.entities; entity = map.entities;
while (ParseEntity(&parser, ent)) { while (ParseEntity(&parser, entity)) {
/* Allocate memory for the bmodel, if needed. */ /* Allocate memory for the bmodel, if needed. */
const char *classname = ValueForKey(ent, "classname"); if (!IsWorldBrushEntity(entity) && entity->nummapbrushes) {
if (strcmp(classname, "func_detail") && ent->nummapbrushes) { entity->lumps[BSPMODEL].data = AllocMem(BSPMODEL, 1, true);
ent->lumps[BSPMODEL].data = AllocMem(BSPMODEL, 1, true); entity->lumps[BSPMODEL].count = 1;
ent->lumps[BSPMODEL].count = 1;
} }
map.numentities++; map.numentities++;
ent++; entity++;
} }
/* Double check the entity count matches our pre-parse count */ /* Double check the entity count matches our pre-parse count */
@ -741,7 +757,6 @@ WriteEntitiesToString(void)
int cLen; int cLen;
struct lumpdata *entities; struct lumpdata *entities;
const mapentity_t *ent; const mapentity_t *ent;
const char *classname;
map.cTotal[BSPENT] = 0; map.cTotal[BSPENT] = 0;
@ -749,8 +764,7 @@ WriteEntitiesToString(void)
entities = &map.entities[i].lumps[BSPENT]; entities = &map.entities[i].lumps[BSPENT];
/* Check if entity needs to be removed */ /* Check if entity needs to be removed */
classname = ValueForKey(ent, "classname"); if (!ent->epairs || IsWorldBrushEntity(ent)) {
if (!ent->epairs || !strcmp(classname, "func_detail")) {
entities->count = 0; entities->count = 0;
entities->data = NULL; entities->data = NULL;
continue; continue;

View File

@ -40,15 +40,20 @@ ProcessEntity(mapentity_t *ent, const int hullnum)
int i, numportals; int i, numportals;
surface_t *surfs; surface_t *surfs;
node_t *nodes; node_t *nodes;
const char *class; const char *classname;
/* No map brushes means non-bmodel entity */ /* No map brushes means non-bmodel entity */
if (!ent->nummapbrushes) if (!ent->nummapbrushes)
return; return;
/* func_detail entities get their brushes added to the worldspawn */ /*
class = ValueForKey(ent, "classname"); * func_group and func_detail entities get their brushes added to the
if (!strcmp(class, "func_detail")) * worldspawn
*/
classname = ValueForKey(ent, "classname");
if (!strcmp(classname, "func_group"))
return;
if (!strcmp(classname, "func_detail"))
return; return;
if (ent != pWorldEnt) { if (ent != pWorldEnt) {
@ -84,23 +89,38 @@ ProcessEntity(mapentity_t *ent, const int hullnum)
PrintEntity(ent); PrintEntity(ent);
Error(errNoValidBrushes); Error(errNoValidBrushes);
} }
Message(msgStat, "%5i brushes", ent->numbrushes);
/* /*
* If this is the world entity, find all func_detail entities and * If this is the world entity, find all func_group and func_detail
* add their brushes with the detail flag set. * entities and add their brushes with the appropriate contents flag set.
*/ */
if (ent == pWorldEnt) { if (ent == pWorldEnt) {
const mapentity_t *detail; const mapentity_t *source;
const int detailstart = ent->numbrushes; int detailcount;
detail = map.entities + 1; /* Add func_group brushes first */
for (i = 1; i < map.numentities; i++, detail++) { source = map.entities + 1;
class = ValueForKey(detail, "classname"); for (i = 1; i < map.numentities; i++, source++) {
if (!strcmp(class, "func_detail")) classname = ValueForKey(source, "classname");
Brush_LoadEntity(ent, detail, hullnum); if (!strcmp(classname, "func_group"))
Brush_LoadEntity(ent, source, hullnum);
} }
Message(msgStat, "%5i detail", ent->numbrushes - detailstart);
/* Add detail brushes next */
detailcount = 0;
source = map.entities + 1;
for (i = 1; i < map.numentities; i++, source++) {
classname = ValueForKey(source, "classname");
if (!strcmp(classname, "func_detail")) {
int detailstart = ent->numbrushes;
Brush_LoadEntity(ent, source, hullnum);
detailcount += ent->numbrushes - detailstart;
}
}
Message(msgStat, "%5i brushes", ent->numbrushes - detailcount);
Message(msgStat, "%5i detail", detailcount);
} else {
Message(msgStat, "%5i brushes", ent->numbrushes);
} }
/* /*