Skip to content

Commit

Permalink
qbsp: more func_illusionary_visblocker fixes
Browse files Browse the repository at this point in the history
See #441

- fix visblocker merging with detail_illusionary, by introducing a new content type
- fix _mirrorinside 0 not working on visblocker
  • Loading branch information
ericwa committed Nov 24, 2024
1 parent 4e11e3e commit a095376
Show file tree
Hide file tree
Showing 5 changed files with 366 additions and 44 deletions.
97 changes: 86 additions & 11 deletions common/bspfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,77 @@ static std::vector<qvec3b> make_palette(std::initializer_list<uint8_t> bytes)
return result;
}

// clang-format off
/**
* Keep up to date with contents_t enum.
*/
static constexpr const char *bitflag_names[] = {"SOLID", "SKY", "DETAIL_WALL", "WINDOW", "AUX", "LAVA", "SLIME",
"WATER", "MIST", "ORIGIN", "PLAYERCLIP", "MONSTERCLIP", "AREAPORTAL", "NO_WATERJUMP", "PROJECTILECLIP",
"MIRROR_INSIDE", "MIRROR_INSIDE_SET", "SUPPRESS_CLIPPING_SAME_TYPE", "CURRENT_0", "CURRENT_90", "CURRENT_180",
"CURRENT_270", "CURRENT_UP", "CURRENT_DOWN", "TRANSLUCENT", "LADDER", "MONSTER", "DEADMONSTER",
"ILLUSIONARY_VISBLOCKER", "DETAIL", "Q2_UNUSED_7", "Q2_UNUSED_8", "Q2_UNUSED_9", "Q2_UNUSED_10", "Q2_UNUSED_11",
"Q2_UNUSED_12", "Q2_UNUSED_30", "Q2_UNUSED_31", "INVALID_BIT_38", "INVALID_BIT_39", "INVALID_BIT_40",
"INVALID_BIT_41", "INVALID_BIT_42", "INVALID_BIT_43", "INVALID_BIT_44", "INVALID_BIT_45", "INVALID_BIT_46",
"INVALID_BIT_47", "INVALID_BIT_48", "INVALID_BIT_49", "INVALID_BIT_50", "INVALID_BIT_51", "INVALID_BIT_52",
"INVALID_BIT_53", "INVALID_BIT_54", "INVALID_BIT_55", "INVALID_BIT_56", "INVALID_BIT_57", "INVALID_BIT_58",
"INVALID_BIT_59", "INVALID_BIT_60", "INVALID_BIT_61", "INVALID_BIT_62", "INVALID_BIT_63"};
static constexpr const char *bitflag_names[] = {
"SOLID", // bit 0
"SKY", // bit 1
"DETAIL_WALL", // bit 2
"WINDOW", // bit 3
"ILLUSIONARY_VISBLOCKER", // bit 4
"AUX", // bit 5
"LAVA", // bit 6
"SLIME", // bit 7
"WATER", // bit 8
"MIST", // bit 9
"ORIGIN", // bit 10
"PLAYERCLIP", // bit 11
"MONSTERCLIP", // bit 12
"AREAPORTAL", // bit 13
"NO_WATERJUMP", // bit 14
"PROJECTILECLIP", // bit 15
"MIRROR_INSIDE", // bit 16
"MIRROR_INSIDE_SET", // bit 17
"SUPPRESS_CLIPPING_SAME_TYPE", // bit 18
"CURRENT_0", // bit 19
"CURRENT_90", // bit 20
"CURRENT_180", // bit 21
"CURRENT_270", // bit 22
"CURRENT_UP", // bit 23
"CURRENT_DOWN", // bit 24
"TRANSLUCENT", // bit 25
"LADDER", // bit 26
"MONSTER", // bit 27
"DEADMONSTER", // bit 28
"DETAIL", // bit 29
"Q2_UNUSED_7", // bit 30
"Q2_UNUSED_8", // bit 31
"Q2_UNUSED_9", // bit 32
"Q2_UNUSED_10", // bit 33
"Q2_UNUSED_11", // bit 34
"Q2_UNUSED_12", // bit 35
"Q2_UNUSED_30", // bit 36
"Q2_UNUSED_31", // bit 37
"INVALID_BIT_38", // bit 38
"INVALID_BIT_39", // bit 39
"INVALID_BIT_40", // bit 40
"INVALID_BIT_41", // bit 41
"INVALID_BIT_42", // bit 42
"INVALID_BIT_43", // bit 43
"INVALID_BIT_44", // bit 44
"INVALID_BIT_45", // bit 45
"INVALID_BIT_46", // bit 46
"INVALID_BIT_47", // bit 47
"INVALID_BIT_48", // bit 48
"INVALID_BIT_49", // bit 49
"INVALID_BIT_50", // bit 50
"INVALID_BIT_51", // bit 51
"INVALID_BIT_52", // bit 52
"INVALID_BIT_53", // bit 53
"INVALID_BIT_54", // bit 54
"INVALID_BIT_55", // bit 55
"INVALID_BIT_56", // bit 56
"INVALID_BIT_57", // bit 57
"INVALID_BIT_58", // bit 58
"INVALID_BIT_59", // bit 59
"INVALID_BIT_60", // bit 60
"INVALID_BIT_61", // bit 61
"INVALID_BIT_62", // bit 62
"INVALID_BIT_63" // bit 63
};
// clang-format on

std::string get_contents_display(contents_t bits)
{
Expand Down Expand Up @@ -167,6 +225,8 @@ struct gamedef_q1_like_t : public gamedef_t
throw std::invalid_argument("EWT_VISCONTENTS_DETAIL_WALL not representable in Q1");
} else if (contents.flags & EWT_VISCONTENTS_WINDOW) {
throw std::invalid_argument("EWT_VISCONTENTS_WINDOW not representable in Q1");
} else if (contents.flags & EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER) {
throw std::invalid_argument("EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER not representable in Q1");
} else if (contents.flags & EWT_VISCONTENTS_AUX) {
throw std::invalid_argument("EWT_VISCONTENTS_AUX not representable in Q1");
} else if (contents.flags & EWT_VISCONTENTS_LAVA) {
Expand Down Expand Up @@ -381,6 +441,8 @@ struct gamedef_q1_like_t : public gamedef_t
return true;
else if (bits == EWT_VISCONTENTS_WINDOW)
return false;
else if (bits == EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER)
return true;
else if (bits == EWT_VISCONTENTS_LAVA)
return !transwater;
else if (bits == EWT_VISCONTENTS_SLIME)
Expand Down Expand Up @@ -409,6 +471,10 @@ struct gamedef_q1_like_t : public gamedef_t
// detail_illusionary in water becomes CONTENTS_WATER, etc.
return contentflags_t::make(contents.flags & ~EWT_VISCONTENTS_MIST);
}
if (contents.flags & EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER) {
// this exports as empty
return contentflags_t::make(contents.flags & ~EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER);
}

return contents;
}
Expand Down Expand Up @@ -474,7 +540,7 @@ struct gamedef_q1_like_t : public gamedef_t
return (bits_brush & EWT_CFLAG_MIRROR_INSIDE) != 0;
}

return (bits_brush & EWT_ALL_LIQUIDS) != 0;
return (bits_brush & (EWT_ALL_LIQUIDS | EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER)) != 0;
}
return true;
}
Expand Down Expand Up @@ -869,6 +935,8 @@ struct gamedef_q2_t : public gamedef_t
throw std::invalid_argument("detail wall not a contents in Q2");
if (contents.flags & EWT_VISCONTENTS_WINDOW)
result |= Q2_CONTENTS_WINDOW;
if (contents.flags & EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER)
throw std::invalid_argument("illusionary visblocker not a contents in Q2");
if (contents.flags & EWT_VISCONTENTS_AUX)
result |= Q2_CONTENTS_AUX;
if (contents.flags & EWT_VISCONTENTS_LAVA)
Expand Down Expand Up @@ -1209,6 +1277,13 @@ struct gamedef_q2_t : public gamedef_t
return contentflags_t::make(result);
}

if (contents.flags & EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER) {
contents_int_t result = contents.flags;
result &= (~EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER);
result |= EWT_VISCONTENTS_MIST;
return contentflags_t::make(result);
}

return contents;
}

Expand Down
72 changes: 40 additions & 32 deletions include/common/bspfile_common.hh
Original file line number Diff line number Diff line change
Expand Up @@ -62,39 +62,46 @@ enum contents_t : contents_int_t
EWT_VISCONTENTS_SKY = nth_bit<uint64_t>(1),
EWT_VISCONTENTS_DETAIL_WALL = nth_bit<uint64_t>(2),
EWT_VISCONTENTS_WINDOW = nth_bit<uint64_t>(3), // translucent, but not watery (detail fence)
EWT_VISCONTENTS_AUX = nth_bit<uint64_t>(4),
EWT_VISCONTENTS_LAVA = nth_bit<uint64_t>(5),
EWT_VISCONTENTS_SLIME = nth_bit<uint64_t>(6),
EWT_VISCONTENTS_WATER = nth_bit<uint64_t>(7),
EWT_VISCONTENTS_MIST = nth_bit<uint64_t>(8),
/**
* Visblocking mist, but doesn't merge with mist/aux
*/
EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER = nth_bit<uint64_t>(4),
/**
* Mist but not mirrored by default. Doesn't merge with mist. Never visblocking / always detail.
*/
EWT_VISCONTENTS_AUX = nth_bit<uint64_t>(5),
EWT_VISCONTENTS_LAVA = nth_bit<uint64_t>(6),
EWT_VISCONTENTS_SLIME = nth_bit<uint64_t>(7),
EWT_VISCONTENTS_WATER = nth_bit<uint64_t>(8),
/**
* Never visblocking / always detail.
*/
EWT_VISCONTENTS_MIST = nth_bit<uint64_t>(9),

EWT_LAST_VISIBLE_CONTENTS_INDEX = 8,
EWT_LAST_VISIBLE_CONTENTS_INDEX = 9,
EWT_LAST_VISIBLE_CONTENTS = EWT_VISCONTENTS_MIST,

EWT_INVISCONTENTS_ORIGIN = nth_bit<uint64_t>(9), // removed before bsping an entity
// Q1 clip
EWT_INVISCONTENTS_PLAYERCLIP = nth_bit<uint64_t>(10),
EWT_INVISCONTENTS_MONSTERCLIP = nth_bit<uint64_t>(11),
EWT_INVISCONTENTS_AREAPORTAL = nth_bit<uint64_t>(12),
EWT_INVISCONTENTS_NO_WATERJUMP = nth_bit<uint64_t>(13), // re-release
EWT_INVISCONTENTS_PROJECTILECLIP = nth_bit<uint64_t>(14), // re-release

EWT_CFLAG_MIRROR_INSIDE = nth_bit<uint64_t>(15),
EWT_CFLAG_MIRROR_INSIDE_SET = nth_bit<uint64_t>(16),
EWT_CFLAG_SUPPRESS_CLIPPING_SAME_TYPE = nth_bit<uint64_t>(17),

EWT_CFLAG_CURRENT_0 = nth_bit<uint64_t>(18),
EWT_CFLAG_CURRENT_90 = nth_bit<uint64_t>(19),
EWT_CFLAG_CURRENT_180 = nth_bit<uint64_t>(20),
EWT_CFLAG_CURRENT_270 = nth_bit<uint64_t>(21),
EWT_CFLAG_CURRENT_UP = nth_bit<uint64_t>(22),
EWT_CFLAG_CURRENT_DOWN = nth_bit<uint64_t>(23),
EWT_CFLAG_TRANSLUCENT = nth_bit<uint64_t>(24), // auto set if any surface has trans,
EWT_CFLAG_LADDER = nth_bit<uint64_t>(25),
EWT_CFLAG_MONSTER = nth_bit<uint64_t>(26), // disallowed in maps, only for gamecode use
EWT_CFLAG_DEADMONSTER = nth_bit<uint64_t>(27), // disallowed in maps, only for gamecode use

// 28 unused
EWT_INVISCONTENTS_ORIGIN = nth_bit<uint64_t>(10), // removed before bsping an entity
EWT_INVISCONTENTS_PLAYERCLIP = nth_bit<uint64_t>(11), // Q1 clip
EWT_INVISCONTENTS_MONSTERCLIP = nth_bit<uint64_t>(12),
EWT_INVISCONTENTS_AREAPORTAL = nth_bit<uint64_t>(13),
EWT_INVISCONTENTS_NO_WATERJUMP = nth_bit<uint64_t>(14), // re-release
EWT_INVISCONTENTS_PROJECTILECLIP = nth_bit<uint64_t>(15), // re-release

EWT_CFLAG_MIRROR_INSIDE = nth_bit<uint64_t>(16),
EWT_CFLAG_MIRROR_INSIDE_SET = nth_bit<uint64_t>(17),
EWT_CFLAG_SUPPRESS_CLIPPING_SAME_TYPE = nth_bit<uint64_t>(18),

EWT_CFLAG_CURRENT_0 = nth_bit<uint64_t>(19),
EWT_CFLAG_CURRENT_90 = nth_bit<uint64_t>(20),
EWT_CFLAG_CURRENT_180 = nth_bit<uint64_t>(21),
EWT_CFLAG_CURRENT_270 = nth_bit<uint64_t>(22),
EWT_CFLAG_CURRENT_UP = nth_bit<uint64_t>(23),
EWT_CFLAG_CURRENT_DOWN = nth_bit<uint64_t>(24),
EWT_CFLAG_TRANSLUCENT = nth_bit<uint64_t>(25), // auto set if any surface has trans,
EWT_CFLAG_LADDER = nth_bit<uint64_t>(26),
EWT_CFLAG_MONSTER = nth_bit<uint64_t>(27), // disallowed in maps, only for gamecode use
EWT_CFLAG_DEADMONSTER = nth_bit<uint64_t>(28), // disallowed in maps, only for gamecode use
EWT_CFLAG_DETAIL = nth_bit<uint64_t>(29), // brushes to be added after vis leafs

// unused Q2 contents bits - just present here so we can roundtrip all 32-bit Q2 contents
Expand All @@ -111,8 +118,9 @@ enum contents_t : contents_int_t
EWT_ALL_LIQUIDS = EWT_VISCONTENTS_LAVA | EWT_VISCONTENTS_SLIME | EWT_VISCONTENTS_WATER,

EWT_ALL_VISIBLE_CONTENTS = EWT_VISCONTENTS_SOLID | EWT_VISCONTENTS_SKY | EWT_VISCONTENTS_DETAIL_WALL |
EWT_VISCONTENTS_WINDOW | EWT_VISCONTENTS_AUX | EWT_VISCONTENTS_LAVA |
EWT_VISCONTENTS_SLIME | EWT_VISCONTENTS_WATER | EWT_VISCONTENTS_MIST,
EWT_VISCONTENTS_WINDOW | EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER | EWT_VISCONTENTS_AUX |
EWT_VISCONTENTS_LAVA | EWT_VISCONTENTS_SLIME | EWT_VISCONTENTS_WATER |
EWT_VISCONTENTS_MIST,

EWT_ALL_INVISCONTENTS = EWT_INVISCONTENTS_ORIGIN | EWT_INVISCONTENTS_PLAYERCLIP | EWT_INVISCONTENTS_MONSTERCLIP |
EWT_INVISCONTENTS_AREAPORTAL | EWT_INVISCONTENTS_PROJECTILECLIP,
Expand Down
2 changes: 1 addition & 1 deletion qbsp/map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1496,7 +1496,7 @@ static contentflags_t Brush_GetContents(const mapentity_t &entity, const mapbrus
// note this overrides the logic in face_get_contents() that normally forces mist to be detail
base_contents = contentflags_t::make(
(base_contents.flags & ~(EWT_ALL_VISIBLE_CONTENTS | EWT_CFLAG_DETAIL))
| (EWT_VISCONTENTS_MIST | EWT_CFLAG_MIRROR_INSIDE | EWT_CFLAG_MIRROR_INSIDE_SET));
| EWT_VISCONTENTS_ILLUSIONARY_VISBLOCKER);
}

// non-Q2: -transwater implies liquids are detail
Expand Down
Loading

0 comments on commit a095376

Please sign in to comment.