enable lighting for warp/sky in Q2

simplify bitflag definitions
change nudging light warning to make more sense
another #define -> constexpr pass
This commit is contained in:
Jonathan 2022-06-10 06:29:14 -04:00
parent 5b4660fa63
commit 812797f7ed
21 changed files with 261 additions and 219 deletions

View File

@ -42,7 +42,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_STANDARD 99)
add_definitions(-DERICWTOOLS_VERSION=${GIT_DESCRIBE})
add_definitions(-DERICWTOOLS_VERSION="${GIT_DESCRIBE}")
if (WIN32)
set("NO_ITERATOR_DEBUG" FALSE CACHE BOOL "Whether to use MSVC iterator debugging or not")

View File

@ -89,7 +89,7 @@ settings::common_settings options;
int main(int argc, char **argv)
{
printf("---- bspinfo / ericw-tools " stringify(ERICWTOOLS_VERSION) " ----\n");
fmt::print("---- bspinfo / ericw-tools {} ----\n", ERICWTOOLS_VERSION);
if (argc == 1) {
printf("usage: bspinfo bspfile [bspfiles]\n");
exit(1);

View File

@ -464,7 +464,7 @@ int main(int argc, char **argv)
bspdata_t bspdata;
mbsp_t &bsp = bspdata.bsp.emplace<mbsp_t>();
printf("---- bsputil / ericw-tools " stringify(ERICWTOOLS_VERSION) " ----\n");
fmt::print("---- bsputil / ericw-tools {} ----\n", ERICWTOOLS_VERSION);
if (argc == 1) {
printf(
"usage: bsputil [--replace-entities] [--extract-entities] [--extract-textures] [--convert bsp29|bsp2|bsp2rmq|q2bsp] [--check] [--modelinfo]\n"

View File

@ -542,7 +542,7 @@ static const char *DefaultOriginTexture(const mbsp_t *bsp)
static const char *DefaultTextureForContents(const mbsp_t *bsp, const contentflags_t &contents)
{
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
int visible = contents.native & ((Q2_LAST_VISIBLE_CONTENTS << 1) - 1);
int visible = contents.native & Q2_ALL_VISIBLE_CONTENTS;
if (visible & Q2_CONTENTS_WATER) {
return "e1u1/water4";

View File

@ -58,15 +58,15 @@ struct gamedef_generic_t : public gamedef_t
int32_t contents_priority(const contentflags_t &) const { throw std::bad_cast(); }
contentflags_t create_extended_contents(const int32_t &) const { throw std::bad_cast(); }
contentflags_t create_extended_contents(const uint16_t &) const { throw std::bad_cast(); }
contentflags_t create_empty_contents(const int32_t &) const { throw std::bad_cast(); }
contentflags_t create_empty_contents(const uint16_t &) const { throw std::bad_cast(); }
contentflags_t create_solid_contents(const int32_t &) const { throw std::bad_cast(); }
contentflags_t create_solid_contents(const uint16_t &) const { throw std::bad_cast(); }
contentflags_t create_sky_contents(const int32_t &) const { throw std::bad_cast(); }
contentflags_t create_sky_contents(const uint16_t &) const { throw std::bad_cast(); }
contentflags_t create_liquid_contents(const int32_t &, const int32_t &) const { throw std::bad_cast(); }
contentflags_t create_liquid_contents(const int32_t &, const uint16_t &) const { throw std::bad_cast(); }
bool contents_are_empty(const contentflags_t &) const { throw std::bad_cast(); }
@ -167,30 +167,30 @@ struct gamedef_q1_like_t : public gamedef_t
}
}
contentflags_t create_extended_contents(const int32_t &cflags) const { return {0, cflags}; }
contentflags_t create_extended_contents(const uint16_t &cflags) const { return {0, cflags}; }
contentflags_t create_empty_contents(const int32_t &cflags = 0) const
contentflags_t create_empty_contents(const uint16_t &cflags = 0) const
{
Q_assert(!(cflags & CFLAGS_CONTENTS_MASK));
return {CONTENTS_EMPTY, cflags};
}
contentflags_t create_solid_contents(const int32_t &cflags = 0) const
contentflags_t create_solid_contents(const uint16_t &cflags = 0) const
{
Q_assert(!(cflags & CFLAGS_CONTENTS_MASK));
return {CONTENTS_SOLID, cflags};
}
contentflags_t create_sky_contents(const int32_t &cflags = 0) const
contentflags_t create_sky_contents(const uint16_t &cflags = 0) const
{
Q_assert(!(cflags & CFLAGS_CONTENTS_MASK));
return {CONTENTS_SKY, cflags};
}
contentflags_t create_liquid_contents(const int32_t &liquid_type, const int32_t &cflags = 0) const
contentflags_t create_liquid_contents(const int32_t &liquid_type, const uint16_t &cflags = 0) const
{
Q_assert(!(cflags & CFLAGS_CONTENTS_MASK));
@ -426,12 +426,9 @@ struct gamedef_q2_t : public gamedef_t
max_entity_key = 256;
}
bool surf_is_lightmapped(const surfflags_t &flags) const
{
return !(flags.native & (Q2_SURF_WARP | Q2_SURF_SKY | Q2_SURF_NODRAW)); // mxd. +Q2_SURF_NODRAW
}
bool surf_is_lightmapped(const surfflags_t &flags) const { return !(flags.native & Q2_SURF_NODRAW); }
bool surf_is_subdivided(const surfflags_t &flags) const { return !(flags.native & (Q2_SURF_WARP | Q2_SURF_SKY)); }
bool surf_is_subdivided(const surfflags_t &flags) const { return true; }
bool surfflags_are_valid(const surfflags_t &flags) const
{
@ -447,7 +444,7 @@ struct gamedef_q2_t : public gamedef_t
contentflags_t cluster_contents(const contentflags_t &contents0, const contentflags_t &contents1) const
{
contentflags_t c = {contents0.native | contents1.native, contents0.extended | contents1.extended};
contentflags_t c = {contents0.native | contents1.native, static_cast<uint16_t>(contents0.extended | contents1.extended)};
// a cluster may include some solid detail areas, but
// still be seen into
@ -459,7 +456,7 @@ struct gamedef_q2_t : public gamedef_t
int32_t get_content_type(const contentflags_t &contents) const
{
return contents.native & (((Q2_LAST_VISIBLE_CONTENTS << 1) - 1) |
return contents.native & (Q2_ALL_VISIBLE_CONTENTS |
(Q2_CONTENTS_PLAYERCLIP | Q2_CONTENTS_MONSTERCLIP | Q2_CONTENTS_ORIGIN |
Q2_CONTENTS_TRANSLUCENT | Q2_CONTENTS_AREAPORTAL));
}
@ -475,7 +472,7 @@ struct gamedef_q2_t : public gamedef_t
} else if (contents.extended & CFLAGS_ILLUSIONARY_VISBLOCKER) {
return 2;
} else {
switch (contents.native & ((Q2_LAST_VISIBLE_CONTENTS << 1) - 1)) {
switch (contents.native & Q2_ALL_VISIBLE_CONTENTS) {
case Q2_CONTENTS_SOLID: return 10;
case Q2_CONTENTS_WINDOW: return 9;
case Q2_CONTENTS_AUX: return 5;
@ -488,15 +485,15 @@ struct gamedef_q2_t : public gamedef_t
}
}
contentflags_t create_extended_contents(const int32_t &cflags) const { return {0, cflags}; }
contentflags_t create_extended_contents(const uint16_t &cflags) const { return {0, cflags}; }
contentflags_t create_empty_contents(const int32_t &cflags) const { return {0, cflags}; }
contentflags_t create_empty_contents(const uint16_t &cflags) const { return {0, cflags}; }
contentflags_t create_solid_contents(const int32_t &cflags) const { return {Q2_CONTENTS_SOLID, cflags}; }
contentflags_t create_solid_contents(const uint16_t &cflags) const { return {Q2_CONTENTS_SOLID, cflags}; }
contentflags_t create_sky_contents(const int32_t &cflags) const { return create_solid_contents(cflags); }
contentflags_t create_sky_contents(const uint16_t &cflags) const { return create_solid_contents(cflags); }
contentflags_t create_liquid_contents(const int32_t &liquid_type, const int32_t &cflags) const
contentflags_t create_liquid_contents(const int32_t &liquid_type, const uint16_t &cflags) const
{
switch (liquid_type) {
case CONTENTS_WATER: return {Q2_CONTENTS_WATER, cflags};
@ -515,7 +512,7 @@ struct gamedef_q2_t : public gamedef_t
return false; // HACK: needs to return false in order for LinkConvexFaces to assign Q2_CONTENTS_AREAPORTAL
// to the leaf
return !(contents.native & ((Q2_LAST_VISIBLE_CONTENTS << 1) - 1));
return !(contents.native & Q2_ALL_VISIBLE_CONTENTS);
}
bool contents_are_solid(const contentflags_t &contents) const
@ -542,7 +539,7 @@ struct gamedef_q2_t : public gamedef_t
bool contents_are_valid(const contentflags_t &contents, bool strict) const
{
// check that we don't have more than one visible contents type
const int32_t x = (contents.native & ((Q2_LAST_VISIBLE_CONTENTS << 1) - 1));
const int32_t x = contents.native & Q2_ALL_VISIBLE_CONTENTS;
if ((x & (x - 1)) != 0) {
return false;
}

View File

@ -138,8 +138,6 @@ std::vector<entdict_t> EntData_Parse(const std::string &entdata)
if (parser.token == "}")
break;
if (parser.token.length() > MAX_ENT_KEY - 1)
FError("Key length > {}: '{}'", MAX_ENT_KEY - 1, parser.token);
std::string keystr = parser.token;
@ -149,8 +147,6 @@ std::vector<entdict_t> EntData_Parse(const std::string &entdata)
if (parser.token == "}")
FError("closing brace without data");
if (parser.token.length() > MAX_ENT_VALUE - 1)
FError("Value length > {}", MAX_ENT_VALUE - 1);
entity.set(keystr, parser.token);
}

View File

@ -49,7 +49,7 @@ void init(const fs::path &filename, const settings::common_settings &settings)
{
if (settings.log.value()) {
logfile.open(filename);
fmt::print(logfile, "---- {} / ericw-tools " stringify(ERICWTOOLS_VERSION) " ----\n", settings.programName);
fmt::print(logfile, "---- {} / ericw-tools {} ----\n", settings.programName, ERICWTOOLS_VERSION);
}
}

View File

@ -167,7 +167,7 @@ std::vector<std::string> setting_container::parse(parser_base_t &parser)
void common_settings::setParameters(int argc, const char **argv)
{
programName = fs::path(argv[0]).stem().string();
fmt::print("---- {} / ericw-tools " stringify(ERICWTOOLS_VERSION) " ----\n", programName);
fmt::print("---- {} / ericw-tools {} ----\n", programName, ERICWTOOLS_VERSION);
}
void common_settings::postinitialize(int argc, const char **argv)

View File

@ -77,4 +77,11 @@ public:
inline bool operator==(const Enum &r) const { return _bits == bitflags(r)._bits; }
inline bool operator!=(const Enum &r) const { return _bits != bitflags(r)._bits; }
};
};
// fetch integral representation of the value at bit N
template<typename T>
constexpr auto nth_bit(T l)
{
return static_cast<T>(1) << l;
}

View File

@ -32,41 +32,6 @@
#include <common/aabb.hh>
#include <common/settings.hh>
/* upper design bounds */
#define MAX_MAP_HULLS_Q1 4
#define MAX_MAP_HULLS_H2 8
#define MAX_MAP_MODELS 256
#define MAX_MAP_BRUSHES 4096
#define MAX_MAP_PLANES 16384
#define MAX_MAP_NODES 32767 /* negative shorts are contents */
#define MAX_MAP_CLIPNODES 65520 /* = 0xfff0; larger are contents */
#define MAX_MAP_LEAFS 32767 /* BSP file format limitation */
#define MAX_MAP_VERTS 65535
#define MAX_MAP_FACES 65535
#define MAX_MAP_MARKSURFACES 65535
#define MAX_MAP_TEXINFO 8192
#define MAX_MAP_EDGES 256000
#define MAX_MAP_SURFEDGES 512000
#define MAX_MAP_MIPTEX 0x0800000
#define MAX_MAP_LIGHTING 0x8000000
#define MAX_MAP_VISIBILITY 0x8000000
/* key / value pair sizes */
#define MAX_ENT_KEY 32
#define MAX_ENT_VALUE 1024
#define NO_VERSION -1
#define BSPVERSION 29
#define BSP2RMQVERSION (('B' << 24) | ('S' << 16) | ('P' << 8) | '2')
#define BSP2VERSION ('B' | ('S' << 8) | ('P' << 16) | ('2' << 24))
#define BSPHLVERSION 30 // 24bit lighting, and private palettes in the textures lump.
#define Q2_BSPIDENT (('P' << 24) + ('S' << 16) + ('B' << 8) + 'I')
#define Q2_BSPVERSION 38
#define Q2_QBISMIDENT (('P' << 24) + ('S' << 16) + ('B' << 8) + 'Q')
struct lump_t
{
int32_t fileofs;
@ -75,45 +40,60 @@ struct lump_t
auto stream_data() { return std::tie(fileofs, filelen); }
};
#define LUMP_ENTITIES 0
#define LUMP_PLANES 1
#define LUMP_TEXTURES 2
#define LUMP_VERTEXES 3
#define LUMP_VISIBILITY 4
#define LUMP_NODES 5
#define LUMP_TEXINFO 6
#define LUMP_FACES 7
#define LUMP_LIGHTING 8
#define LUMP_CLIPNODES 9
#define LUMP_LEAFS 10
#define LUMP_MARKSURFACES 11
#define LUMP_EDGES 12
#define LUMP_SURFEDGES 13
#define LUMP_MODELS 14
constexpr int32_t BSPVERSION = 29;
constexpr int32_t BSP2RMQVERSION = (('B' << 24) | ('S' << 16) | ('P' << 8) | '2');
constexpr int32_t BSP2VERSION = ('B' | ('S' << 8) | ('P' << 16) | ('2' << 24));
constexpr int32_t BSPHLVERSION = 30; // 24bit lighting, and private palettes in the textures lump.
#define BSP_LUMPS 15
enum q1_lump_t
{
LUMP_ENTITIES,
LUMP_PLANES,
LUMP_TEXTURES,
LUMP_VERTEXES,
LUMP_VISIBILITY,
LUMP_NODES,
LUMP_TEXINFO,
LUMP_FACES,
LUMP_LIGHTING,
LUMP_CLIPNODES,
LUMP_LEAFS,
LUMP_MARKSURFACES,
LUMP_EDGES,
LUMP_SURFEDGES,
LUMP_MODELS,
#define Q2_LUMP_ENTITIES 0
#define Q2_LUMP_PLANES 1
#define Q2_LUMP_VERTEXES 2
#define Q2_LUMP_VISIBILITY 3
#define Q2_LUMP_NODES 4
#define Q2_LUMP_TEXINFO 5
#define Q2_LUMP_FACES 6
#define Q2_LUMP_LIGHTING 7
#define Q2_LUMP_LEAFS 8
#define Q2_LUMP_LEAFFACES 9
#define Q2_LUMP_LEAFBRUSHES 10
#define Q2_LUMP_EDGES 11
#define Q2_LUMP_SURFEDGES 12
#define Q2_LUMP_MODELS 13
#define Q2_LUMP_BRUSHES 14
#define Q2_LUMP_BRUSHSIDES 15
#define Q2_LUMP_POP 16
#define Q2_LUMP_AREAS 17
#define Q2_LUMP_AREAPORTALS 18
BSP_LUMPS
};
#define Q2_HEADER_LUMPS 19
constexpr int32_t Q2_BSPVERSION = 38;
constexpr int32_t Q2_BSPIDENT = (('P' << 24) + ('S' << 16) + ('B' << 8) + 'I');
constexpr int32_t Q2_QBISMIDENT = (('P' << 24) + ('S' << 16) + ('B' << 8) + 'Q');
enum q2_lump_t
{
Q2_LUMP_ENTITIES,
Q2_LUMP_PLANES,
Q2_LUMP_VERTEXES,
Q2_LUMP_VISIBILITY,
Q2_LUMP_NODES,
Q2_LUMP_TEXINFO,
Q2_LUMP_FACES,
Q2_LUMP_LIGHTING,
Q2_LUMP_LEAFS,
Q2_LUMP_LEAFFACES,
Q2_LUMP_LEAFBRUSHES,
Q2_LUMP_EDGES,
Q2_LUMP_SURFEDGES,
Q2_LUMP_MODELS,
Q2_LUMP_BRUSHES,
Q2_LUMP_BRUSHSIDES,
Q2_LUMP_POP,
Q2_LUMP_AREAS,
Q2_LUMP_AREAPORTALS,
Q2_HEADER_LUMPS
};
struct bspx_header_t
{
@ -164,6 +144,8 @@ inline qvec<T, 3> aabb_maxs_cast(const qvec<F, 3> &f, const char *overflow_messa
numeric_cast<T>(f[2], overflow_message)};
}
constexpr size_t MAX_MAP_HULLS_H2 = 8;
struct dmodelh2_t
{
qvec3f mins;
@ -196,6 +178,8 @@ constexpr ADest array_cast(const ASrc &src, const char *overflow_message = "src"
return dest;
}
constexpr size_t MAX_MAP_HULLS_Q1 = 4;
struct dmodelq1_t
{
qvec3f mins;
@ -518,13 +502,17 @@ struct dplane_t : qplane3f
// Q1 contents
constexpr int CONTENTS_EMPTY = -1;
constexpr int CONTENTS_SOLID = -2;
constexpr int CONTENTS_WATER = -3;
constexpr int CONTENTS_SLIME = -4;
constexpr int CONTENTS_LAVA = -5;
constexpr int CONTENTS_SKY = -6;
constexpr int CONTENTS_MIN = CONTENTS_SKY;
enum q1_contents_t : int32_t
{
CONTENTS_EMPTY = -1,
CONTENTS_SOLID = -2,
CONTENTS_WATER = -3,
CONTENTS_SLIME = -4,
CONTENTS_LAVA = -5,
CONTENTS_SKY = -6,
CONTENTS_MIN = CONTENTS_SKY
};
// Q2 contents (from qfiles.h)
@ -532,63 +520,67 @@ constexpr int CONTENTS_MIN = CONTENTS_SKY;
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf
// these definitions also need to be in q_shared.h!
// lower bits are stronger, and will eat weaker brushes completely
constexpr int Q2_CONTENTS_SOLID = 1; // an eye is never valid in a solid
constexpr int Q2_CONTENTS_WINDOW = 2; // translucent, but not watery
constexpr int Q2_CONTENTS_AUX = 4;
constexpr int Q2_CONTENTS_LAVA = 8;
constexpr int Q2_CONTENTS_SLIME = 16;
constexpr int Q2_CONTENTS_WATER = 32;
constexpr int Q2_CONTENTS_MIST = 64;
constexpr int Q2_LAST_VISIBLE_CONTENTS = 64;
enum q2_contents_t : int32_t
{
Q2_CONTENTS_SOLID = nth_bit(0), // an eye is never valid in a solid
Q2_CONTENTS_WINDOW = nth_bit(1), // translucent, but not watery
Q2_CONTENTS_AUX = nth_bit(2),
Q2_CONTENTS_LAVA = nth_bit(3),
Q2_CONTENTS_SLIME = nth_bit(4),
Q2_CONTENTS_WATER = nth_bit(5),
Q2_CONTENTS_MIST = nth_bit(6),
Q2_LAST_VISIBLE_CONTENTS = Q2_CONTENTS_MIST,
Q2_ALL_VISIBLE_CONTENTS = Q2_CONTENTS_SOLID | Q2_CONTENTS_WINDOW | Q2_CONTENTS_AUX | Q2_CONTENTS_LAVA |
Q2_CONTENTS_SLIME | Q2_CONTENTS_WATER | Q2_CONTENTS_MIST,
constexpr int Q2_CONTENTS_LIQUID = (Q2_CONTENTS_LAVA | Q2_CONTENTS_SLIME | Q2_CONTENTS_WATER); // mxd
Q2_CONTENTS_LIQUID = (Q2_CONTENTS_LAVA | Q2_CONTENTS_SLIME | Q2_CONTENTS_WATER), // mxd
// remaining contents are non-visible, and don't eat brushes
// remaining contents are non-visible, and don't eat brushes
constexpr int Q2_CONTENTS_AREAPORTAL = 0x8000;
Q2_CONTENTS_AREAPORTAL = nth_bit(15),
constexpr int Q2_CONTENTS_PLAYERCLIP = 0x10000;
constexpr int Q2_CONTENTS_MONSTERCLIP = 0x20000;
Q2_CONTENTS_PLAYERCLIP = nth_bit(16),
Q2_CONTENTS_MONSTERCLIP = nth_bit(17),
// currents can be added to any other contents, and may be mixed
constexpr int Q2_CONTENTS_CURRENT_0 = 0x40000;
constexpr int Q2_CONTENTS_CURRENT_90 = 0x80000;
constexpr int Q2_CONTENTS_CURRENT_180 = 0x100000;
constexpr int Q2_CONTENTS_CURRENT_270 = 0x200000;
constexpr int Q2_CONTENTS_CURRENT_UP = 0x400000;
constexpr int Q2_CONTENTS_CURRENT_DOWN = 0x800000;
// currents can be added to any other contents, and may be mixed
Q2_CONTENTS_CURRENT_0 = nth_bit(18),
Q2_CONTENTS_CURRENT_90 = nth_bit(19),
Q2_CONTENTS_CURRENT_180 = nth_bit(20),
Q2_CONTENTS_CURRENT_270 = nth_bit(21),
Q2_CONTENTS_CURRENT_UP = nth_bit(22),
Q2_CONTENTS_CURRENT_DOWN = nth_bit(23),
constexpr int Q2_CONTENTS_ORIGIN = 0x1000000; // removed before bsping an entity
Q2_CONTENTS_ORIGIN = nth_bit(24), // removed before bsping an entity
constexpr int Q2_CONTENTS_MONSTER = 0x2000000; // should never be on a brush, only in game
constexpr int Q2_CONTENTS_DEADMONSTER = 0x4000000;
constexpr int Q2_CONTENTS_DETAIL = 0x8000000; // brushes to be added after vis leafs
constexpr int Q2_CONTENTS_TRANSLUCENT = 0x10000000; // auto set if any surface has trans
constexpr int Q2_CONTENTS_LADDER = 0x20000000;
Q2_CONTENTS_MONSTER = nth_bit(25), // should never be on a brush, only in game
Q2_CONTENTS_DEADMONSTER = nth_bit(26),
Q2_CONTENTS_DETAIL = nth_bit(27), // brushes to be added after vis leafs
Q2_CONTENTS_TRANSLUCENT = nth_bit(28), // auto set if any surface has trans
Q2_CONTENTS_LADDER = nth_bit(29)
};
// Special contents flags for the compiler only
constexpr int CFLAGS_STRUCTURAL_COVERED_BY_DETAIL = (1 << 0);
constexpr int CFLAGS_WAS_ILLUSIONARY = (1 << 1); /* was illusionary, got changed to something else */
constexpr int CFLAGS_BMODEL_MIRROR_INSIDE =
(1 << 3); /* set "_mirrorinside" "1" on a bmodel to mirror faces for when the player is inside. */
constexpr int CFLAGS_NO_CLIPPING_SAME_TYPE =
(1 << 4); /* Don't clip the same content type. mostly intended for CONTENTS_DETAIL_ILLUSIONARY */
// only one of these flags below should ever be set.
constexpr int CFLAGS_HINT = (1 << 5);
constexpr int CFLAGS_CLIP = (1 << 6);
constexpr int CFLAGS_ORIGIN = (1 << 7);
constexpr int CFLAGS_DETAIL = (1 << 8);
constexpr int CFLAGS_DETAIL_ILLUSIONARY = (1 << 9);
constexpr int CFLAGS_DETAIL_FENCE = (1 << 10);
constexpr int CFLAGS_ILLUSIONARY_VISBLOCKER = (1 << 11);
// all of the detail values
constexpr int CFLAGS_DETAIL_MASK = (CFLAGS_DETAIL | CFLAGS_DETAIL_ILLUSIONARY | CFLAGS_DETAIL_FENCE);
// all of the special content types
constexpr int CFLAGS_CONTENTS_MASK =
(CFLAGS_HINT | CFLAGS_CLIP | CFLAGS_ORIGIN | CFLAGS_DETAIL_MASK | CFLAGS_ILLUSIONARY_VISBLOCKER);
enum extended_cflags_t : uint16_t
{
CFLAGS_STRUCTURAL_COVERED_BY_DETAIL = nth_bit(0u),
CFLAGS_WAS_ILLUSIONARY = nth_bit(1), /* was illusionary, got changed to something else */
CFLAGS_BMODEL_MIRROR_INSIDE = nth_bit(3), /* set "_mirrorinside" "1" on a bmodel to mirror faces for when the player is inside. */
CFLAGS_NO_CLIPPING_SAME_TYPE = nth_bit(4), /* Don't clip the same content type. mostly intended for CONTENTS_DETAIL_ILLUSIONARY */
// only one of these flags below should ever be set.
CFLAGS_HINT = nth_bit(5),
CFLAGS_CLIP = nth_bit(6),
CFLAGS_ORIGIN = nth_bit(7),
CFLAGS_DETAIL = nth_bit(8),
CFLAGS_DETAIL_ILLUSIONARY = nth_bit(9),
CFLAGS_DETAIL_FENCE = nth_bit(10),
CFLAGS_ILLUSIONARY_VISBLOCKER = nth_bit(11),
// all of the detail values
CFLAGS_DETAIL_MASK = (CFLAGS_DETAIL | CFLAGS_DETAIL_ILLUSIONARY | CFLAGS_DETAIL_FENCE),
// all of the special content types
CFLAGS_CONTENTS_MASK =
(CFLAGS_HINT | CFLAGS_CLIP | CFLAGS_ORIGIN | CFLAGS_DETAIL_MASK | CFLAGS_ILLUSIONARY_VISBLOCKER)
};
struct gamedef_t;
@ -598,7 +590,7 @@ struct contentflags_t
int32_t native;
// extra flags, specific to BSP only
int32_t extended;
uint16_t extended;
// for CFLAGS_STRUCTURAL_COVERED_BY_DETAIL
int32_t covered_native;
@ -816,24 +808,30 @@ private:
};
// Q1 Texture flags.
#define TEX_SPECIAL 1 /* sky or slime, no lightmap or 256 subdivision */
enum q1_surf_flags_t : int32_t
{
TEX_SPECIAL = nth_bit(0) /* sky or slime, no lightmap or 256 subdivision */
};
// Q2 Texture flags.
#define Q2_SURF_LIGHT 0x1 // value will hold the light strength
enum q2_surf_flags_t : int32_t
{
Q2_SURF_LIGHT = nth_bit(0), // value will hold the light strength
#define Q2_SURF_SLICK 0x2 // effects game physics
Q2_SURF_SLICK = nth_bit(1), // effects game physics
#define Q2_SURF_SKY 0x4 // don't draw, but add to skybox
#define Q2_SURF_WARP 0x8 // turbulent water warp
#define Q2_SURF_TRANS33 0x10
#define Q2_SURF_TRANS66 0x20
#define Q2_SURF_FLOWING 0x40 // scroll towards angle
#define Q2_SURF_NODRAW 0x80 // don't bother referencing the texture
Q2_SURF_SKY = nth_bit(2), // don't draw, but add to skybox
Q2_SURF_WARP = nth_bit(3), // turbulent water warp
Q2_SURF_TRANS33 = nth_bit(4),
Q2_SURF_TRANS66 = nth_bit(5),
Q2_SURF_FLOWING = nth_bit(6), // scroll towards angle
Q2_SURF_NODRAW = nth_bit(7), // don't bother referencing the texture
#define Q2_SURF_HINT 0x100 // make a primary bsp splitter
#define Q2_SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes
Q2_SURF_HINT = nth_bit(8), // make a primary bsp splitter
Q2_SURF_SKIP = nth_bit(9), // ONLY FOR HINT! "nodraw" = Q1 "skip"
#define Q2_SURF_TRANSLUCENT (Q2_SURF_TRANS33 | Q2_SURF_TRANS66) // mxd
Q2_SURF_TRANSLUCENT = (Q2_SURF_TRANS33 | Q2_SURF_TRANS66), // mxd
};
struct surfflags_t
{
@ -1160,11 +1158,15 @@ struct q2_dface_qbism_t
* all other leafs need visibility info
*/
/* Ambient Sounds */
#define AMBIENT_WATER 0
#define AMBIENT_SKY 1
#define AMBIENT_SLIME 2
#define AMBIENT_LAVA 3
constexpr size_t NUM_AMBIENTS = 4;
enum ambient_type_t : uint8_t
{
AMBIENT_WATER,
AMBIENT_SKY,
AMBIENT_SLIME,
AMBIENT_LAVA,
NUM_AMBIENTS = 4
};
struct mleaf_t
{
@ -1790,11 +1792,11 @@ struct gamedef_t
virtual contentflags_t cluster_contents(const contentflags_t &contents0, const contentflags_t &contents1) const = 0;
virtual int32_t get_content_type(const contentflags_t &contents) const = 0;
virtual int32_t contents_priority(const contentflags_t &contents) const = 0;
virtual contentflags_t create_extended_contents(const int32_t &cflags = 0) const = 0;
virtual contentflags_t create_empty_contents(const int32_t &cflags = 0) const = 0;
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_extended_contents(const uint16_t &cflags = 0) const = 0;
virtual contentflags_t create_empty_contents(const uint16_t &cflags = 0) const = 0;
virtual contentflags_t create_solid_contents(const uint16_t &cflags = 0) const = 0;
virtual contentflags_t create_sky_contents(const uint16_t &cflags = 0) const = 0;
virtual contentflags_t create_liquid_contents(const int32_t &liquid_type, const uint16_t &cflags = 0) const = 0;
virtual bool contents_are_empty(const contentflags_t &contents) const = 0;
virtual bool contents_are_solid(const contentflags_t &contents) const = 0;
virtual bool contents_are_sky(const contentflags_t &contents) const = 0;
@ -1809,6 +1811,8 @@ struct gamedef_t
virtual const std::vector<qvec3b> &get_default_palette() const = 0;
};
constexpr int32_t NO_VERSION = -1;
// BSP version struct & instances
struct bspversion_t
{

View File

@ -32,21 +32,36 @@
#include <fmt/format.h>
#include <common/log.hh>
#define stringify__(x) #x
#define stringify(x) stringify__(x)
#ifdef _WIN32
#define Q_strncasecmp _strnicmp
#define Q_strcasecmp _stricmp
#elif defined(__has_include) && __has_include(<strings.h>)
#if defined(__has_include) && __has_include(<strings.h>)
#include <strings.h>
#define Q_strncasecmp strncasecmp
#define Q_strcasecmp strcasecmp
#else
#define Q_strncasecmp strnicmp
#define Q_strcasecmp stricmp
#endif
inline int32_t Q_strncasecmp(const char *a, const char *b, size_t maxcount)
{
return
#ifdef _WIN32
_strnicmp
#elif defined(__has_include) && __has_include(<strings.h>)
strncasecmp
#else
strnicmp
#endif
(a, b, maxcount);
}
inline int32_t Q_strcasecmp(const char *a, const char *b)
{
return
#ifdef _WIN32
_stricmp
#elif defined(__has_include) && __has_include(<strings.h>)
strcasecmp
#else
stricmp
#endif
(a, b);
}
bool string_iequals(const std::string &a, const std::string &b); // mxd
struct case_insensitive_hash
@ -255,7 +270,9 @@ inline float BigFloat(float l)
/**
* assertion macro that is used in all builds (debug/release)
*/
#define Q_assert(x) logging::assert_((x), stringify(x), __FILE__, __LINE__)
#define Q_stringify__(x) #x
#define Q_stringify(x) Q_stringify__(x)
#define Q_assert(x) logging::assert_((x), Q_stringify(x), __FILE__, __LINE__)
#define Q_assert_unreachable() Q_assert(false)
@ -470,6 +487,14 @@ inline std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::stream_wr
return s;
}
template<typename T>
inline std::enable_if_t<std::is_enum_v<T>, std::ostream &> operator<=(
std::ostream &s, const T &obj)
{
s <= reinterpret_cast<const std::underlying_type_t<T> &>(obj);
return s;
}
template<size_t n>
inline std::istream &operator>=(std::istream &s, padding<n> &)
{
@ -611,6 +636,14 @@ inline std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::stream_re
return s;
}
template<typename T>
inline std::enable_if_t<std::is_enum_v<T>, std::istream &> operator>=(
std::istream &s, T &obj)
{
s >= reinterpret_cast<std::underlying_type_t<T> &>(obj);
return s;
}
template<typename Dst, typename Src>
constexpr bool numeric_cast_will_overflow(const Src &value)
{

View File

@ -43,11 +43,11 @@ namespace logging
enum class flag : uint8_t
{
NONE = 0, // none of the below (still prints though)
DEFAULT = 1 << 0, // prints everywhere
VERBOSE = 1 << 1, // prints everywhere, if enabled
PROGRESS = 1 << 2, // prints only to stdout
PERCENT = 1 << 3, // prints everywhere, if enabled
STAT = 1 << 4, // prints everywhere, if enabled
DEFAULT = nth_bit(0), // prints everywhere
VERBOSE = nth_bit(1), // prints everywhere, if enabled
PROGRESS = nth_bit(2), // prints only to stdout
PERCENT = nth_bit(3), // prints everywhere, if enabled
STAT = nth_bit(4), // prints everywhere, if enabled
ALL = 0xFF
};

View File

@ -21,7 +21,7 @@
#include <common/bspfile.hh>
#define LIT_VERSION 1
constexpr int32_t LIT_VERSION = 1;
struct litheader_t
{

View File

@ -98,7 +98,7 @@ public:
constexpr uint32_t *data() { return bits; }
constexpr const uint32_t *data() const { return bits; }
constexpr bool operator[](const size_t &index) const { return !!(bits[index >> shift] & (1UL << (index & mask))); }
constexpr bool operator[](const size_t &index) const { return !!(bits[index >> shift] & nth_bit(index & mask)); }
struct reference
{
@ -119,5 +119,5 @@ public:
}
};
constexpr reference operator[](const size_t &index) { return {bits, index >> shift, static_cast<size_t>(1) << (index & mask)}; }
constexpr reference operator[](const size_t &index) { return {bits, index >> shift, nth_bit(index & mask)}; }
};

View File

@ -687,7 +687,7 @@ void Matrix4x4_CM_Projection_Inf(std::array<vec_t, 16> &proj, vec_t fovx, vec_t
proj[2] = 0;
proj[6] = 0;
proj[10] = -1 * ((vec_t)(1 << 21) / (1 << 22));
proj[10] = -1 * 0.5;
proj[14] = -2 * neard * nudge;
proj[3] = 0;
@ -1026,7 +1026,7 @@ static qvec3d FixLightOnFace(const mbsp_t *bsp, const qvec3d &point)
}
}
logging::print("WARNING: couldn't nudge light in solid at {}\n", point);
logging::print("WARNING: couldn't nudge light out of solid at {}\n", point);
return point;
}

View File

@ -407,6 +407,11 @@ static void FindModelInfo(const mbsp_t *bsp)
Q_assert(modelinfo.size() == bsp->dmodels.size());
}
// FIXME: in theory can't we calculate the exact amount of
// storage required? we'd have to expand it by 4 to account for
// lightstyles though
static constexpr size_t MAX_MAP_LIGHTING = 0x8000000;
/*
* =============
* LightWorld
@ -455,7 +460,7 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
if (lmshift_lump != bspdata->bspx.entries.end()) {
for (int i = 0; i < bsp.dfaces.size(); i++)
faces_sup[i].lmscale = 1 << reinterpret_cast<const char *>(lmshift_lump->second.lumpdata.get())[i];
faces_sup[i].lmscale = nth_bit(reinterpret_cast<const char *>(lmshift_lump->second.lumpdata.get())[i]);
} else {
for (int i = 0; i < bsp.dfaces.size(); i++)
faces_sup[i].lmscale = modelinfo.at(0)->lightmapscale;

View File

@ -57,7 +57,7 @@ void WriteLitFile(const mbsp_t *bsp, facesup_t *facesup, const fs::path &filenam
extents[i * 2 + 0] = LittleShort(facesup[i].extent[0]);
extents[i * 2 + 1] = LittleShort(facesup[i].extent[1]);
j = 0;
while ((1u << j) < facesup[i].lmscale)
while (nth_bit(j) < facesup[i].lmscale)
j++;
shifts[i] = j;
}

View File

@ -1416,12 +1416,12 @@ static void ParseTextureDef(parser_t &parser, mapface_t &mapface, const mapbrush
for (int i = 0; i < 8; i++) {
if (!got) {
if (mapface.contents.native & (1 << i)) {
if (mapface.contents.native & nth_bit(i)) {
got = true;
continue;
}
} else {
mapface.contents.native &= ~(1 << i);
mapface.contents.native &= ~nth_bit(i);
}
}
}

View File

@ -51,7 +51,7 @@ static wedge_t *pWEdges;
//============================================================================
#define NUM_HASH 1024
constexpr size_t NUM_HASH = 1024;
static wedge_t *wedge_hash[NUM_HASH];
static qvec3d hash_min, hash_scale;

View File

@ -65,7 +65,7 @@ void CalcAmbientSounds(mbsp_t *bsp)
mleaf_t *leaf, *hit;
uint8_t *vis;
float d, maxd;
int ambient_type;
ambient_type_t ambient_type;
float dists[NUM_AMBIENTS];
float vol;
@ -85,7 +85,7 @@ void CalcAmbientSounds(mbsp_t *bsp)
}
for (j = 0; j < portalleafs_real; j++) {
if (!(vis[j >> 3] & (1 << (j & 7))))
if (!(vis[j >> 3] & nth_bit(j & 7)))
continue;
//
@ -181,7 +181,7 @@ void CalcPHS(mbsp_t *bsp)
if (!bitbyte)
continue;
for (int32_t k = 0; k < 8; k++) {
if (!(bitbyte & (1 << k)))
if (!(bitbyte & nth_bit(k)))
continue;
// OR this pvs row into the phs
int32_t index = ((j << 3) + k);
@ -196,7 +196,7 @@ void CalcPHS(mbsp_t *bsp)
}
}
for (int32_t j = 0; j < portalleafs; j++)
if (uncompressed[j >> 3] & (1 << (j & 7)))
if (uncompressed[j >> 3] & nth_bit(j & 7))
count++;
//

View File

@ -352,7 +352,7 @@ static void PortalCompleted(portal_t *completed)
*/
while (changed) {
bit = ffsl(changed) - 1;
changed &= ~(1UL << bit);
changed &= ~nth_bit(bit);
leafnum = (j << leafbits_t::shift) + bit;
UpdateMightsee(leafs + leafnum, myleaf);
}
@ -443,7 +443,7 @@ static void ClusterFlow(int clusternum, leafbits_t &buffer, mbsp_t *bsp)
outbuffer = uncompressed_q2 + clusternum * leafbytes;
for (i = 0; i < portalleafs; i++) {
if (buffer[i]) {
outbuffer[i >> 3] |= (1 << (i & 7));
outbuffer[i >> 3] |= nth_bit(i & 7);
numvis++;
}
}
@ -451,7 +451,7 @@ static void ClusterFlow(int clusternum, leafbits_t &buffer, mbsp_t *bsp)
outbuffer = uncompressed + clusternum * leafbytes_real;
for (i = 0; i < portalleafs_real; i++) {
if (buffer[bsp->dleafs[i + 1].cluster]) {
outbuffer[i >> 3] |= (1 << (i & 7));
outbuffer[i >> 3] |= nth_bit(i & 7);
numvis++;
}
}