qbsp: add func_detail_fence
This commit is contained in:
parent
7198884392
commit
77f3da30bf
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
10
qbsp/csg4.cc
10
qbsp/csg4.cc
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue