qbsp: add func_detail_fence

This commit is contained in:
Eric Wasylishen 2017-06-09 15:03:56 -06:00
parent 7198884392
commit 77f3da30bf
8 changed files with 83 additions and 13 deletions

View File

@ -63,7 +63,7 @@ typedef struct mapentity_s {
int nummapbrushes;
// Temporary lists used to build `brushes` in the correct order.
brush_t *solid, *sky, *detail, *detail_illusionary, *liquid;
brush_t *solid, *sky, *detail, *detail_illusionary, *detail_fence, *liquid;
epair_t *epairs;
vec3_t mins, maxs;

View File

@ -109,6 +109,7 @@
#define CONTENTS_ORIGIN -9 /* compiler internal use only */
#define CONTENTS_DETAIL -10 /* compiler internal use only */
#define CONTENTS_DETAIL_ILLUSIONARY -11 /* compiler internal use only */
#define CONTENTS_DETAIL_FENCE -12 /* compiler internal use only */
// Special contents flags for the compiler only
#define CFLAGS_STRUCTURAL_COVERED_BY_DETAIL (1U << 0)
@ -349,6 +350,7 @@ typedef struct options_s {
bool fOmitDetail;
bool fOmitDetailWall;
bool fOmitDetailIllusionary;
bool fOmitDetailFence;
bool fForcePRT1;
} options_t;

View File

@ -944,6 +944,11 @@ Entity_SortBrushes(mapentity_t *dst)
*nextLink = dst->liquid;
nextLink = &last->next;
}
if (dst->detail_fence) {
brush_t *last = Brush_ListTail(dst->detail_fence);
*nextLink = dst->detail_fence;
nextLink = &last->next;
}
if (dst->detail) {
brush_t *last = Brush_ListTail(dst->detail);
*nextLink = dst->detail;
@ -977,12 +982,13 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
vec3_t rotate_offset;
int i, contents, cflags = 0;
int lmshift;
bool detail, detail_illusionary;
bool detail, detail_fence, detail_illusionary;
/*
* The brush list needs to be ordered (lowest to highest priority):
* - detail_illusionary (which is saved as empty)
* - liquid
* - detail_fence
* - detail (which is solid)
* - sky
* - solid
@ -1039,6 +1045,11 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
cflags |= CFLAGS_DETAIL_WALL;
}
detail_fence = false;
if (!Q_strcasecmp(classname, "func_detail_fence") && !options.fNodetail) {
detail_fence = true;
}
detail_illusionary = false;
if (!Q_strcasecmp(classname, "func_detail_illusionary") && !options.fNodetail) {
detail_illusionary = true;
@ -1069,6 +1080,8 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
continue;
if (options.fOmitDetailIllusionary && detail_illusionary)
continue;
if (options.fOmitDetailFence && detail_fence)
continue;
/* turn solid brushes into detail, if we're in hull0 */
if (hullnum == 0 && contents == CONTENTS_SOLID) {
@ -1076,6 +1089,8 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
contents = CONTENTS_DETAIL;
} else if (detail_illusionary) {
contents = CONTENTS_DETAIL_ILLUSIONARY;
} else if (detail_fence) {
contents = CONTENTS_DETAIL_FENCE;
}
}
@ -1143,6 +1158,9 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
} else if (brush->contents == CONTENTS_DETAIL_ILLUSIONARY) {
brush->next = dst->detail_illusionary;
dst->detail_illusionary = brush;
} else if (brush->contents == CONTENTS_DETAIL_FENCE) {
brush->next = dst->detail_fence;
dst->detail_fence = brush;
} else {
brush->next = dst->liquid;
dst->liquid = brush;

View File

@ -351,6 +351,7 @@ SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map<int, face_t *> &pla
// want the face. So just set the texinfo to "skip" so it gets deleted.
if (face->contents[1] == CONTENTS_DETAIL
|| face->contents[1] == CONTENTS_DETAIL_ILLUSIONARY
|| face->contents[1] == CONTENTS_DETAIL_FENCE
|| (face->cflags[1] & CFLAGS_WAS_ILLUSIONARY)) {
newface->texinfo = MakeSkipTexinfo();
}
@ -590,6 +591,12 @@ CSGFaces(const mapentity_t *entity)
*/
continue;
}
if (clipbrush->contents == CONTENTS_DETAIL_FENCE
&& brush->contents != CONTENTS_DETAIL_FENCE) {
/* CONTENTS_DETAIL_FENCE never clips anything but itself */
continue;
}
/* check bounding box first */
for (i = 0; i < 3; i++) {
@ -631,7 +638,8 @@ CSGFaces(const mapentity_t *entity)
&& clipbrush->contents != CONTENTS_SKY
&& clipbrush->contents != CONTENTS_DETAIL))
|| (IsLiquid(brush->contents) && clipbrush->contents == CONTENTS_DETAIL_ILLUSIONARY)
|| (brush->contents == CONTENTS_DETAIL_ILLUSIONARY && IsLiquid(clipbrush->contents)))
|| (brush->contents == CONTENTS_DETAIL_ILLUSIONARY && IsLiquid(clipbrush->contents))
|| (brush->contents == CONTENTS_DETAIL_FENCE && IsLiquid(clipbrush->contents)))
{
SaveInsideFaces(inside, clipbrush, &outside);
} else {

View File

@ -1530,6 +1530,8 @@ IsWorldBrushEntity(const mapentity_t *entity)
return true;
if (!Q_strcasecmp(classname, "func_detail_wall"))
return true;
if (!Q_strcasecmp(classname, "func_detail_fence"))
return true;
return false;
}

View File

@ -76,6 +76,7 @@ ProcessEntity(mapentity_t *entity, const int hullnum)
entity->sky = NULL;
entity->detail = NULL;
entity->detail_illusionary = NULL;
entity->detail_fence = NULL;
entity->liquid = NULL;
entity->numbrushes = 0;
for (i = 0; i < 3; i++) {
@ -113,6 +114,7 @@ ProcessEntity(mapentity_t *entity, const int hullnum)
int detail_all_count = Brush_ListCount(entity->detail); /* including CFLAGS_DETAIL_WALL */
int detail_wall_count = Brush_ListCountWithCFlags(entity->detail, CFLAGS_DETAIL_WALL);
int detail_illusionarycount = Brush_ListCount(entity->detail_illusionary);
int detail_fence_count = Brush_ListCount(entity->detail_fence);
int liquidcount = Brush_ListCount(entity->liquid);
int nondetailcount = (solidcount + skycount + liquidcount);
@ -125,6 +127,9 @@ ProcessEntity(mapentity_t *entity, const int hullnum)
if (detail_wall_count > 0) {
Message(msgStat, "%8d detail wall", detail_wall_count);
}
if (detail_fence_count > 0) {
Message(msgStat, "%8d detail fence", detail_fence_count);
}
if (detail_illusionarycount > 0) {
Message(msgStat, "%8d detail illusionary", detail_illusionarycount);
}
@ -655,6 +660,7 @@ PrintOptions(void)
" -omitdetail func_detail brushes are omitted from the compile\n"
" -omitdetailwall func_detail_wall brushes are omitted from the compile\n"
" -omitdetailillusionary func_detail_illusionary brushes are omitted from the compile\n"
" -omitdetailfence func_detail_fence brushes are omitted from the compile\n"
" -convert <fmt> Convert a .MAP to a different .MAP format. fmt can be: quake, quake2, valve, bp (brush primitives).\n"
" sourcefile .MAP file to process\n"
" destfile .BSP file to output\n");
@ -841,6 +847,8 @@ ParseOptions(char *szOptions)
options.fOmitDetailWall = true;
} else if (!Q_strcasecmp(szTok, "omitdetailillusionary")) {
options.fOmitDetailIllusionary = true;
} else if (!Q_strcasecmp(szTok, "omitdetailfence")) {
options.fOmitDetailFence = true;
} else if (!Q_strcasecmp(szTok, "convert")) {
szTok2 = GetTok(szTok + strlen(szTok) + 1, szEnd);
if (!szTok2)

View File

@ -27,7 +27,7 @@ int splitnodes;
static int leaffaces;
static int nodefaces;
static int c_solid, c_empty, c_water, c_detail, c_detail_illusionary;
static int c_solid, c_empty, c_water, c_detail, c_detail_illusionary, c_detail_fence;
static bool usemidsplit;
//============================================================================
@ -64,6 +64,9 @@ DetailToSolid(node_t *node)
} else if (node->contents == CONTENTS_DETAIL_ILLUSIONARY) {
node->contents = CONTENTS_EMPTY;
}
/* N.B.: CONTENTS_DETAIL_FENCE is not remapped to CONTENTS_SOLID until the very last moment,
* because we want to generate a leaf (if we set it to CONTENTS_SOLID now it would use leaf 0).
*/
return;
} else {
DetailToSolid(node->children[0]);
@ -559,6 +562,10 @@ CalcSurfaceInfo(surface_t *surf)
|| (f->contents[1] == CONTENTS_DETAIL_ILLUSIONARY))
faceIsDetail = true;
if ((f->contents[0] == CONTENTS_DETAIL_FENCE)
|| (f->contents[1] == CONTENTS_DETAIL_FENCE))
faceIsDetail = true;
if ((f->cflags[0] & CFLAGS_WAS_ILLUSIONARY)
|| (f->cflags[1] & CFLAGS_WAS_ILLUSIONARY))
faceIsDetail = true;
@ -732,10 +739,13 @@ GetContentsName( int Contents ) {
case CONTENTS_DETAIL:
return "Detail";
case CONTENTS_DETAIL_ILLUSIONARY:
return "DetailIllusionary";
case CONTENTS_DETAIL_FENCE:
return "DetailFence";
default:
return "Error";
}
@ -744,12 +754,14 @@ GetContentsName( int Contents ) {
static int Contents_Priority(int contents)
{
switch (contents) {
case CONTENTS_SOLID: return 6;
case CONTENTS_SOLID: return 7;
case CONTENTS_SKY: return 5;
case CONTENTS_SKY: return 6;
case CONTENTS_DETAIL: return 5;
case CONTENTS_DETAIL_FENCE: return 4;
case CONTENTS_DETAIL: return 4;
case CONTENTS_DETAIL_ILLUSIONARY: return 3;
case CONTENTS_WATER: return 2;
@ -831,6 +843,9 @@ LinkConvexFaces(surface_t *planelist, node_t *leafnode)
case CONTENTS_DETAIL_ILLUSIONARY:
c_detail_illusionary++;
break;
case CONTENTS_DETAIL_FENCE:
c_detail_fence++;
break;
default:
Error("Bad contents in face (%s)", __func__);
}
@ -1015,6 +1030,7 @@ SolidBSP(const mapentity_t *entity, surface_t *surfhead, bool midsplit)
c_water = 0;
c_detail = 0;
c_detail_illusionary = 0;
c_detail_fence = 0;
PartitionSurfaces(surfhead, headnode);
@ -1024,6 +1040,7 @@ SolidBSP(const mapentity_t *entity, surface_t *surfhead, bool midsplit)
Message(msgStat, "%8d water leafs", c_water);
Message(msgStat, "%8d detail leafs", c_detail);
Message(msgStat, "%8d detail illusionary leafs", c_detail_illusionary);
Message(msgStat, "%8d detail fence leafs", c_detail_fence);
Message(msgStat, "%8d leaffaces", leaffaces);
Message(msgStat, "%8d nodefaces", nodefaces);

View File

@ -39,6 +39,21 @@ AssertVanillaContentType(int content)
}
}
static int
RemapContentsForExport(int content)
{
if (content == CONTENTS_DETAIL_FENCE) {
/*
* This is for func_detail_wall.. we want to write a solid leaf that has faces,
* because it may be possible to see inside (fence textures).
*
* Normally solid leafs are not written and just referenced as leaf 0.
*/
return CONTENTS_SOLID;
}
return content;
}
static void
ExportNodePlanes_r(node_t *node, int *planemap)
{
@ -362,7 +377,7 @@ ExportLeaf_BSP29(mapentity_t *entity, node_t *node)
leaves->index++;
map.cTotal[LUMP_LEAFS]++;
dleaf->contents = node->contents;
dleaf->contents = RemapContentsForExport(node->contents);
AssertVanillaContentType(dleaf->contents);
/*
@ -412,7 +427,7 @@ ExportLeaf_BSP2(mapentity_t *entity, node_t *node)
leaves->index++;
map.cTotal[LUMP_LEAFS]++;
dleaf->contents = node->contents;
dleaf->contents = RemapContentsForExport(node->contents);
AssertVanillaContentType(dleaf->contents);
/*
@ -462,7 +477,7 @@ ExportLeaf_BSP2rmq(mapentity_t *entity, node_t *node)
leaves->index++;
map.cTotal[LUMP_LEAFS]++;
dleaf->contents = node->contents;
dleaf->contents = RemapContentsForExport(node->contents);
AssertVanillaContentType(dleaf->contents);
/*