Fix operator<

Introduce gamedef, to reduce rewriting of data in bspversions
fix name of needs_subdivision
include value in texinfo, in prep for Q2
This commit is contained in:
Jonathan 2021-09-07 01:41:32 -04:00
parent acc65953ce
commit 00efa6e67d
18 changed files with 181 additions and 126 deletions

View File

@ -22,34 +22,88 @@
#include <common/bspfile.hh>
#include <cstdint>
bool q1_surf_is_lightmapped(const surfflags_t &flags) {
struct gamedef_generic_t : public gamedef_t {
gamedef_generic_t()
{
id = GAME_UNKNOWN;
base_dir = nullptr;
}
bool surf_is_lightmapped(const surfflags_t &flags) const {
throw std::bad_cast();
}
bool surf_is_subdivided(const surfflags_t &flags) const {
throw std::bad_cast();
}
};
template<gameid_t id>
struct gamedef_q1_like_t : public gamedef_t {
gamedef_q1_like_t()
{
this->id = id;
has_rgb_lightmap = false;
base_dir = "ID1";
}
bool surf_is_lightmapped(const surfflags_t &flags) const {
return !(flags.native & TEX_SPECIAL);
}
}
bool q2_surf_is_lightmapped(const surfflags_t &flags) {
bool surf_is_subdivided(const surfflags_t &flags) const {
return !(flags.native & TEX_SPECIAL);
}
};
struct gamedef_h2_t : public gamedef_q1_like_t<GAME_HEXEN_II> {
gamedef_h2_t()
{
base_dir = "DATA1";
}
};
struct gamedef_hl_t : public gamedef_q1_like_t<GAME_HALF_LIFE> {
gamedef_hl_t()
{
has_rgb_lightmap = true;
base_dir = "VALVE";
}
};
struct gamedef_q2_t : public gamedef_t {
gamedef_q2_t()
{
this->id = GAME_QUAKE_II;
has_rgb_lightmap = true;
base_dir = "BASEQ2";
}
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 q1_surf_needs_subdivision(const surfflags_t &flags) {
return flags.native & TEX_SPECIAL;
}
bool surf_is_subdivided(const surfflags_t &flags) const {
return !(flags.native & (Q2_SURF_WARP | Q2_SURF_SKY));
}
};
bool q2_surf_needs_subdivision(const surfflags_t &flags) {
return flags.native & (Q2_SURF_WARP | Q2_SURF_SKY);
}
/* game, colored lightmap, surf_is_lightmapped surf_needs_subdivision */
const bspversion_t bspver_generic { NO_VERSION, NO_VERSION, "mbsp", "generic BSP", GAME_UNKNOWN };
const bspversion_t bspver_q1 { BSPVERSION, NO_VERSION, "bsp29", "Quake BSP", GAME_QUAKE, false, q1_surf_is_lightmapped, q1_surf_needs_subdivision };
const bspversion_t bspver_bsp2 { BSP2VERSION, NO_VERSION, "bsp2", "Quake BSP2", GAME_QUAKE, false, q1_surf_is_lightmapped, q1_surf_needs_subdivision };
const bspversion_t bspver_bsp2rmq { BSP2RMQVERSION, NO_VERSION, "bsp2rmq", "Quake BSP2-RMQ", GAME_QUAKE, false, q1_surf_is_lightmapped, q1_surf_needs_subdivision };
static const gamedef_generic_t gamedef_generic;
const bspversion_t bspver_generic { NO_VERSION, NO_VERSION, "mbsp", "generic BSP", &gamedef_generic };
static const gamedef_q1_like_t<GAME_QUAKE> gamedef_q1;
const bspversion_t bspver_q1 { BSPVERSION, NO_VERSION, "bsp29", "Quake BSP", &gamedef_q1 };
const bspversion_t bspver_bsp2 { BSP2VERSION, NO_VERSION, "bsp2", "Quake BSP2", &gamedef_q1 };
const bspversion_t bspver_bsp2rmq { BSP2RMQVERSION, NO_VERSION, "bsp2rmq", "Quake BSP2-RMQ", &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", GAME_HEXEN_II, false, q1_surf_is_lightmapped, q1_surf_needs_subdivision };
const bspversion_t bspver_h2bsp2 { BSP2VERSION, NO_VERSION, "hexen2bsp2", "Hexen II BSP2", GAME_HEXEN_II, false, q1_surf_is_lightmapped, q1_surf_needs_subdivision };
const bspversion_t bspver_h2bsp2rmq { BSP2RMQVERSION, NO_VERSION, "hexen2bsp2rmq", "Hexen II BSP2-RMQ", GAME_HEXEN_II, false, q1_surf_is_lightmapped, q1_surf_needs_subdivision };
const bspversion_t bspver_hl { BSPHLVERSION, NO_VERSION, "hl", "Half-Life BSP", GAME_HALF_LIFE, true, q1_surf_is_lightmapped, q1_surf_needs_subdivision };
const bspversion_t bspver_q2 { Q2_BSPIDENT, Q2_BSPVERSION, "q2bsp", "Quake II BSP", GAME_QUAKE_II, true, q2_surf_is_lightmapped, q2_surf_needs_subdivision };
const bspversion_t bspver_qbism { Q2_QBISMIDENT, Q2_BSPVERSION, "qbism", "Quake II Qbism BSP", GAME_QUAKE_II, true, q2_surf_is_lightmapped, q2_surf_needs_subdivision };
static const gamedef_h2_t gamedef_h2;
const bspversion_t bspver_h2 { BSPVERSION, NO_VERSION, "hexen2", "Hexen II BSP", &gamedef_h2 };
const bspversion_t bspver_h2bsp2 { BSP2VERSION, NO_VERSION, "hexen2bsp2", "Hexen II BSP2", &gamedef_h2 };
const bspversion_t bspver_h2bsp2rmq { BSP2RMQVERSION, NO_VERSION, "hexen2bsp2rmq", "Hexen II BSP2-RMQ", &gamedef_h2 };
static const gamedef_hl_t gamedef_hl;
const bspversion_t bspver_hl { BSPHLVERSION, NO_VERSION, "hl", "Half-Life BSP", &gamedef_hl };
static const gamedef_q2_t gamedef_q2;
const bspversion_t bspver_q2 { Q2_BSPIDENT, Q2_BSPVERSION, "q2bsp", "Quake II BSP", &gamedef_q2 };
const bspversion_t bspver_qbism { Q2_QBISMIDENT, Q2_BSPVERSION, "qbism", "Quake II Qbism BSP", &gamedef_q2 };
static const char *
BSPVersionString(const bspversion_t *version)

View File

@ -189,7 +189,7 @@ bool Face_IsLightmapped(const mbsp_t *bsp, const bsp2_dface_t *face)
if (texinfo == nullptr)
return false;
return bsp->loadversion->surf_is_lightmapped(texinfo->flags);
return bsp->loadversion->game->surf_is_lightmapped(texinfo->flags);
}
const float *GetSurfaceVertexPoint(const mbsp_t *bsp, const bsp2_dface_t *f, int v)
@ -215,7 +215,7 @@ TextureName_Contents(const char *texname)
bool //mxd
ContentsOrSurfaceFlags_IsTranslucent(const mbsp_t *bsp, const int contents_or_surf_flags)
{
if (bsp->loadversion->game == GAME_QUAKE_II)
if (bsp->loadversion->game->id == GAME_QUAKE_II)
return (contents_or_surf_flags & Q2_SURF_TRANSLUCENT) && ((contents_or_surf_flags & Q2_SURF_TRANSLUCENT) != Q2_SURF_TRANSLUCENT); // Don't count KMQ2 fence flags combo as translucent
else
return contents_or_surf_flags == CONTENTS_WATER || contents_or_surf_flags == CONTENTS_LAVA || contents_or_surf_flags == CONTENTS_SLIME;
@ -230,7 +230,7 @@ Face_IsTranslucent(const mbsp_t *bsp, const bsp2_dface_t *face)
int //mxd. Returns CONTENTS_ value for Q1, Q2_SURF_ bitflags for Q2...
Face_ContentsOrSurfaceFlags(const mbsp_t *bsp, const bsp2_dface_t *face)
{
if (bsp->loadversion->game == GAME_QUAKE_II) {
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
const gtexinfo_t *info = Face_Texinfo(bsp, face);
return info->flags.native;
} else {
@ -275,7 +275,7 @@ static bool Light_PointInSolid_r(const mbsp_t *bsp, const int nodenum, const vec
const mleaf_t *leaf = BSP_GetLeafFromNodeNum(bsp, nodenum);
//mxd
if (bsp->loadversion->game == GAME_QUAKE_II) {
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
return leaf->contents & Q2_CONTENTS_SOLID;
}

View File

@ -21,6 +21,7 @@
#define __COMMON_BSPFILE_H__
#include <stdint.h>
#include <array>
#include <common/cmdlib.hh>
#include <common/log.hh>
@ -373,7 +374,7 @@ struct surfflags_t {
uint8_t minlight;
// red minlight colors for this face
uint8_t minlight_color[3];
std::array<uint8_t, 3> minlight_color;
// if non zero, overrides _phong_angle for concave joints
uint8_t phong_angle_concave;
@ -980,13 +981,29 @@ typedef struct {
bspxentry_t *bspxentries;
} bspdata_t;
// native game ID target
enum bspgame_t {
// native game target ID
enum gameid_t {
GAME_UNKNOWN,
GAME_QUAKE,
GAME_HEXEN_II,
GAME_HALF_LIFE,
GAME_QUAKE_II
GAME_QUAKE_II,
GAME_TOTAL
};
// Game definition, which contains data specific to
// the game a BSP version is being compiled for.
struct gamedef_t
{
gameid_t id;
bool has_rgb_lightmap;
const char *base_dir;
virtual bool surf_is_lightmapped(const surfflags_t &flags) const = 0;
virtual bool surf_is_subdivided(const surfflags_t &flags) const = 0;
};
// BSP version struct & instances
@ -1000,13 +1017,8 @@ struct bspversion_t
const char *short_name;
/* full display name for printing */
const char *name;
/* game ID */
bspgame_t game;
/* whether the game natively has a colored lightmap or not */
/* TODO: move to a game-specific table */
bool rgb_lightmap;
bool (*surf_is_lightmapped)(const surfflags_t &flags);
bool (*surf_needs_subdivision)(const surfflags_t &flags);
/* game ptr */
const gamedef_t *game;
};
extern const bspversion_t bspver_generic;

View File

@ -206,8 +206,7 @@ struct extended_tx_info_t {
};
int FindMiptex(const char *name);
int FindTexinfo(mtexinfo_t *texinfo, surfflags_t flags); //FIXME: Make this take const texinfo
int FindTexinfoEnt(mtexinfo_t *texinfo, mapentity_t *entity); //FIXME: Make this take const texinfo
int FindTexinfo(const mtexinfo_t &texinfo, surfflags_t flags);
void PrintEntity(const mapentity_t *entity);
const char *ValueForKey(const mapentity_t *entity, const char *key);

View File

@ -26,6 +26,7 @@
#include <vector>
#include <map>
#include <unordered_map>
#include <array>
#include <assert.h>
#include <ctype.h>
@ -141,14 +142,17 @@ enum {
#include <common/mathlib.hh>
#include <qbsp/winding.hh>
using stvecs = std::array<std::array<float, 4>, 2>;
typedef struct mtexinfo_s {
float vecs[2][4]; /* [s/t][xyz offset] */
int32_t miptex;
surfflags_t flags;
int outputnum; // -1 until added to bsp
stvecs vecs; /* [s/t][xyz offset] */
int32_t miptex = 0;
surfflags_t flags = {};
int32_t value = 0; // Q2-specific
int outputnum = -1; // -1 until added to bsp
constexpr auto as_tuple() const {
return std::tie(vecs, miptex, flags);
return std::tie(vecs, miptex, flags, value);
}
constexpr bool operator<(const mtexinfo_s &other) const {

View File

@ -1579,7 +1579,7 @@ static void MakeSurfaceLights(const mbsp_t *bsp)
for (int i = 0; i < bsp->numleafs; i++) {
const mleaf_t *leaf = bsp->dleafs + i;
const qboolean underwater = ((bsp->loadversion->game == GAME_QUAKE_II) ? (leaf->contents & Q2_CONTENTS_LIQUID) : leaf->contents != CONTENTS_EMPTY); //mxd
const qboolean underwater = ((bsp->loadversion->game->id == GAME_QUAKE_II) ? (leaf->contents & Q2_CONTENTS_LIQUID) : leaf->contents != CONTENTS_EMPTY); //mxd
for (int k = 0; k < leaf->nummarksurfaces; k++) {
const int facenum = bsp->dleaffaces[leaf->firstmarksurface + k];

View File

@ -44,7 +44,7 @@ void // WHO TOUCHED MY PALET?
LoadPalette(bspdata_t *bspdata)
{
// Load Quake 2 palette
if (bspdata->loadversion->game == GAME_QUAKE_II) {
if (bspdata->loadversion->game->id == GAME_QUAKE_II) {
uint8_t *palette;
char path[1024];
char colormap[] = "pics/colormap.pcx";
@ -66,7 +66,7 @@ LoadPalette(bspdata_t *bspdata)
for (int i = 0; i < 768; i++)
thepalette[i] = palette[i];
} else if (bspdata->loadversion->game == GAME_HEXEN_II) {
} else if (bspdata->loadversion->game->id == GAME_HEXEN_II) {
// Copy Hexen 2 palette
for (int i = 0; i < 768; i++)
thepalette[i] = hexen2palette[i];
@ -721,7 +721,7 @@ void // Expects correct palette and game/mod paths to be set
LoadOrConvertTextures(mbsp_t *bsp)
{
// Load or convert textures...
if (bsp->loadversion->game == GAME_QUAKE_II)
if (bsp->loadversion->game->id == GAME_QUAKE_II)
LoadTextures(bsp);
else if (bsp->texdatasize > 0)
ConvertTextures(bsp);

View File

@ -439,7 +439,7 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
CalculateVertexNormals(bsp);
const qboolean bouncerequired = cfg_static.bounce.boolValue() && (debugmode == debugmode_none || debugmode == debugmode_bounce || debugmode == debugmode_bouncelights); //mxd
const qboolean isQuake2map = bsp->loadversion->game == GAME_QUAKE_II; //mxd
const qboolean isQuake2map = bsp->loadversion->game->id == GAME_QUAKE_II; //mxd
if (bouncerequired || isQuake2map) {
MakeTextureColors(bsp);
@ -470,7 +470,7 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
// Transfer greyscale lightmap (or color lightmap for Q2/HL) to the bsp and update lightdatasize
if (!litonly) {
free(bsp->dlightdata);
if (bsp->loadversion->rgb_lightmap) {
if (bsp->loadversion->game->has_rgb_lightmap) {
bsp->lightdatasize = lit_file_p;
bsp->dlightdata = (uint8_t *)malloc(bsp->lightdatasize);
memcpy(bsp->dlightdata, lit_filebase, bsp->lightdatasize);
@ -537,11 +537,7 @@ LoadExtendedTexinfoFlags(const char *sourcefilename, const mbsp_t *bsp)
static const char* //mxd
GetBaseDirName(bspdata_t *bspdata)
{
if (bspdata->loadversion->game == GAME_QUAKE_II)
return "BASEQ2";
if (bspdata->loadversion->game == GAME_HEXEN_II)
return "DATA1";
return "ID1";
return bspdata->loadversion->game->base_dir;
}
//obj
@ -1194,7 +1190,7 @@ light_main(int argc, const char **argv)
ConvertBSPFormat(&bspdata, &bspver_generic);
//mxd. Use 1.0 rangescale as a default to better match with qrad3/arghrad
if ((loadversion->game == GAME_QUAKE_II) && !cfg.rangescale.isChanged())
if ((loadversion->game->id == GAME_QUAKE_II) && !cfg.rangescale.isChanged())
{
const auto rs = new lockable_vec_t(cfg.rangescale.primaryName(), 1.0f, 0.0f, 100.0f);
cfg.rangescale = *rs; // Gross hacks to avoid displaying this in OptionsSummary...
@ -1234,7 +1230,7 @@ light_main(int argc, const char **argv)
if (!onlyents)
{
if (!loadversion->rgb_lightmap) {
if (!loadversion->game->has_rgb_lightmap) {
CheckLitNeeded(cfg);
}
SetupDirt(cfg);

View File

@ -3081,7 +3081,7 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
continue;
// skip lightmaps where all samples have brightness below 1
if (bsp->loadversion->game == GAME_QUAKE_II) { // HACK: don't do this on Q2. seems if all styles are 0xff, the face is drawn fullbright instead of black (Q1)
if (bsp->loadversion->game->id == GAME_QUAKE_II) { // HACK: don't do this on Q2. seems if all styles are 0xff, the face is drawn fullbright instead of black (Q1)
const float maxb = Lightmap_MaxBrightness(&lightmap, lightsurf);
if (maxb < 1)
continue;
@ -3147,7 +3147,7 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
int lightofs;
// Q2/HL native colored lightmaps
if (bsp->loadversion->rgb_lightmap) {
if (bsp->loadversion->game->has_rgb_lightmap) {
lightofs = lit - lit_filebase;
} else {
lightofs = out - filebase;

View File

@ -716,7 +716,7 @@ TraceFaces (traceinfo_t *ti, int node, const vec3_t start, const vec3_t end)
// only solid and sky faces stop the trace.
bool issolid, issky; //mxd
if(bsp_static->loadversion->game == GAME_QUAKE_II) {
if(bsp_static->loadversion->game->id == GAME_QUAKE_II) {
issolid = !(fi->content_or_surf_flags & Q2_SURF_TRANSLUCENT);
issky = (fi->content_or_surf_flags & Q2_SURF_SKY);
} else {

View File

@ -353,7 +353,7 @@ Embree_FilterFuncN(const struct RTCFilterFunctionNArguments* args)
//mxd
bool isFence, isGlass;
if(bsp_static->loadversion->game == GAME_QUAKE_II) {
if(bsp_static->loadversion->game->id == GAME_QUAKE_II) {
const int surf_flags = Face_ContentsOrSurfaceFlags(bsp_static, face);
isFence = ((surf_flags & Q2_SURF_TRANSLUCENT) == Q2_SURF_TRANSLUCENT); // KMQuake 2-specific. Use texture alpha chanel when both flags are set.
isGlass = !isFence && (surf_flags & Q2_SURF_TRANSLUCENT);
@ -558,7 +558,7 @@ MakeFaces_r(const mbsp_t *bsp, const int nodenum, std::vector<plane_t> *planes,
const int leafnum = -nodenum - 1;
const mleaf_t *leaf = &bsp->dleafs[leafnum];
if ((bsp->loadversion->game == GAME_QUAKE_II) ? (leaf->contents & Q2_CONTENTS_SOLID) : leaf->contents == CONTENTS_SOLID) {
if ((bsp->loadversion->game->id == GAME_QUAKE_II) ? (leaf->contents & Q2_CONTENTS_SOLID) : leaf->contents == CONTENTS_SOLID) {
std::vector<winding_t *> leaf_windings = Leaf_MakeFaces(bsp, leaf, *planes);
for (winding_t *w : leaf_windings) {
result->push_back(w);
@ -630,7 +630,7 @@ Embree_TraceInit(const mbsp_t *bsp)
const int contents_or_surf_flags = Face_ContentsOrSurfaceFlags(bsp, face); //mxd
const gtexinfo_t *texinfo = Face_Texinfo(bsp, face);
const bool is_q2 = bsp->loadversion->game == GAME_QUAKE_II;
const bool is_q2 = bsp->loadversion->game->id == GAME_QUAKE_II;
//mxd. Skip NODRAW faces, but not SKY ones (Q2's sky01.wal has both flags set)
if(is_q2 && (contents_or_surf_flags & Q2_SURF_NODRAW) && !(contents_or_surf_flags & Q2_SURF_SKY))

View File

@ -439,11 +439,11 @@ CreateBrushFaces(const mapentity_t *src, hullbrush_t *hullbrush,
// account for texture offset, from txqbsp-xt
if (options.fixRotateObjTexture) {
const mtexinfo_t &texinfo = map.mtexinfos.at(mapface->texinfo);
mtexinfo_t texInfoNew;
mtexinfo_t texInfoNew = texinfo;
texInfoNew.outputnum = -1;
vec3_t vecs[2];
int k, l;
memcpy(&texInfoNew, &texinfo, sizeof(texInfoNew));
for (k=0; k<2; k++) {
for (l=0; l<3; l++) {
vecs[k][l] = texinfo.vecs[k][l];
@ -453,7 +453,7 @@ CreateBrushFaces(const mapentity_t *src, hullbrush_t *hullbrush,
texInfoNew.vecs[0][3] += DotProduct( rotate_offset, vecs[0] );
texInfoNew.vecs[1][3] += DotProduct( rotate_offset, vecs[1] );
mapface->texinfo = FindTexinfo( &texInfoNew, texInfoNew.flags );
mapface->texinfo = FindTexinfo(texInfoNew, texInfoNew.flags);
}
VectorCopy(mapface->plane.normal, plane.normal);
@ -487,7 +487,7 @@ CreateBrushFaces(const mapentity_t *src, hullbrush_t *hullbrush,
(rotate_offset[0] != 0.0 || rotate_offset[1] != 0.0 || rotate_offset[2] != 0.0)
&& rottype == rotation_t::hipnotic
&& (hullnum >= 0) // hullnum < 0 corresponds to -wrbrushes clipping hulls
&& options.target_version->game != GAME_HEXEN_II; // never do this in Hexen 2
&& options.target_version->game->id != GAME_HEXEN_II; // never do this in Hexen 2
if (shouldExpand) {
vec_t delta;
@ -930,7 +930,7 @@ brush_t *LoadBrush(const mapentity_t *src, const mapbrush_t *mapbrush, int conte
facelist = CreateBrushFaces(src, &hullbrush, rotate_offset, rottype, hullnum);
}
}
else if (options.target_version->game == GAME_HEXEN_II)
else if (options.target_version->game->id == GAME_HEXEN_II)
{
if (hullnum == 1) {
vec3_t size[2] = { {-16, -16, -32}, {16, 16, 24} };

View File

@ -53,16 +53,13 @@ MakeSkipTexinfo()
// FindMiptex, FindTexinfo not threadsafe
std::unique_lock<std::mutex> lck { csgfaces_lock };
int texinfo;
mtexinfo_t mt;
mtexinfo_t mt { };
mt.miptex = FindMiptex("skip");
mt.flags = { 0, TEX_EXFLAG_SKIP };
memset(&mt.vecs, 0, sizeof(mt.vecs));
texinfo = FindTexinfo(&mt, mt.flags);
return texinfo;
return FindTexinfo(mt, mt.flags);
}
/*

View File

@ -112,7 +112,7 @@ public:
static texdef_valve_t TexDef_BSPToValve(const float in_vecs[2][4]);
static qvec2f projectToAxisPlane(const vec3_t snapped_normal, qvec3f point);
static texdef_quake_ed_noshift_t Reverse_QuakeEd(qmat2x2f M, const qbsp_plane_t *plane, bool preserveX);
static void SetTexinfo_QuakeEd_New(const qbsp_plane_t *plane, const vec_t shift[2], vec_t rotate, const vec_t scale[2], float out_vecs[2][4]);
static void SetTexinfo_QuakeEd_New(const qbsp_plane_t *plane, const vec_t shift[2], vec_t rotate, const vec_t scale[2], stvecs &out_vecs);
static void TestExpandBrushes(const mapentity_t *src);
const mapface_t &mapbrush_t::face(int i) const {
@ -172,7 +172,7 @@ FindMiptex(const char *name)
const char *pathsep;
int i;
if (options.target_version->game != GAME_QUAKE_II) {
if (options.target_version->game->id != GAME_QUAKE_II) {
/* Ignore leading path in texture names (Q2 map compatibility) */
pathsep = strrchr(name, '/');
if (pathsep)
@ -185,7 +185,7 @@ FindMiptex(const char *name)
}
/* Handle animating textures carefully */
if (options.target_version->game != GAME_QUAKE_II) {
if (options.target_version->game->id != GAME_QUAKE_II) {
if (name[0] == '+') {
AddAnimTex(name);
i = map.nummiptex();
@ -256,33 +256,29 @@ Returns a global texinfo number
===============
*/
int
FindTexinfo(mtexinfo_t *texinfo, surfflags_t flags)
FindTexinfo(const mtexinfo_t &texinfo, surfflags_t flags)
{
/* Set the texture flags */
texinfo->flags = flags;
texinfo->outputnum = -1;
// NaN's will break mtexinfo_lookup, since they're being used as a std::map key and don't compare properly with <.
// They should have been stripped out already in ValidateTextureProjection.
for (int i=0;i<2;i++) {
for (int j=0;j<4;j++) {
Q_assert(!std::isnan(texinfo->vecs[i][j]));
Q_assert(!std::isnan(texinfo.vecs[i][j]));
}
}
// check for an exact match in the reverse lookup
const auto it = map.mtexinfo_lookup.find(*texinfo);
const auto it = map.mtexinfo_lookup.find(texinfo);
if (it != map.mtexinfo_lookup.end()) {
return it->second;
}
/* Allocate a new texinfo at the end of the array */
const int num_texinfo = static_cast<int>(map.mtexinfos.size());
map.mtexinfos.push_back(*texinfo);
map.mtexinfo_lookup[*texinfo] = num_texinfo;
map.mtexinfos.push_back(texinfo);
map.mtexinfo_lookup[texinfo] = num_texinfo;
// catch broken < implementations in mtexinfo_t
assert(map.mtexinfo_lookup.find(*texinfo) != map.mtexinfo_lookup.end());
assert(map.mtexinfo_lookup.find(texinfo) != map.mtexinfo_lookup.end());
return num_texinfo;
}
@ -299,14 +295,14 @@ normalize_color_format(vec3_t color)
}
}
int
FindTexinfoEnt(mtexinfo_t *texinfo, const mapentity_t *entity)
static int
FindTexinfoEnt(const mtexinfo_t &texinfo, const mapentity_t *entity)
{
surfflags_t flags {};
const char *texname = map.miptex.at(texinfo->miptex).name.c_str();
const char *texname = map.miptex.at(texinfo.miptex).name.c_str();
const int shadow = atoi(ValueForKey(entity, "_shadow"));
// These flags are pulled from surf flags in Q2.
if (options.target_version->game != GAME_QUAKE_II) {
if (options.target_version->game->id != GAME_QUAKE_II) {
if (IsSkipName(texname))
flags.extended |= TEX_EXFLAG_SKIP;
if (IsHintName(texname))
@ -422,7 +418,7 @@ ParseEpair(parser_t *parser, mapentity_t *entity)
// Quake II uses multiple starts for level transitions/backtracking.
// TODO: instead, this should check targetnames. There should only be
// one info_player_start per targetname in Q2.
if (options.target_version->game != GAME_QUAKE_II && (rgfStartSpots & info_player_start))
if (options.target_version->game->id != GAME_QUAKE_II && (rgfStartSpots & info_player_start))
Message(msgWarning, warnMultipleStarts);
rgfStartSpots |= info_player_start;
} else if (!Q_strcasecmp(epair->value, "info_player_deathmatch")) {
@ -498,7 +494,7 @@ ParseExtendedTX(parser_t *parser)
return result;
}
static qmat4x4f texVecsTo4x4Matrix(const qbsp_plane_t &faceplane, const float in_vecs[2][4])
static qmat4x4f texVecsTo4x4Matrix(const qbsp_plane_t &faceplane, const stvecs &in_vecs)
{
// [s]
// T * vec = [t]
@ -545,7 +541,7 @@ static float extractRotation(qmat2x2f m) {
static qvec2f evalTexDefAtPoint(const texdef_quake_ed_t &texdef, const qbsp_plane_t *faceplane, const qvec3f point)
{
float temp[2][4];
stvecs temp;
SetTexinfo_QuakeEd_New(faceplane, texdef.shift, texdef.rotate, texdef.scale, temp);
const qmat4x4f worldToTexSpace_res = texVecsTo4x4Matrix(*faceplane, temp);
@ -608,7 +604,7 @@ qvec2f normalizeShift(const texture_t *texture, const qvec2f &in)
/// `texture` is optional. If given, the "shift" values can be normalized
static texdef_quake_ed_t
TexDef_BSPToQuakeEd(const qbsp_plane_t &faceplane, const texture_t *texture, const float in_vecs[2][4], const vec3_t facepoints[3])
TexDef_BSPToQuakeEd(const qbsp_plane_t &faceplane, const texture_t *texture, const stvecs &in_vecs, const vec3_t facepoints[3])
{
// First get the un-rotated, un-scaled unit texture vecs (based on the face plane).
vec3_t snapped_normal;
@ -892,7 +888,7 @@ Reverse_QuakeEd(qmat2x2f M, const qbsp_plane_t *plane, bool preserveX)
}
static void
SetTexinfo_QuakeEd_New(const qbsp_plane_t *plane, const vec_t shift[2], vec_t rotate, const vec_t scale[2], float out_vecs[2][4])
SetTexinfo_QuakeEd_New(const qbsp_plane_t *plane, const vec_t shift[2], vec_t rotate, const vec_t scale[2], stvecs &out_vecs)
{
vec_t sanitized_scale[2];
for (int i=0; i<2; i++) {
@ -1011,7 +1007,7 @@ SetTexinfo_QuakeEd(const qbsp_plane_t *plane, const vec3_t planepts[3], const ve
if (false) {
// Self-test of SetTexinfo_QuakeEd_New
float check[2][4];
stvecs check;
SetTexinfo_QuakeEd_New(plane, shift, rotate, scale, check);
for (int i=0; i<2; i++) {
for (int j=0; j<4; j++) {
@ -1174,7 +1170,7 @@ static void ComputeAxisBase( const vec3_t normal_unsanitized, vec3_t texX, vec3_
}
static void
SetTexinfo_BrushPrimitives(const vec3_t texMat[2], const vec3_t faceNormal, int texWidth, int texHeight, float vecs[2][4])
SetTexinfo_BrushPrimitives(const vec3_t texMat[2], const vec3_t faceNormal, int texWidth, int texHeight, stvecs &vecs)
{
vec3_t texX, texY;
@ -1214,7 +1210,7 @@ SetTexinfo_BrushPrimitives(const vec3_t texMat[2], const vec3_t faceNormal, int
vecs[1][3] = texHeight * texMat[1][2];
}
static void BSP_GetSTCoordsForPoint(const vec_t *point, const int texSize[2], const float in_vecs[2][4], vec_t *st_out)
static void BSP_GetSTCoordsForPoint(const vec_t *point, const int texSize[2], const stvecs &in_vecs, vec_t *st_out)
{
for (int i=0; i<2; i++) {
st_out[i] = (point[0] * in_vecs[i][0]
@ -1226,7 +1222,7 @@ static void BSP_GetSTCoordsForPoint(const vec_t *point, const int texSize[2], co
// From FaceToBrushPrimitFace in GtkRadiant
static texdef_brush_primitives_t
TexDef_BSPToBrushPrimitives(const qbsp_plane_t plane, const int texSize[2], const float in_vecs[2][4])
TexDef_BSPToBrushPrimitives(const qbsp_plane_t plane, const int texSize[2], const stvecs &in_vecs)
{
vec3_t texX, texY;
ComputeAxisBase( plane.normal, texX, texY );
@ -1474,6 +1470,7 @@ void mapface_t::set_texvecs(const std::array<qvec4f, 2> &vecs)
{
// start with a copy of the current texinfo structure
mtexinfo_t texInfoNew = map.mtexinfos.at(this->texinfo);
texInfoNew.outputnum = -1;
// update vecs
for (int i=0; i<2; i++) {
@ -1482,7 +1479,7 @@ void mapface_t::set_texvecs(const std::array<qvec4f, 2> &vecs)
}
}
this->texinfo = FindTexinfo( &texInfoNew, texInfoNew.flags );
this->texinfo = FindTexinfo(texInfoNew, texInfoNew.flags);
}
bool
@ -1573,7 +1570,7 @@ ParseBrushFace(parser_t *parser, const mapbrush_t *brush, const mapentity_t *ent
ValidateTextureProjection(*face, &tx);
face->texinfo = FindTexinfoEnt(&tx, entity);
face->texinfo = FindTexinfoEnt(tx, entity);
return face;
}
@ -1972,7 +1969,7 @@ LoadMapFile(void)
}
static texdef_valve_t
TexDef_BSPToValve(const float in_vecs[2][4])
TexDef_BSPToValve(const stvecs &in_vecs)
{
texdef_valve_t res;

View File

@ -575,7 +575,7 @@ CreateHulls(void)
if (options.target_version == &bspver_hl)
CreateSingleHull(3);
else if (options.target_version->game == GAME_HEXEN_II)
else if (options.target_version->game->id == GAME_HEXEN_II)
{ /*note: h2mp doesn't use hull 2 automatically, however gamecode can explicitly set ent.hull=3 to access it*/
CreateSingleHull(3);
CreateSingleHull(4);
@ -622,11 +622,7 @@ EnsureTexturesLoaded()
static const char* //mxd
GetBaseDirName(const bspversion_t *bspver)
{
if (bspver->game == GAME_QUAKE_II)
return "BASEQ2";
if (bspver->game == GAME_HEXEN_II)
return "DATA1";
return "ID1";
return bspver->game->base_dir;
}
/*
@ -977,7 +973,7 @@ ParseOptions(char *szOptions)
}
// force specific flags for Q2
if (options.target_version->game == GAME_QUAKE_II) {
if (options.target_version->game->id == GAME_QUAKE_II) {
options.fNoclip = true;
}
}

View File

@ -47,9 +47,9 @@ SubdivideFace(face_t *f, face_t **prevptr)
/* special (non-surface cached) faces don't need subdivision */
tex = &map.mtexinfos.at(f->texinfo);
// FIXME: Q2
if (tex->flags.extended & (TEX_EXFLAG_SKIP | TEX_EXFLAG_HINT) ||
options.target_version->surf_needs_subdivision(tex->flags))
!options.target_version->game->surf_is_subdivided(tex->flags))
return;
//subdivision is pretty much pointless other than because of lightmap block limits
//one lightmap block will always be added at the end, for smooth interpolation

View File

@ -31,7 +31,7 @@ static void
AssertVanillaContentType(int content)
{
// TODO
if (options.target_version->game == GAME_QUAKE_II) {
if (options.target_version->game->id == GAME_QUAKE_II) {
return;
}
@ -72,7 +72,7 @@ RemapContentsForExport(int content)
content = RemapContentsForExport_(content);
// TODO
if (options.target_version->game == GAME_QUAKE_II) {
if (options.target_version->game->id == GAME_QUAKE_II) {
switch (content) {
case CONTENTS_EMPTY:
return 0;
@ -124,7 +124,7 @@ int
ExportMapTexinfo(int texinfonum)
{
mtexinfo_t *src = &map.mtexinfos.at(texinfonum);
if (src->outputnum != PLANENUM_LEAF)
if (src->outputnum != -1)
return src->outputnum;
// this will be the index of the exported texinfo in the BSP lump
@ -292,7 +292,7 @@ ExportDrawNodes(mapentity_t *entity, node_t *node)
if (node->children[i]->planenum == PLANENUM_LEAF) {
// In Q2, all leaves must have their own ID even if they share solidity.
// (probably for collision purposes? makes sense given they store leafbrushes)
if (options.target_version->game != GAME_QUAKE_II && node->children[i]->contents == CONTENTS_SOLID)
if (options.target_version->game->id != GAME_QUAKE_II && node->children[i]->contents == CONTENTS_SOLID)
dnode->children[i] = -1;
else {
int nextLeafIndex = static_cast<int>(map.exported_leafs.size());

View File

@ -571,7 +571,7 @@ LeafFlow(int leafnum, mleaf_t *dleaf, const mbsp_t *bsp)
/*
* flow through all portals, collecting visible bits
*/
outbuffer = (bsp->loadversion->game == GAME_QUAKE_II ? uncompressed_q2 : uncompressed) + leafnum * leafbytes;
outbuffer = (bsp->loadversion->game->id == GAME_QUAKE_II ? uncompressed_q2 : uncompressed) + leafnum * leafbytes;
leaf = &leafs[leafnum];
for (i = 0; i < leaf->numportals; i++) {
p = leaf->portals[i];
@ -653,7 +653,7 @@ ClusterFlow(int clusternum, leafbits_t *buffer, const mbsp_t *bsp)
*/
numvis = 0;
if (bsp->loadversion->game == GAME_QUAKE_II) {
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
outbuffer = uncompressed_q2 + clusternum * leafbytes;
for (i = 0; i < portalleafs; i++) {
if (TestLeafBit(buffer, i)) {
@ -688,7 +688,7 @@ ClusterFlow(int clusternum, leafbits_t *buffer, const mbsp_t *bsp)
}
/* Allocate for worst case where RLE might grow the data (unlikely) */
if (bsp->loadversion->game == GAME_QUAKE_II) {
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
compressed = static_cast<uint8_t *>(malloc(portalleafs * 2 / 8));
len = CompressRow(outbuffer, (portalleafs + 7) >> 3, compressed);
} else {
@ -1061,7 +1061,7 @@ LoadPortals(char *name, mbsp_t *bsp)
if (count != 2)
Error("%s: unable to parse %s HEADER\n", __func__, PORTALFILE);
if (bsp->loadversion->game == GAME_QUAKE_II) {
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
portalleafs_real = bsp->numleafs;
logprint("%6d leafs\n", portalleafs_real);
logprint("%6d clusters\n", portalleafs);
@ -1101,7 +1101,7 @@ LoadPortals(char *name, mbsp_t *bsp)
leafs = static_cast<leaf_t *>(malloc(portalleafs * sizeof(leaf_t)));
memset(leafs, 0, portalleafs * sizeof(leaf_t));
if (bsp->loadversion->game == GAME_QUAKE_II) {
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
originalvismapsize = portalleafs * ((portalleafs + 7) / 8);
} else {
originalvismapsize = portalleafs_real * ((portalleafs_real + 7) / 8);
@ -1180,7 +1180,7 @@ LoadPortals(char *name, mbsp_t *bsp)
}
/* Load the cluster expansion map if needed */
if (bsp->loadversion->game == GAME_QUAKE_II) {
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
clustermap = static_cast<int *>(malloc(portalleafs_real * sizeof(int)));
for (int32_t i = 0; i < bsp->numleafs; i++) {
@ -1333,7 +1333,7 @@ main(int argc, char **argv)
StripExtension(statetmpfile);
DefaultExtension(statetmpfile, ".vi0");
if (bsp->loadversion->game != GAME_QUAKE_II) {
if (bsp->loadversion->game->id != GAME_QUAKE_II) {
uncompressed = static_cast<uint8_t *>(calloc(portalleafs, leafbytes_real));
} else {
uncompressed_q2 = static_cast<uint8_t *>(calloc(portalleafs, leafbytes));
@ -1351,7 +1351,7 @@ main(int argc, char **argv)
bsp->visdatasize, originalvismapsize);
// no ambient sounds for Q2
if (bsp->loadversion->game != GAME_QUAKE_II) {
if (bsp->loadversion->game->id != GAME_QUAKE_II) {
CalcAmbientSounds(bsp);
}