qbsp: add create_detail_illusionary/fence/solid_contents

This commit is contained in:
Eric Wasylishen 2022-06-10 01:07:20 -06:00
parent 014e0d8aaa
commit 3c4f798e97
5 changed files with 71 additions and 13 deletions

View File

@ -70,6 +70,12 @@ struct gamedef_generic_t : public gamedef_t
contentflags_t create_liquid_contents(const int32_t &, const int32_t &) const { throw std::bad_cast(); }
contentflags_t create_detail_illusionary_contents(const contentflags_t &original) const { throw std::bad_cast(); }
contentflags_t create_detail_fence_contents(const contentflags_t &original) const { throw std::bad_cast(); }
contentflags_t create_detail_solid_contents(const contentflags_t &original) const { throw std::bad_cast(); }
bool contents_are_any_detail(const contentflags_t &) const { throw std::bad_cast(); }
bool contents_are_detail_solid(const contentflags_t &contents) const { throw std::bad_cast(); }
@ -213,6 +219,19 @@ struct gamedef_q1_like_t : public gamedef_t
return {liquid_type, cflags};
}
contentflags_t create_detail_illusionary_contents(const contentflags_t &original) const {
// ignore the original contents in Q1
return {0, CFLAGS_DETAIL_ILLUSIONARY};
}
contentflags_t create_detail_fence_contents(const contentflags_t &original) const {
return {0, CFLAGS_DETAIL_FENCE};
}
contentflags_t create_detail_solid_contents(const contentflags_t &original) const {
return {0, CFLAGS_DETAIL};
}
bool contents_are_any_detail(const contentflags_t &contents) const
{
// in Q1, there are only CFLAGS_DETAIL, CFLAGS_DETAIL_ILLUSIONARY, or CFLAGS_DETAIL_FENCE
@ -555,6 +574,26 @@ struct gamedef_q2_t : public gamedef_t
}
}
contentflags_t create_detail_illusionary_contents(const contentflags_t &original) const {
contentflags_t result = original;
result.native &= ~Q2_CONTENTS_SOLID;
result.native |= Q2_CONTENTS_MIST | Q2_CONTENTS_DETAIL;
return result;
}
contentflags_t create_detail_fence_contents(const contentflags_t &original) const {
contentflags_t result = original;
result.native &= ~Q2_CONTENTS_SOLID;
result.native |= (Q2_CONTENTS_WINDOW | Q2_CONTENTS_TRANSLUCENT | Q2_CONTENTS_DETAIL);
return result;
}
contentflags_t create_detail_solid_contents(const contentflags_t &original) const {
contentflags_t result = original;
result.native |= (Q2_CONTENTS_SOLID | Q2_CONTENTS_DETAIL);
return result;
}
bool contents_are_any_detail(const contentflags_t &contents) const
{
return ((contents.native & Q2_CONTENTS_DETAIL) != 0);
@ -562,20 +601,32 @@ struct gamedef_q2_t : public gamedef_t
bool contents_are_detail_solid(const contentflags_t &contents) const
{
// fixme-brushbsp: check native flag
return ((contents.extended & CFLAGS_DETAIL) != 0);
int32_t test = (Q2_CONTENTS_DETAIL|Q2_CONTENTS_SOLID);
return ((contents.native & test) == test);
}
bool contents_are_detail_fence(const contentflags_t &contents) const
{
// fixme-brushbsp: check native flag
return ((contents.extended & CFLAGS_DETAIL_FENCE) != 0);
if (contents.native & Q2_CONTENTS_SOLID) {
return false;
}
int32_t test = (Q2_CONTENTS_DETAIL|Q2_CONTENTS_WINDOW);
return ((contents.native & test) == test);
}
bool contents_are_detail_illusionary(const contentflags_t &contents) const
{
// fixme-brushbsp: check native flag
return ((contents.extended & CFLAGS_DETAIL_ILLUSIONARY) != 0);
if (contents.native & Q2_CONTENTS_SOLID) {
return false;
}
int32_t mist1_type = (Q2_CONTENTS_DETAIL|Q2_CONTENTS_MIST);
int32_t mist2_type = (Q2_CONTENTS_DETAIL|Q2_CONTENTS_AUX);
return ((contents.native & mist1_type) == mist1_type)
|| ((contents.native & mist2_type) == mist2_type);
}
bool contents_are_empty(const contentflags_t &contents) const
@ -740,6 +791,7 @@ struct gamedef_q2_t : public gamedef_t
// FIXME: this is a bit of a hack, but this is because clip
// and liquids and stuff are already handled *like* detail by
// the compiler.
// fixme-brushbsp: remove this
if (surf_contents.extended & CFLAGS_DETAIL) {
if (!(surf_contents.native & Q2_CONTENTS_SOLID)) {
surf_contents.extended &= ~CFLAGS_DETAIL;

View File

@ -626,7 +626,9 @@ struct contentflags_t
constexpr bool clips_same_type() const { return !(extended & CFLAGS_NO_CLIPPING_SAME_TYPE); }
constexpr bool is_fence() const { return (extended & (CFLAGS_DETAIL_FENCE | CFLAGS_DETAIL_ILLUSIONARY)) != 0; }
bool is_fence(const gamedef_t *game) const {
return is_detail_fence(game) || is_detail_illusionary(game);
}
// check if this content's `type` - which is distinct from various
// flags that turn things on/off - match. Exactly what the native
@ -1796,6 +1798,9 @@ struct gamedef_t
virtual contentflags_t create_solid_contents(const int32_t &cflags = 0) const = 0;
virtual contentflags_t create_sky_contents(const int32_t &cflags = 0) const = 0;
virtual contentflags_t create_liquid_contents(const int32_t &liquid_type, const int32_t &cflags = 0) const = 0;
virtual contentflags_t create_detail_illusionary_contents(const contentflags_t &original) const = 0;
virtual contentflags_t create_detail_fence_contents(const contentflags_t &original) const = 0;
virtual contentflags_t create_detail_solid_contents(const contentflags_t &original) const = 0;
virtual bool contents_are_any_detail(const contentflags_t &contents) const = 0;
virtual bool contents_are_detail_solid(const contentflags_t &contents) const = 0;
virtual bool contents_are_detail_fence(const contentflags_t &contents) const = 0;

View File

@ -896,11 +896,11 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
/* turn solid brushes into detail, if we're in hull0 */
if (hullnum <= 0 && contents.is_solid(options.target_game)) {
if (detail_illusionary) {
contents = {contents.native, CFLAGS_DETAIL_ILLUSIONARY};
contents = options.target_game->create_detail_illusionary_contents(contents);
} else if (detail_fence) {
contents = {contents.native, CFLAGS_DETAIL_FENCE};
contents = options.target_game->create_detail_fence_contents(contents);
} else if (detail) {
contents = {contents.native, CFLAGS_DETAIL};
contents = options.target_game->create_detail_solid_contents(contents);
}
}
@ -950,7 +950,7 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
contents type.
*/
if (hullnum <= 0 && mirrorinside) {
contents = {contents.native, CFLAGS_DETAIL_FENCE};
contents = options.target_game->create_detail_fence_contents(contents);
}
}

View File

@ -300,7 +300,7 @@ static bool ShouldClipbrushEatBrush(const brush_t &brush, const brush_t &clipbru
|| (brush.contents.is_liquid(options.target_game) &&
clipbrush.contents.is_detail_illusionary(options.target_game))
|| (brush.contents.is_fence() && clipbrush.contents.is_liquid(options.target_game))) {
|| (brush.contents.is_fence(options.target_game) && clipbrush.contents.is_liquid(options.target_game))) {
return false;
}

View File

@ -36,13 +36,14 @@ static contentflags_t RemapContentsForExport(const contentflags_t &content)
{
if (content.is_detail_fence(options.target_game)) {
/*
* A bit of a hack for Q2, to ensure that structural faces which are completely covered by CFLAGS_DETAIL_FENCE
* A bit of a hack for Q2, to ensure that structural faces which are completely covered by detail fence
* still render.
*
* If we export the detail fence leaf as CONTENTS_SOLID, Q2 engines will refuse to render the covered sturctural
* face because of a short-circuit in GL_DrawLeaf.
*/
if (options.target_game->id == GAME_QUAKE_II) {
// fixme-brushbsp: can remove this once we use WINDOW natively for detail_fence
return {Q2_CONTENTS_WINDOW, 0};
}
/*