-includeskip for Q2RTX

Fix missing fmt include
Default nexttexinfo to -1 to match other tools
Fmt support for bspversion_t, use that instead of a static function
Cleanup write functions
This commit is contained in:
Jonathan 2021-10-09 14:14:49 -04:00
parent 1b1679fa22
commit eb4bcf96dc
9 changed files with 433 additions and 436 deletions

View File

@ -25,164 +25,6 @@
#include <fmt/format.h>
/*
* =========================================================================
* ...
* =========================================================================
*/
constexpr lumpspec_t lumpspec_bsp29[] = {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp29_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp29_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp29_dclipnode_t)},
{"leafs", sizeof(bsp29_dleaf_t)},
{"marksurfaces", sizeof(uint16_t)},
{"edges", sizeof(bsp29_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelq1_t)},
};
constexpr lumpspec_t lumpspec_bsp2rmq[] = {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp2rmq_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp2_dclipnode_t)},
{"leafs", sizeof(bsp2rmq_dleaf_t)},
{"marksurfaces", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelq1_t)},
};
constexpr lumpspec_t lumpspec_bsp2[] = {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp2_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp2_dclipnode_t)},
{"leafs", sizeof(bsp2_dleaf_t)},
{"marksurfaces", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelq1_t)},
};
constexpr lumpspec_t lumpspec_bsp29_h2[] = {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp29_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp29_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp29_dclipnode_t)},
{"leafs", sizeof(bsp29_dleaf_t)},
{"marksurfaces", sizeof(uint16_t)},
{"edges", sizeof(bsp29_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelh2_t)},
};
constexpr lumpspec_t lumpspec_bsp2rmq_h2[] = {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp2rmq_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp2_dclipnode_t)},
{"leafs", sizeof(bsp2rmq_dleaf_t)},
{"marksurfaces", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelh2_t)},
};
constexpr lumpspec_t lumpspec_bsp2_h2[] = {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp2_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp2_dclipnode_t)},
{"leafs", sizeof(bsp2_dleaf_t)},
{"marksurfaces", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelh2_t)},
};
constexpr lumpspec_t lumpspec_q2bsp[] = {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(q2_dnode_t)},
{"texinfos", sizeof(q2_texinfo_t)},
{"faces", sizeof(q2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"leafs", sizeof(q2_dleaf_t)},
{"leaffaces", sizeof(uint16_t)},
{"leafbrushes", sizeof(uint16_t)},
{"edges", sizeof(bsp29_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(q2_dmodel_t)},
{"brushes", sizeof(dbrush_t)},
{"brushsides", sizeof(q2_dbrushside_t)},
{"pop", sizeof(uint8_t)},
{"areas", sizeof(darea_t)},
{"areaportals", sizeof(dareaportal_t)},
};
constexpr lumpspec_t lumpspec_qbism[] = {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(q2_dnode_qbism_t)},
{"texinfos", sizeof(q2_texinfo_t)},
{"faces", sizeof(q2_dface_qbism_t)},
{"lighting", sizeof(uint8_t)},
{"leafs", sizeof(q2_dleaf_qbism_t)},
{"leaffaces", sizeof(uint32_t)},
{"leafbrushes", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(q2_dmodel_t)},
{"brushes", sizeof(dbrush_t)},
{"brushsides", sizeof(q2_dbrushside_qbism_t)},
{"pop", sizeof(uint8_t)},
{"areas", sizeof(darea_t)},
{"areaportals", sizeof(dareaportal_t)},
};
struct gamedef_generic_t : public gamedef_t
{
gamedef_generic_t() : gamedef_t("") { id = GAME_UNKNOWN; }
@ -576,27 +418,165 @@ struct gamedef_q2_t : public gamedef_t
}
};
// Game definitions, used for the bsp versions below
static const gamedef_generic_t gamedef_generic;
const bspversion_t bspver_generic{NO_VERSION, NO_VERSION, "mbsp", "generic BSP", nullptr, &gamedef_generic};
static const gamedef_q1_like_t<GAME_QUAKE> gamedef_q1;
const bspversion_t bspver_q1{BSPVERSION, NO_VERSION, "bsp29", "Quake BSP", lumpspec_bsp29, &gamedef_q1, &bspver_bsp2};
const bspversion_t bspver_bsp2{BSP2VERSION, NO_VERSION, "bsp2", "Quake BSP2", lumpspec_bsp2, &gamedef_q1};
const bspversion_t bspver_bsp2rmq{
BSP2RMQVERSION, NO_VERSION, "bsp2rmq", "Quake BSP2-RMQ", lumpspec_bsp2rmq, &gamedef_q1};
/* Hexen II doesn't use a separate version, but we can still use a separate tag/name for it */
static const gamedef_h2_t gamedef_h2;
const bspversion_t bspver_h2{
BSPVERSION, NO_VERSION, "hexen2", "Hexen II BSP", lumpspec_bsp29_h2, &gamedef_h2, &bspver_h2bsp2};
const bspversion_t bspver_h2bsp2{BSP2VERSION, NO_VERSION, "hexen2bsp2", "Hexen II BSP2", lumpspec_bsp2_h2, &gamedef_h2};
const bspversion_t bspver_h2bsp2rmq{
BSP2RMQVERSION, NO_VERSION, "hexen2bsp2rmq", "Hexen II BSP2-RMQ", lumpspec_bsp2rmq_h2, &gamedef_h2};
static const gamedef_hl_t gamedef_hl;
const bspversion_t bspver_hl{BSPHLVERSION, NO_VERSION, "hl", "Half-Life BSP", lumpspec_bsp29, &gamedef_hl};
static const gamedef_q2_t gamedef_q2;
const bspversion_t bspver_generic{NO_VERSION, NO_VERSION, "mbsp", "generic BSP", {}, &gamedef_generic};
const bspversion_t bspver_q1{BSPVERSION, NO_VERSION, "bsp29", "Quake BSP", {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp29_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp29_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp29_dclipnode_t)},
{"leafs", sizeof(bsp29_dleaf_t)},
{"marksurfaces", sizeof(uint16_t)},
{"edges", sizeof(bsp29_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelq1_t)},
}, &gamedef_q1, &bspver_bsp2};
const bspversion_t bspver_bsp2{BSP2VERSION, NO_VERSION, "bsp2", "Quake BSP2", {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp2_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp2_dclipnode_t)},
{"leafs", sizeof(bsp2_dleaf_t)},
{"marksurfaces", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelq1_t)},
}, &gamedef_q1};
const bspversion_t bspver_bsp2rmq{
BSP2RMQVERSION, NO_VERSION, "bsp2rmq", "Quake BSP2-RMQ", {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp2rmq_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp2_dclipnode_t)},
{"leafs", sizeof(bsp2rmq_dleaf_t)},
{"marksurfaces", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelq1_t)},
}, &gamedef_q1};
/* Hexen II doesn't use a separate version, but we can still use a separate tag/name for it */
const bspversion_t bspver_h2{
BSPVERSION, NO_VERSION, "hexen2", "Hexen II BSP", {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp29_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp29_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp29_dclipnode_t)},
{"leafs", sizeof(bsp29_dleaf_t)},
{"marksurfaces", sizeof(uint16_t)},
{"edges", sizeof(bsp29_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelh2_t)},
}, &gamedef_h2, &bspver_h2bsp2};
const bspversion_t bspver_h2bsp2{BSP2VERSION, NO_VERSION, "hexen2bsp2", "Hexen II BSP2", {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp2_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp2_dclipnode_t)},
{"leafs", sizeof(bsp2_dleaf_t)},
{"marksurfaces", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelh2_t)},
}, &gamedef_h2};
const bspversion_t bspver_h2bsp2rmq{
BSP2RMQVERSION, NO_VERSION, "hexen2bsp2rmq", "Hexen II BSP2-RMQ", {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"texture", sizeof(uint8_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(bsp2rmq_dnode_t)},
{"texinfos", sizeof(texinfo_t)},
{"faces", sizeof(bsp2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"clipnodes", sizeof(bsp2_dclipnode_t)},
{"leafs", sizeof(bsp2rmq_dleaf_t)},
{"marksurfaces", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(dmodelh2_t)},
}, &gamedef_h2};
const bspversion_t bspver_hl{BSPHLVERSION, NO_VERSION, "hl", "Half-Life BSP", bspver_q1.lumps, &gamedef_hl};
const bspversion_t bspver_q2{
Q2_BSPIDENT, Q2_BSPVERSION, "q2bsp", "Quake II BSP", lumpspec_q2bsp, &gamedef_q2, &bspver_qbism};
Q2_BSPIDENT, Q2_BSPVERSION, "q2bsp", "Quake II BSP", {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(q2_dnode_t)},
{"texinfos", sizeof(q2_texinfo_t)},
{"faces", sizeof(q2_dface_t)},
{"lighting", sizeof(uint8_t)},
{"leafs", sizeof(q2_dleaf_t)},
{"leaffaces", sizeof(uint16_t)},
{"leafbrushes", sizeof(uint16_t)},
{"edges", sizeof(bsp29_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(q2_dmodel_t)},
{"brushes", sizeof(dbrush_t)},
{"brushsides", sizeof(q2_dbrushside_t)},
{"pop", sizeof(uint8_t)},
{"areas", sizeof(darea_t)},
{"areaportals", sizeof(dareaportal_t)},
}, &gamedef_q2, &bspver_qbism};
const bspversion_t bspver_qbism{
Q2_QBISMIDENT, Q2_BSPVERSION, "qbism", "Quake II Qbism BSP", lumpspec_qbism, &gamedef_q2};
Q2_QBISMIDENT, Q2_BSPVERSION, "qbism", "Quake II Qbism BSP", {
{"entities", sizeof(char)},
{"planes", sizeof(dplane_t)},
{"vertexes", sizeof(qvec3f)},
{"visibility", sizeof(uint8_t)},
{"nodes", sizeof(q2_dnode_qbism_t)},
{"texinfos", sizeof(q2_texinfo_t)},
{"faces", sizeof(q2_dface_qbism_t)},
{"lighting", sizeof(uint8_t)},
{"leafs", sizeof(q2_dleaf_qbism_t)},
{"leaffaces", sizeof(uint32_t)},
{"leafbrushes", sizeof(uint32_t)},
{"edges", sizeof(bsp2_dedge_t)},
{"surfedges", sizeof(int32_t)},
{"models", sizeof(q2_dmodel_t)},
{"brushes", sizeof(dbrush_t)},
{"brushsides", sizeof(q2_dbrushside_qbism_t)},
{"pop", sizeof(uint8_t)},
{"areas", sizeof(darea_t)},
{"areaportals", sizeof(dareaportal_t)},
}, &gamedef_q2};
bool contentflags_t::types_equal(const contentflags_t &other, const gamedef_t *game) const
{
@ -640,23 +620,6 @@ std::string contentflags_t::to_string(const gamedef_t *game) const
return s;
}
static const char *BSPVersionString(const bspversion_t *version)
{
if (version->name) {
return version->name;
}
static char buffers[2][20];
static int index;
char *buffer = buffers[1 & ++index];
if (version->version != NO_VERSION) {
snprintf(buffer, sizeof(buffers[0]), "%d:%d", version->version, version->ident);
} else {
snprintf(buffer, sizeof(buffers[0]), "%d", version->version);
}
return buffer;
}
static bool BSPVersionSupported(int32_t ident, int32_t version, const bspversion_t **out_version)
{
for (const bspversion_t *bspver : bspversions) {
@ -928,7 +891,8 @@ struct lump_reader
template<typename T>
void read(size_t lump_num, std::vector<T> &buffer)
{
const lumpspec_t &lumpspec = version->lumps[lump_num];
Q_assert(version->lumps.size() > lump_num);
const lumpspec_t &lumpspec = version->lumps.begin()[lump_num];
const lump_t &lump = lumps[lump_num];
size_t length;
@ -963,7 +927,8 @@ struct lump_reader
// read string from stream
void read(size_t lump_num, std::string &buffer)
{
const lumpspec_t &lumpspec = version->lumps[lump_num];
Q_assert(version->lumps.size() > lump_num);
const lumpspec_t &lumpspec = version->lumps.begin()[lump_num];
const lump_t &lump = lumps[lump_num];
Q_assert(lumpspec.size == 1);
@ -988,7 +953,8 @@ struct lump_reader
template<typename T, typename = std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::stream_read)>>>
void read(size_t lump_num, T &buffer)
{
const lumpspec_t &lumpspec = version->lumps[lump_num];
Q_assert(version->lumps.size() > lump_num);
const lumpspec_t &lumpspec = version->lumps.begin()[lump_num];
const lump_t &lump = lumps[lump_num];
if (!lump.filelen)
@ -1098,7 +1064,7 @@ void LoadBSPFile(std::filesystem::path &filename, bspdata_t *bspdata)
/* check the file version */
if (!BSPVersionSupported(temp_version.ident, temp_version.version, &bspdata->version)) {
LogPrint("BSP is version {}\n", BSPVersionString(&temp_version));
LogPrint("BSP is version {}\n", temp_version);
Error("Sorry, this bsp version is not supported.");
} else {
// special case handling for Hexen II
@ -1112,7 +1078,7 @@ void LoadBSPFile(std::filesystem::path &filename, bspdata_t *bspdata)
}
}
LogPrint("BSP is version {}\n", BSPVersionString(bspdata->version));
LogPrint("BSP is version {}\n", *bspdata->version);
}
lump_reader reader{stream, bspdata->version, lumps};
@ -1183,30 +1149,31 @@ struct bspfile_t
};
std::ofstream stream;
};
// write structured lump data from vector
template<typename T>
static void WriteLump(bspfile_t &bspfile, size_t lump_num, const std::vector<T> &data)
{
private:
// write structured lump data from vector
template<typename T>
inline void write_lump(size_t lump_num, const std::vector<T> &data)
{
static constexpr char pad[4]{};
const lumpspec_t &lumpspec = bspfile.version->lumps[lump_num];
Q_assert(version->lumps.size() > lump_num);
const lumpspec_t &lumpspec = version->lumps.begin()[lump_num];
lump_t *lumps;
if (bspfile.version->version != NO_VERSION) {
lumps = bspfile.q2header.lumps.data();
if (version->version != NO_VERSION) {
lumps = q2header.lumps.data();
} else {
lumps = bspfile.q1header.lumps.data();
lumps = q1header.lumps.data();
}
lump_t &lump = lumps[lump_num];
lump.fileofs = bspfile.stream.tellp();
lump.fileofs = stream.tellp();
for (auto &v : data)
bspfile.stream <= v;
stream <= v;
auto written = static_cast<int32_t>(bspfile.stream.tellp()) - lump.fileofs;
auto written = static_cast<int32_t>(stream.tellp()) - lump.fileofs;
if (sizeof(T) == 1 || lumpspec.size > 1)
Q_assert(written == (lumpspec.size * data.size()));
@ -1214,161 +1181,163 @@ static void WriteLump(bspfile_t &bspfile, size_t lump_num, const std::vector<T>
lump.filelen = written;
if (written % 4)
bspfile.stream.write(pad, 4 - (written % 4));
}
stream.write(pad, 4 - (written % 4));
}
// write structured string data
static void WriteLump(bspfile_t &bspfile, size_t lump_num, const std::string &data)
{
// this is only here to satisfy std::visit
constexpr void write_lump(size_t, const std::monostate &) { }
// write structured string data
inline void write_lump(size_t lump_num, const std::string &data)
{
Q_assert(version->lumps.size() > lump_num);
static constexpr char pad[4]{};
const lumpspec_t &lumpspec = bspfile.version->lumps[lump_num];
const lumpspec_t &lumpspec = version->lumps.begin()[lump_num];
lump_t *lumps;
Q_assert(lumpspec.size == 1);
if (bspfile.version->version != NO_VERSION) {
lumps = bspfile.q2header.lumps.data();
if (version->version != NO_VERSION) {
lumps = q2header.lumps.data();
} else {
lumps = bspfile.q1header.lumps.data();
lumps = q1header.lumps.data();
}
lump_t &lump = lumps[lump_num];
lump.fileofs = bspfile.stream.tellp();
lump.fileofs = stream.tellp();
bspfile.stream.write(data.c_str(), data.size() + 1); // null terminator
stream.write(data.c_str(), data.size() + 1); // null terminator
auto written = static_cast<int32_t>(bspfile.stream.tellp()) - lump.fileofs;
auto written = static_cast<int32_t>(stream.tellp()) - lump.fileofs;
Q_assert(written == data.size() + 1);
lump.filelen = written;
if (written % 4)
bspfile.stream.write(pad, 4 - (written % 4));
}
stream.write(pad, 4 - (written % 4));
}
// write structured lump data
template<typename T, typename = std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::stream_write)>>>
static void WriteLump(bspfile_t &bspfile, size_t lump_num, const T &data)
{
// write structured lump data
template<typename T, typename = std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::stream_write)>>>
inline void write_lump(size_t lump_num, const T &data)
{
static constexpr char pad[4]{};
const lumpspec_t &lumpspec = bspfile.version->lumps[lump_num];
const lumpspec_t &lumpspec = version->lumps.begin()[lump_num];
lump_t *lumps;
Q_assert(lumpspec.size == 1);
if (bspfile.version->version != NO_VERSION) {
lumps = bspfile.q2header.lumps.data();
if (version->version != NO_VERSION) {
lumps = q2header.lumps.data();
} else {
lumps = bspfile.q1header.lumps.data();
lumps = q1header.lumps.data();
}
lump_t &lump = lumps[lump_num];
lump.fileofs = bspfile.stream.tellp();
lump.fileofs = stream.tellp();
data.stream_write(bspfile.stream);
data.stream_write(stream);
auto written = static_cast<int32_t>(bspfile.stream.tellp()) - lump.fileofs;
auto written = static_cast<int32_t>(stream.tellp()) - lump.fileofs;
lump.filelen = written;
if (written % 4)
bspfile.stream.write(pad, 4 - (written % 4));
}
template<typename T>
inline void WriteQ1BSP(bspfile_t &bspfile, const T &bsp)
{
WriteLump(bspfile, LUMP_PLANES, bsp.dplanes);
WriteLump(bspfile, LUMP_LEAFS, bsp.dleafs);
WriteLump(bspfile, LUMP_VERTEXES, bsp.dvertexes);
WriteLump(bspfile, LUMP_NODES, bsp.dnodes);
WriteLump(bspfile, LUMP_TEXINFO, bsp.texinfo);
WriteLump(bspfile, LUMP_FACES, bsp.dfaces);
WriteLump(bspfile, LUMP_CLIPNODES, bsp.dclipnodes);
WriteLump(bspfile, LUMP_MARKSURFACES, bsp.dmarksurfaces);
WriteLump(bspfile, LUMP_SURFEDGES, bsp.dsurfedges);
WriteLump(bspfile, LUMP_EDGES, bsp.dedges);
if (std::holds_alternative<dmodelh2_vector>(bsp.dmodels)) {
WriteLump(bspfile, LUMP_MODELS, std::get<dmodelh2_vector>(bsp.dmodels));
} else {
WriteLump(bspfile, LUMP_MODELS, std::get<dmodelq1_vector>(bsp.dmodels));
stream.write(pad, 4 - (written % 4));
}
WriteLump(bspfile, LUMP_LIGHTING, bsp.dlightdata);
WriteLump(bspfile, LUMP_VISIBILITY, bsp.dvisdata);
WriteLump(bspfile, LUMP_ENTITIES, bsp.dentdata);
if (std::holds_alternative<miptexhl_lump>(bsp.dtex)) {
WriteLump(bspfile, LUMP_TEXTURES, std::get<miptexhl_lump>(bsp.dtex));
} else {
WriteLump(bspfile, LUMP_TEXTURES, std::get<miptexq1_lump>(bsp.dtex));
public:
inline void write_bsp(const mbsp_t &) { FError("Can't write generic BSP"); }
inline void write_bsp(const std::monostate &) { FError("No BSP to write"); }
template<typename T, typename std::enable_if_t<std::is_base_of_v<q1bsp_tag_t, T>, int> = 0>
inline void write_bsp(const T &bsp)
{
write_lump(LUMP_PLANES, bsp.dplanes);
write_lump(LUMP_LEAFS, bsp.dleafs);
write_lump(LUMP_VERTEXES, bsp.dvertexes);
write_lump(LUMP_NODES, bsp.dnodes);
write_lump(LUMP_TEXINFO, bsp.texinfo);
write_lump(LUMP_FACES, bsp.dfaces);
write_lump(LUMP_CLIPNODES, bsp.dclipnodes);
write_lump(LUMP_MARKSURFACES, bsp.dmarksurfaces);
write_lump(LUMP_SURFEDGES, bsp.dsurfedges);
write_lump(LUMP_EDGES, bsp.dedges);
std::visit([this](auto&& arg) { write_lump(LUMP_MODELS, arg); }, bsp.dmodels);
write_lump(LUMP_LIGHTING, bsp.dlightdata);
write_lump(LUMP_VISIBILITY, bsp.dvisdata);
write_lump(LUMP_ENTITIES, bsp.dentdata);
std::visit([this](auto&& arg) { write_lump(LUMP_TEXTURES, arg); }, bsp.dtex);
}
}
template<typename T>
inline void WriteQ2BSP(bspfile_t &bspfile, const T &bsp)
{
WriteLump(bspfile, Q2_LUMP_PLANES, bsp.dplanes);
WriteLump(bspfile, Q2_LUMP_LEAFS, bsp.dleafs);
WriteLump(bspfile, Q2_LUMP_VERTEXES, bsp.dvertexes);
WriteLump(bspfile, Q2_LUMP_NODES, bsp.dnodes);
WriteLump(bspfile, Q2_LUMP_TEXINFO, bsp.texinfo);
WriteLump(bspfile, Q2_LUMP_FACES, bsp.dfaces);
WriteLump(bspfile, Q2_LUMP_LEAFFACES, bsp.dleaffaces);
WriteLump(bspfile, Q2_LUMP_SURFEDGES, bsp.dsurfedges);
WriteLump(bspfile, Q2_LUMP_EDGES, bsp.dedges);
WriteLump(bspfile, Q2_LUMP_MODELS, bsp.dmodels);
WriteLump(bspfile, Q2_LUMP_LEAFBRUSHES, bsp.dleafbrushes);
WriteLump(bspfile, Q2_LUMP_BRUSHES, bsp.dbrushes);
WriteLump(bspfile, Q2_LUMP_BRUSHSIDES, bsp.dbrushsides);
WriteLump(bspfile, Q2_LUMP_AREAS, bsp.dareas);
WriteLump(bspfile, Q2_LUMP_AREAPORTALS, bsp.dareaportals);
template<typename T, typename std::enable_if_t<std::is_base_of_v<q2bsp_tag_t, T>, int> = 0>
inline void write_bsp(const T &bsp)
{
write_lump(Q2_LUMP_PLANES, bsp.dplanes);
write_lump(Q2_LUMP_LEAFS, bsp.dleafs);
write_lump(Q2_LUMP_VERTEXES, bsp.dvertexes);
write_lump(Q2_LUMP_NODES, bsp.dnodes);
write_lump(Q2_LUMP_TEXINFO, bsp.texinfo);
write_lump(Q2_LUMP_FACES, bsp.dfaces);
write_lump(Q2_LUMP_LEAFFACES, bsp.dleaffaces);
write_lump(Q2_LUMP_SURFEDGES, bsp.dsurfedges);
write_lump(Q2_LUMP_EDGES, bsp.dedges);
write_lump(Q2_LUMP_MODELS, bsp.dmodels);
write_lump(Q2_LUMP_LEAFBRUSHES, bsp.dleafbrushes);
write_lump(Q2_LUMP_BRUSHES, bsp.dbrushes);
write_lump(Q2_LUMP_BRUSHSIDES, bsp.dbrushsides);
write_lump(Q2_LUMP_AREAS, bsp.dareas);
write_lump(Q2_LUMP_AREAPORTALS, bsp.dareaportals);
WriteLump(bspfile, Q2_LUMP_LIGHTING, bsp.dlightdata);
WriteLump(bspfile, Q2_LUMP_VISIBILITY, bsp.dvis);
WriteLump(bspfile, Q2_LUMP_ENTITIES, bsp.dentdata);
}
write_lump(Q2_LUMP_LIGHTING, bsp.dlightdata);
write_lump(Q2_LUMP_VISIBILITY, bsp.dvis);
write_lump(Q2_LUMP_ENTITIES, bsp.dentdata);
}
inline void WriteBSPXLumps(bspdata_t *bspdata, bspfile_t &bspfile)
{
if (!bspdata->bspx.entries.size())
inline void write_bspx(const bspdata_t &bspdata)
{
if (!bspdata.bspx.entries.size())
return;
if (bspfile.stream.tellp() & 3)
if (stream.tellp() & 3)
FError("BSPX header is misaligned");
bspfile.stream <= bspx_header_t(bspdata->bspx.entries.size());
stream <= bspx_header_t(bspdata.bspx.entries.size());
auto bspxheader = bspfile.stream.tellp();
auto bspxheader = stream.tellp();
// write dummy lump headers
for (auto &x : bspdata->bspx.entries) {
bspfile.stream <= bspx_lump_t{};
for (auto &x : bspdata.bspx.entries) {
stream <= bspx_lump_t{};
}
std::vector<bspx_lump_t> xlumps;
xlumps.reserve(bspdata->bspx.entries.size());
xlumps.reserve(bspdata.bspx.entries.size());
for (auto &x : bspdata->bspx.entries) {
for (auto &x : bspdata.bspx.entries) {
static constexpr char pad[4]{};
bspx_lump_t &lump = xlumps.emplace_back();
lump.filelen = x.second.lumpsize;
lump.fileofs = bspfile.stream.tellp();
lump.fileofs = stream.tellp();
memcpy(lump.lumpname.data(), x.first.c_str(), std::min(x.first.size(), lump.lumpname.size() - 1));
bspfile.stream.write(reinterpret_cast<const char *>(x.second.lumpdata.get()), x.second.lumpsize);
stream.write(reinterpret_cast<const char *>(x.second.lumpdata.get()), x.second.lumpsize);
if (x.second.lumpsize % 4)
bspfile.stream.write(pad, 4 - (x.second.lumpsize % 4));
stream.write(pad, 4 - (x.second.lumpsize % 4));
}
bspfile.stream.seekp(bspxheader);
stream.seekp(bspxheader);
for (auto &lump : xlumps)
bspfile.stream <= lump;
}
stream <= lump;
}
};
/*
* =============
@ -1389,7 +1358,7 @@ void WriteBSPFile(const std::filesystem::path &filename, bspdata_t *bspdata)
bspfile.q2header.version = bspfile.version->version;
}
LogPrint("Writing {} as BSP version {}\n", filename, BSPVersionString(bspdata->version));
LogPrint("Writing {} as BSP version {}\n", filename, *bspdata->version);
bspfile.stream.open(filename, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
if (!bspfile.stream)
@ -1404,22 +1373,10 @@ void WriteBSPFile(const std::filesystem::path &filename, bspdata_t *bspdata)
bspfile.stream <= bspfile.q1header;
}
if (std::holds_alternative<bsp29_t>(bspdata->bsp)) {
WriteQ1BSP(bspfile, std::get<bsp29_t>(bspdata->bsp));
} else if (std::holds_alternative<bsp2rmq_t>(bspdata->bsp)) {
WriteQ1BSP(bspfile, std::get<bsp2rmq_t>(bspdata->bsp));
} else if (std::holds_alternative<bsp2_t>(bspdata->bsp)) {
WriteQ1BSP(bspfile, std::get<bsp2_t>(bspdata->bsp));
} else if (std::holds_alternative<q2bsp_t>(bspdata->bsp)) {
WriteQ2BSP(bspfile, std::get<q2bsp_t>(bspdata->bsp));
} else if (std::holds_alternative<q2bsp_qbism_t>(bspdata->bsp)) {
WriteQ2BSP(bspfile, std::get<q2bsp_qbism_t>(bspdata->bsp));
} else {
FError("Unknown format");
}
std::visit([&bspfile](auto&& arg) { bspfile.write_bsp(arg); }, bspdata->bsp);
/*BSPX lumps are at a 4-byte alignment after the last of any official lump*/
WriteBSPXLumps(bspdata, bspfile);
bspfile.write_bspx(*bspdata);
bspfile.stream.seekp(0);
@ -1433,30 +1390,29 @@ void WriteBSPFile(const std::filesystem::path &filename, bspdata_t *bspdata)
/* ========================================================================= */
static void PrintLumpSize(const lumpspec_t *lumpspec, int lumptype, int count)
inline void PrintLumpSize(const lumpspec_t &lump, size_t count)
{
const lumpspec_t *lump = &lumpspec[lumptype];
LogPrint("{:7} {:<12} {:10}\n", count, lump->name, count * lump->size);
LogPrint("{:7} {:<12} {:10}\n", count, lump.name, count * lump.size);
}
template<typename T>
inline void PrintQ1BSPLumps(const lumpspec_t *lumpspec, const T &bsp)
inline void PrintQ1BSPLumps(const std::initializer_list<lumpspec_t> &lumpspec, const T &bsp)
{
if (std::holds_alternative<dmodelh2_vector>(bsp.dmodels))
LogPrint("{:7} {:<12}\n", std::get<dmodelh2_vector>(bsp.dmodels).size(), "models");
else
LogPrint("{:7} {:<12}\n", std::get<dmodelq1_vector>(bsp.dmodels).size(), "models");
PrintLumpSize(lumpspec, LUMP_PLANES, bsp.dplanes.size());
PrintLumpSize(lumpspec, LUMP_VERTEXES, bsp.dvertexes.size());
PrintLumpSize(lumpspec, LUMP_NODES, bsp.dnodes.size());
PrintLumpSize(lumpspec, LUMP_TEXINFO, bsp.texinfo.size());
PrintLumpSize(lumpspec, LUMP_FACES, bsp.dfaces.size());
PrintLumpSize(lumpspec, LUMP_CLIPNODES, bsp.dclipnodes.size());
PrintLumpSize(lumpspec, LUMP_LEAFS, bsp.dleafs.size());
PrintLumpSize(lumpspec, LUMP_MARKSURFACES, bsp.dmarksurfaces.size());
PrintLumpSize(lumpspec, LUMP_EDGES, bsp.dedges.size());
PrintLumpSize(lumpspec, LUMP_SURFEDGES, bsp.dsurfedges.size());
PrintLumpSize(lumpspec.begin()[LUMP_PLANES], bsp.dplanes.size());
PrintLumpSize(lumpspec.begin()[LUMP_VERTEXES], bsp.dvertexes.size());
PrintLumpSize(lumpspec.begin()[LUMP_NODES], bsp.dnodes.size());
PrintLumpSize(lumpspec.begin()[LUMP_TEXINFO], bsp.texinfo.size());
PrintLumpSize(lumpspec.begin()[LUMP_FACES], bsp.dfaces.size());
PrintLumpSize(lumpspec.begin()[LUMP_CLIPNODES], bsp.dclipnodes.size());
PrintLumpSize(lumpspec.begin()[LUMP_LEAFS], bsp.dleafs.size());
PrintLumpSize(lumpspec.begin()[LUMP_MARKSURFACES], bsp.dmarksurfaces.size());
PrintLumpSize(lumpspec.begin()[LUMP_EDGES], bsp.dedges.size());
PrintLumpSize(lumpspec.begin()[LUMP_SURFEDGES], bsp.dsurfedges.size());
if (std::holds_alternative<miptexhl_lump>(bsp.dtex))
LogPrint("{:7} {:<12} {:10}\n", "", "textures", std::get<miptexhl_lump>(bsp.dtex).textures.size());
@ -1468,24 +1424,24 @@ inline void PrintQ1BSPLumps(const lumpspec_t *lumpspec, const T &bsp)
}
template<typename T>
inline void PrintQ2BSPLumps(const lumpspec_t *lumpspec, const T &bsp)
inline void PrintQ2BSPLumps(const std::initializer_list<lumpspec_t> &lumpspec, const T &bsp)
{
LogPrint("{:7} {:<12}\n", bsp.dmodels.size(), "models");
PrintLumpSize(lumpspec, Q2_LUMP_PLANES, bsp.dplanes.size());
PrintLumpSize(lumpspec, Q2_LUMP_VERTEXES, bsp.dvertexes.size());
PrintLumpSize(lumpspec, Q2_LUMP_NODES, bsp.dnodes.size());
PrintLumpSize(lumpspec, Q2_LUMP_TEXINFO, bsp.texinfo.size());
PrintLumpSize(lumpspec, Q2_LUMP_FACES, bsp.dfaces.size());
PrintLumpSize(lumpspec, Q2_LUMP_LEAFS, bsp.dleafs.size());
PrintLumpSize(lumpspec, Q2_LUMP_LEAFFACES, bsp.dleaffaces.size());
PrintLumpSize(lumpspec, Q2_LUMP_LEAFBRUSHES, bsp.dleafbrushes.size());
PrintLumpSize(lumpspec, Q2_LUMP_EDGES, bsp.dedges.size());
PrintLumpSize(lumpspec, Q2_LUMP_SURFEDGES, bsp.dsurfedges.size());
PrintLumpSize(lumpspec, Q2_LUMP_BRUSHES, bsp.dbrushes.size());
PrintLumpSize(lumpspec, Q2_LUMP_BRUSHSIDES, bsp.dbrushsides.size());
PrintLumpSize(lumpspec, Q2_LUMP_AREAS, bsp.dareas.size());
PrintLumpSize(lumpspec, Q2_LUMP_AREAPORTALS, bsp.dareaportals.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_PLANES], bsp.dplanes.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_VERTEXES], bsp.dvertexes.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_NODES], bsp.dnodes.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_TEXINFO], bsp.texinfo.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_FACES], bsp.dfaces.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_LEAFS], bsp.dleafs.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_LEAFFACES], bsp.dleaffaces.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_LEAFBRUSHES], bsp.dleafbrushes.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_EDGES], bsp.dedges.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_SURFEDGES], bsp.dsurfedges.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_BRUSHES], bsp.dbrushes.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_BRUSHSIDES], bsp.dbrushsides.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_AREAS], bsp.dareas.size());
PrintLumpSize(lumpspec.begin()[Q2_LUMP_AREAPORTALS], bsp.dareaportals.size());
LogPrint("{:7} {:<12} {:10}\n", "", "lightdata", bsp.dlightdata.size());
LogPrint("{:7} {:<12} {:10}\n", "", "visdata", bsp.dvis.bits.size());
@ -1500,7 +1456,7 @@ inline void PrintQ2BSPLumps(const lumpspec_t *lumpspec, const T &bsp)
*/
void PrintBSPFileSizes(const bspdata_t *bspdata)
{
const lumpspec_t *lumpspec = bspdata->version->lumps;
const auto &lumpspec = bspdata->version->lumps;
if (std::holds_alternative<q2bsp_t>(bspdata->bsp)) {
PrintQ2BSPLumps(lumpspec, std::get<q2bsp_t>(bspdata->bsp));
@ -1513,7 +1469,7 @@ void PrintBSPFileSizes(const bspdata_t *bspdata)
} else if (std::holds_alternative<bsp2_t>(bspdata->bsp)) {
PrintQ1BSPLumps(lumpspec, std::get<bsp2_t>(bspdata->bsp));
} else {
Error("Unsupported BSP version: {}", BSPVersionString(bspdata->version));
Error("Unsupported BSP version: {}", *bspdata->version);
}
for (auto &x : bspdata->bspx.entries) {

View File

@ -829,7 +829,7 @@ struct gtexinfo_t
// q2 only
int32_t value; // light emission, etc
std::array<char, 32> texture; // texture name (textures/*.wal)
int32_t nexttexinfo; // for animations, -1 = end of chain
int32_t nexttexinfo = -1; // for animations, -1 = end of chain
};
struct texinfo_t
@ -1398,7 +1398,10 @@ using dmodelh2_vector = std::vector<dmodelh2_t>;
using miptexq1_lump = dmiptexlump_t<miptex_t>;
using miptexhl_lump = dmiptexlump_t<miptexhl_t>;
struct bsp29_t
// type tag used for type inference
struct q1bsp_tag_t { };
struct bsp29_t : q1bsp_tag_t
{
std::variant<std::monostate, dmodelq1_vector, dmodelh2_vector> dmodels;
std::vector<uint8_t> dvisdata;
@ -1417,7 +1420,7 @@ struct bsp29_t
std::vector<int32_t> dsurfedges;
};
struct bsp2rmq_t
struct bsp2rmq_t : q1bsp_tag_t
{
std::variant<std::monostate, dmodelq1_vector, dmodelh2_vector> dmodels;
std::vector<uint8_t> dvisdata;
@ -1436,7 +1439,7 @@ struct bsp2rmq_t
std::vector<int32_t> dsurfedges;
};
struct bsp2_t
struct bsp2_t : q1bsp_tag_t
{
std::variant<std::monostate, dmodelq1_vector, dmodelh2_vector> dmodels;
std::vector<uint8_t> dvisdata;
@ -1455,7 +1458,10 @@ struct bsp2_t
std::vector<int32_t> dsurfedges;
};
struct q2bsp_t
// type tag used for type inference
struct q2bsp_tag_t { };
struct q2bsp_t : q2bsp_tag_t
{
std::vector<q2_dmodel_t> dmodels;
@ -1479,7 +1485,7 @@ struct q2bsp_t
std::vector<q2_dbrushside_t> dbrushsides;
};
struct q2bsp_qbism_t
struct q2bsp_qbism_t : q2bsp_tag_t
{
std::vector<q2_dmodel_t> dmodels;
mvis_t dvis;
@ -1657,13 +1663,37 @@ struct bspversion_t
/* full display name for printing */
const char *name;
/* lump specification */
const lumpspec_t *lumps;
const std::initializer_list<lumpspec_t> lumps;
/* game ptr */
const gamedef_t *game;
/* if we surpass the limits of this format, upgrade to this one */
const bspversion_t *extended_limits;
};
// FMT support
template<>
struct fmt::formatter<bspversion_t>
{
constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin())
{
return ctx.end();
}
template<typename FormatContext>
auto format(const bspversion_t &v, FormatContext &ctx) -> decltype(ctx.out())
{
if (v.name) {
return format_to(ctx.out(), "{}", v.name);
}
if (v.version != NO_VERSION) {
return format_to(ctx.out(), "{}:{}", v.version, v.ident);
}
return format_to(ctx.out(), "{}", v.version, v.ident);
}
};
extern const bspversion_t bspver_generic;
extern const bspversion_t bspver_q1;
extern const bspversion_t bspver_h2;

View File

@ -607,9 +607,6 @@ namespace qv
[[nodiscard]] qmat2x2f inverse(const qmat2x2f &input);
}; // namespace qv
// FMT support
#include <fmt/format.h>
template<size_t N, class T>
struct fmt::formatter<qvec<N, T>> : formatter<T>
{

View File

@ -295,6 +295,7 @@ public:
bool fContentHack;
vec_t worldExtent;
bool fNoThreads;
bool includeSkip;
options_t()
: fNofill(false), fNoclip(false), fNoskip(false), fNodetail(false), fOnlyents(false), fConvertMapFormat(false),

View File

@ -96,6 +96,8 @@ Detail brushes are omitted from the compile.
Convert a .MAP to a different .MAP format. fmt can be: quake, quake2, valve, bp (brush primitives).
Conversions to "quake" or "quake2" format may not be able to match the texture alignment in the source map, other conversions are lossless.
The converted map is saved to <source map name>-<fmt>.map.
.IP "\fB-includeskip\fP"
Emit skip/nodraw faces. Mainly for Q2RTX.
.SH "SPECIAL TEXTURE NAMES"
.PP

View File

@ -171,6 +171,7 @@ static void ExportObj_Marksurfaces_r(const node_t *node, std::unordered_set<cons
for (face_t **markface = node->markfaces; *markface; markface++) {
face_t *face = *markface;
if (map.mtexinfos.at(face->texinfo).flags.extended & TEX_EXFLAG_SKIP)
continue;

View File

@ -162,7 +162,7 @@ static std::vector<std::tuple<size_t, face_t *>> AddBrushBevels(const brush_t *b
int32_t planenum = FindPlane(&new_plane.normal[0], new_plane.dist, nullptr);
int32_t outputplanenum = ExportMapPlane(planenum);
planes.emplace_back(outputplanenum, nullptr);
planes.emplace_back(outputplanenum, b->faces);
}
// if the plane is not in it canonical order, swap it
@ -250,7 +250,7 @@ static std::vector<std::tuple<size_t, face_t *>> AddBrushBevels(const brush_t *b
// add this plane
int32_t planenum = FindPlane(&current.normal[0], current.dist, nullptr);
int32_t outputplanenum = ExportMapPlane(planenum);
planes.emplace_back(outputplanenum, nullptr);
planes.emplace_back(outputplanenum, b->faces);
}
}
}
@ -273,7 +273,7 @@ static void ExportBrushList(const mapentity_t *entity, node_t *node, uint32_t &b
for (auto &plane : bevels) {
map.bsp.dbrushsides.push_back(
{(uint32_t)std::get<0>(plane), (int32_t)ExportMapTexinfo(b->faces->texinfo)});
{(uint32_t)std::get<0>(plane), (int32_t)ExportMapTexinfo(std::get<1>(plane)->texinfo)});
brush.numsides++;
brush_state.total_brush_sides++;
}
@ -1153,6 +1153,7 @@ PrintOptions
" -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"
" -includeskip Include skip/nodraw faces."
" -expand Write hull 1 expanded brushes to expanded.map for debugging\n"
" -leaktest Make compilation fail if the map leaks\n"
" -contenthack Hack to fix leaks through solids. Causes missing faces in some cases so disabled by default.\n"
@ -1378,6 +1379,8 @@ static void ParseOptions(char *szOptions)
options.fConvertMapFormat = true;
szTok = szTok2;
} else if (!Q_strcasecmp(szTok, "includeskip")) {
options.includeSkip = true;
} else if (!Q_strcasecmp(szTok, "forceprt1")) {
options.fForcePRT1 = true;
LogPrint("WARNING: Forcing creation of PRT1.\n");

View File

@ -303,7 +303,9 @@ FindFaceEdges
*/
static void FindFaceEdges(mapentity_t *entity, face_t *face)
{
if (map.mtexinfos.at(face->texinfo).flags.extended & (TEX_EXFLAG_SKIP | TEX_EXFLAG_HINT))
if (!options.includeSkip && (map.mtexinfos.at(face->texinfo).flags.extended & TEX_EXFLAG_SKIP))
return;
if (map.mtexinfos.at(face->texinfo).flags.extended & TEX_EXFLAG_HINT)
return;
face->outputnumber = std::nullopt;
@ -349,7 +351,9 @@ static void EmitFace(mapentity_t *entity, face_t *face)
{
int i;
if (map.mtexinfos.at(face->texinfo).flags.extended & (TEX_EXFLAG_SKIP | TEX_EXFLAG_HINT))
if (!options.includeSkip && (map.mtexinfos.at(face->texinfo).flags.extended & TEX_EXFLAG_SKIP))
return;
if (map.mtexinfos.at(face->texinfo).flags.extended & TEX_EXFLAG_HINT)
return;
// emit a region
@ -404,7 +408,9 @@ static void GrowNodeRegion(mapentity_t *entity, node_t *node)
static void CountFace(mapentity_t *entity, face_t *f, size_t &facesCount, size_t &vertexesCount)
{
if (map.mtexinfos.at(f->texinfo).flags.extended & (TEX_EXFLAG_SKIP | TEX_EXFLAG_HINT))
if (!options.includeSkip && (map.mtexinfos.at(f->texinfo).flags.extended & TEX_EXFLAG_SKIP))
return;
if (map.mtexinfos.at(f->texinfo).flags.extended & TEX_EXFLAG_HINT)
return;
if (f->lmshift[1] != 4)

View File

@ -186,7 +186,8 @@ static void ExportLeaf(mapentity_t *entity, node_t *node)
for (face_t **markfaces = node->markfaces; *markfaces; markfaces++) {
face_t *face = *markfaces;
if (map.mtexinfos.at(face->texinfo).flags.extended & TEX_EXFLAG_SKIP)
if (!options.includeSkip && (map.mtexinfos.at(face->texinfo).flags.extended & TEX_EXFLAG_SKIP))
continue;
/* emit a marksurface */