Squashed commit of the following:
commit8ca122916dAuthor: Eric Wasylishen <ewasylishen@gmail.com> Date: Thu Jul 4 20:54:23 2019 -0600 fix linker error (radlights is in 2 .cpp files) commit8f06fc9c8dAuthor: Eric Wasylishen <ewasylishen@gmail.com> Date: Thu Jul 4 20:53:57 2019 -0600 add clarification comment commit038a553fb0Author: Eric Wasylishen <ewasylishen@gmail.com> Date: Thu Jul 4 20:30:27 2019 -0600 fix tests compilation commit02e94ec507Author: Eric Wasylishen <ewasylishen@gmail.com> Date: Thu Jul 4 19:59:25 2019 -0600 hlbsp: use q_snprintf commit669a5a7911Author: Eric Wasylishen <ewasylishen@gmail.com> Date: Thu Jul 4 19:56:21 2019 -0600 Reformat commit6653760982Merge:347a455ac3553cAuthor: Eric Wasylishen <ewasylishen@gmail.com> Date: Thu Jul 4 19:28:06 2019 -0600 Merge remote-tracking branch 'origin/master' into hlbsp # Conflicts: # include/qbsp/qbsp.hh commit347a455102Author: Shpoike <Shpoike@users.noreply.github.com> Date: Thu Mar 28 02:18:16 2019 +0000 Misc HLBSP tweaks Added support for multiple -wadpath args. Added -xwadpath (for eg valve/*.wad to avoid bloat/license issues). Reworked hint brushes - the non-hint surfaces can use any name, just so long as they're not 'hint', for compat with zhlt. Support 'bevel' and 'null' textures for compat with zhlt. commit7fb22c7367Author: Shpoike <Shpoike@users.noreply.github.com> Date: Thu Mar 28 01:59:42 2019 +0000 Support for halflife-style .rad surface lights (probably too bright, but the basics work). commit2da504fb62Author: Shpoike <Shpoike@users.noreply.github.com> Date: Thu Mar 28 01:56:27 2019 +0000 Add minus-prefixed textures for halflife's randomised-textures feature, instead of getting crash-to-desktop errors when the map is loaded. commit6366199bdbAuthor: Shpoike <Shpoike@users.noreply.github.com> Date: Thu Mar 21 04:51:24 2019 +0000 First attempt at hlbsp output.
This commit is contained in:
parent
ac3553cb50
commit
89365949bc
|
|
@ -33,6 +33,8 @@ BSPVersionString(int32_t version)
|
||||||
return "BSP2rmq";
|
return "BSP2rmq";
|
||||||
case BSP2VERSION:
|
case BSP2VERSION:
|
||||||
return "BSP2";
|
return "BSP2";
|
||||||
|
case BSPHLVERSION:
|
||||||
|
return "HLBSP";
|
||||||
case Q2_BSPVERSION:
|
case Q2_BSPVERSION:
|
||||||
return "Q2BSP";
|
return "Q2BSP";
|
||||||
default:
|
default:
|
||||||
|
|
@ -49,6 +51,8 @@ BSPVersionSupported(int32_t version)
|
||||||
case BSPVERSION:
|
case BSPVERSION:
|
||||||
case BSP2VERSION:
|
case BSP2VERSION:
|
||||||
case BSP2RMQVERSION:
|
case BSP2RMQVERSION:
|
||||||
|
case BSPHLVERSION:
|
||||||
|
return true;
|
||||||
case Q2_BSPVERSION:
|
case Q2_BSPVERSION:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
|
@ -579,7 +583,7 @@ SwapBSPFile(bspdata_t *bspdata, swaptype_t swap)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bspdata->version == BSPVERSION) {
|
if (bspdata->version == BSPVERSION || bspdata->version == BSPHLVERSION) {
|
||||||
bsp29_t *bsp = &bspdata->data.bsp29;
|
bsp29_t *bsp = &bspdata->data.bsp29;
|
||||||
|
|
||||||
SwapBSPVertexes(bsp->numvertexes, bsp->dvertexes);
|
SwapBSPVertexes(bsp->numvertexes, bsp->dvertexes);
|
||||||
|
|
@ -1567,7 +1571,7 @@ ConvertBSPFormat(int32_t version, bspdata_t *bspdata)
|
||||||
|
|
||||||
// conversions to GENERIC_BSP
|
// conversions to GENERIC_BSP
|
||||||
|
|
||||||
if (bspdata->version == BSPVERSION && version == GENERIC_BSP) {
|
if ((bspdata->version == BSPVERSION || bspdata->version == BSPHLVERSION) && version == GENERIC_BSP) {
|
||||||
const bsp29_t *bsp29 = &bspdata->data.bsp29;
|
const bsp29_t *bsp29 = &bspdata->data.bsp29;
|
||||||
mbsp_t *mbsp = &bspdata->data.mbsp;
|
mbsp_t *mbsp = &bspdata->data.mbsp;
|
||||||
|
|
||||||
|
|
@ -1777,7 +1781,7 @@ ConvertBSPFormat(int32_t version, bspdata_t *bspdata)
|
||||||
|
|
||||||
// conversions from GENERIC_BSP
|
// conversions from GENERIC_BSP
|
||||||
|
|
||||||
if (bspdata->version == GENERIC_BSP && version == BSPVERSION) {
|
if (bspdata->version == GENERIC_BSP && (version == BSPVERSION || version == BSPHLVERSION)) {
|
||||||
bsp29_t *bsp29 = &bspdata->data.bsp29;
|
bsp29_t *bsp29 = &bspdata->data.bsp29;
|
||||||
const mbsp_t *mbsp = &bspdata->data.mbsp;
|
const mbsp_t *mbsp = &bspdata->data.mbsp;
|
||||||
|
|
||||||
|
|
@ -2089,6 +2093,7 @@ CopyLump(const dheader_t *header, int lumpnum, void *destptr)
|
||||||
|
|
||||||
switch (header->version) {
|
switch (header->version) {
|
||||||
case BSPVERSION:
|
case BSPVERSION:
|
||||||
|
case BSPHLVERSION:
|
||||||
lumpspec = &lumpspec_bsp29[lumpnum];
|
lumpspec = &lumpspec_bsp29[lumpnum];
|
||||||
break;
|
break;
|
||||||
case BSP2RMQVERSION:
|
case BSP2RMQVERSION:
|
||||||
|
|
@ -2351,7 +2356,7 @@ LoadBSPFile(char *filename, bspdata_t *bspdata)
|
||||||
Q2_CopyLump (header, Q2_LUMP_POP, &bsp->dpop);
|
Q2_CopyLump (header, Q2_LUMP_POP, &bsp->dpop);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version == BSPVERSION) {
|
if (version == BSPVERSION || version == BSPHLVERSION) {
|
||||||
dheader_t *header = (dheader_t *)file_data;
|
dheader_t *header = (dheader_t *)file_data;
|
||||||
bsp29_t *bsp = &bspdata->data.bsp29;
|
bsp29_t *bsp = &bspdata->data.bsp29;
|
||||||
|
|
||||||
|
|
@ -2488,6 +2493,7 @@ AddLump(bspfile_t *bspfile, int lumpnum, const void *data, int count)
|
||||||
|
|
||||||
switch (bspfile->version) {
|
switch (bspfile->version) {
|
||||||
case BSPVERSION:
|
case BSPVERSION:
|
||||||
|
case BSPHLVERSION:
|
||||||
size = lumpspec_bsp29[lumpnum].size * count;
|
size = lumpspec_bsp29[lumpnum].size * count;
|
||||||
break;
|
break;
|
||||||
case BSP2RMQVERSION:
|
case BSP2RMQVERSION:
|
||||||
|
|
@ -2584,7 +2590,8 @@ WriteBSPFile(const char *filename, bspdata_t *bspdata)
|
||||||
SafeWrite(bspfile.file, &bspfile.q1header, sizeof(bspfile.q1header));
|
SafeWrite(bspfile.file, &bspfile.q1header, sizeof(bspfile.q1header));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bspdata->version == BSPVERSION) {
|
if (bspdata->version == BSPVERSION ||
|
||||||
|
bspdata->version == BSPHLVERSION) {
|
||||||
bsp29_t *bsp = &bspdata->data.bsp29;
|
bsp29_t *bsp = &bspdata->data.bsp29;
|
||||||
|
|
||||||
AddLump(&bspfile, LUMP_PLANES, bsp->dplanes, bsp->numplanes);
|
AddLump(&bspfile, LUMP_PLANES, bsp->dplanes, bsp->numplanes);
|
||||||
|
|
@ -2766,7 +2773,7 @@ PrintBSPFileSizes(const bspdata_t *bspdata)
|
||||||
logprint("%7s %-12s %10i\n", "", "entdata", bsp->entdatasize);
|
logprint("%7s %-12s %10i\n", "", "entdata", bsp->entdatasize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bspdata->version == BSPVERSION) {
|
if (bspdata->version == BSPVERSION || bspdata->version == BSPHLVERSION) {
|
||||||
const bsp29_t *bsp = &bspdata->data.bsp29;
|
const bsp29_t *bsp = &bspdata->data.bsp29;
|
||||||
const lumpspec_t *lumpspec = lumpspec_bsp29;
|
const lumpspec_t *lumpspec = lumpspec_bsp29;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
#define BSPVERSION 29
|
#define BSPVERSION 29
|
||||||
#define BSP2RMQVERSION (('B' << 24) | ('S' << 16) | ('P' << 8) | '2')
|
#define BSP2RMQVERSION (('B' << 24) | ('S' << 16) | ('P' << 8) | '2')
|
||||||
#define BSP2VERSION ('B' | ('S' << 8) | ('P' << 16) | ('2' << 24))
|
#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_BSPIDENT (('P'<<24)+('S'<<16)+('B'<<8)+'I')
|
||||||
#define Q2_BSPVERSION 38
|
#define Q2_BSPVERSION 38
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,7 @@ std::string WorldValueForKey(const std::string &key);
|
||||||
|
|
||||||
void LoadEntities(const globalconfig_t &cfg, const mbsp_t *bsp);
|
void LoadEntities(const globalconfig_t &cfg, const mbsp_t *bsp);
|
||||||
void SetupLights(const globalconfig_t &cfg, const mbsp_t *bsp);
|
void SetupLights(const globalconfig_t &cfg, const mbsp_t *bsp);
|
||||||
|
bool ParseLightsFile(const char *fname);
|
||||||
void WriteEntitiesToString(mbsp_t *bsp);
|
void WriteEntitiesToString(mbsp_t *bsp);
|
||||||
void EstimateVisibleBoundsAtPoint(const vec3_t point, vec3_t mins, vec3_t maxs);
|
void EstimateVisibleBoundsAtPoint(const vec3_t point, vec3_t mins, vec3_t maxs);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ int Brush_ListCountWithCFlags(const brush_t *brush, int cflags);
|
||||||
int Brush_ListCount(const brush_t *brush);
|
int Brush_ListCount(const brush_t *brush);
|
||||||
int Brush_NumFaces(const brush_t *brush);
|
int Brush_NumFaces(const brush_t *brush);
|
||||||
|
|
||||||
brush_t *LoadBrush(const mapbrush_t *mapbrush, const vec3_t rotate_offset, const int hullnum);
|
brush_t *LoadBrush(const mapbrush_t *mapbrush, int contents, const vec3_t rotate_offset, const int hullnum);
|
||||||
void FreeBrushes(mapentity_t *ent);
|
void FreeBrushes(mapentity_t *ent);
|
||||||
|
|
||||||
int FindPlane(const vec3_t normal, const vec_t dist, int *side);
|
int FindPlane(const vec3_t normal, const vec_t dist, int *side);
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ extern "C" {
|
||||||
typedef uint8_t byte;
|
typedef uint8_t byte;
|
||||||
|
|
||||||
#define BSPVERSION 29
|
#define BSPVERSION 29
|
||||||
|
#define BSPHLVERSION 30
|
||||||
#define BSP2RMQVERSION (('B' << 24) | ('S' << 16) | ('P' << 8) | '2')
|
#define BSP2RMQVERSION (('B' << 24) | ('S' << 16) | ('P' << 8) | '2')
|
||||||
#define BSP2VERSION ('B' | ('S' << 8) | ('P' << 16) | ('2' << 24))
|
#define BSP2VERSION ('B' | ('S' << 8) | ('P' << 16) | ('2' << 24))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ public:
|
||||||
int firstface;
|
int firstface;
|
||||||
int numfaces;
|
int numfaces;
|
||||||
brushformat_t format;
|
brushformat_t format;
|
||||||
|
int contents;
|
||||||
|
|
||||||
mapbrush_t() : firstface(0), numfaces(0), format(brushformat_t::NORMAL) {}
|
mapbrush_t() : firstface(0), numfaces(0), format(brushformat_t::NORMAL) {}
|
||||||
const mapface_t &face(int i) const;
|
const mapface_t &face(int i) const;
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,8 @@
|
||||||
#define CONTENTS_DETAIL_ILLUSIONARY -11 /* compiler internal use only */
|
#define CONTENTS_DETAIL_ILLUSIONARY -11 /* compiler internal use only */
|
||||||
#define CONTENTS_DETAIL_FENCE -12 /* compiler internal use only */
|
#define CONTENTS_DETAIL_FENCE -12 /* compiler internal use only */
|
||||||
#define CONTENTS_ILLUSIONARY_VISBLOCKER -13
|
#define CONTENTS_ILLUSIONARY_VISBLOCKER -13
|
||||||
|
#define CONTENTS_FENCE -15 /* compiler internal use only */
|
||||||
|
#define CONTENTS_LADDER -16 /* reserved for engine use */
|
||||||
|
|
||||||
// Special contents flags for the compiler only
|
// Special contents flags for the compiler only
|
||||||
#define CFLAGS_STRUCTURAL_COVERED_BY_DETAIL (1U << 0)
|
#define CFLAGS_STRUCTURAL_COVERED_BY_DETAIL (1U << 0)
|
||||||
|
|
@ -140,6 +142,7 @@
|
||||||
#define TEX_PHONG_ANGLE_CONCAVE_MASK (255ULL << TEX_PHONG_ANGLE_CONCAVE_SHIFT) /* 8 bit value. if non zero, overrides _phong_angle for concave joints. */
|
#define TEX_PHONG_ANGLE_CONCAVE_MASK (255ULL << TEX_PHONG_ANGLE_CONCAVE_SHIFT) /* 8 bit value. if non zero, overrides _phong_angle for concave joints. */
|
||||||
#define TEX_NOBOUNCE (1ULL << 53) /* light doesn't bounce off this face */
|
#define TEX_NOBOUNCE (1ULL << 53) /* light doesn't bounce off this face */
|
||||||
#define TEX_NOMINLIGHT (1ULL << 54) /* opt out of minlight on this face */
|
#define TEX_NOMINLIGHT (1ULL << 54) /* opt out of minlight on this face */
|
||||||
|
#define TEX_NOEXPAND (1ULL << 55) /* don't expand this face for larger clip hulls */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The quality of the bsp output is highly sensitive to these epsilon values.
|
* The quality of the bsp output is highly sensitive to these epsilon values.
|
||||||
|
|
@ -368,7 +371,11 @@ public:
|
||||||
float midsplitSurfFraction;
|
float midsplitSurfFraction;
|
||||||
char szMapName[512];
|
char szMapName[512];
|
||||||
char szBSPName[512];
|
char szBSPName[512];
|
||||||
char wadPath[512];
|
struct
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
bool external; //wads from this path are not to be embedded into the bsp, but will instead require the engine to load them from elsewhere. strongly recommended for eg halflife.wad
|
||||||
|
} wadPaths[16];
|
||||||
vec_t on_epsilon;
|
vec_t on_epsilon;
|
||||||
bool fObjExport;
|
bool fObjExport;
|
||||||
bool fOmitDetail;
|
bool fOmitDetail;
|
||||||
|
|
@ -381,6 +388,14 @@ public:
|
||||||
bool fContentHack;
|
bool fContentHack;
|
||||||
vec_t worldExtent;
|
vec_t worldExtent;
|
||||||
|
|
||||||
|
|
||||||
|
~options_t() {
|
||||||
|
for (int i = 0; i < sizeof(wadPaths)/sizeof(wadPaths[0]); i++)
|
||||||
|
{
|
||||||
|
free(wadPaths[i].path);
|
||||||
|
wadPaths[i].path = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
options_t() {
|
options_t() {
|
||||||
memset(this, 0, sizeof(options_t));
|
memset(this, 0, sizeof(options_t));
|
||||||
|
|
||||||
|
|
@ -390,7 +405,6 @@ public:
|
||||||
this->fVerbose = true;
|
this->fVerbose = true;
|
||||||
this->szMapName[0] = 0;
|
this->szMapName[0] = 0;
|
||||||
this->szBSPName[0] = 0;
|
this->szBSPName[0] = 0;
|
||||||
this->wadPath[0] = 0;
|
|
||||||
|
|
||||||
/* Default to the original Quake BSP Version... */
|
/* Default to the original Quake BSP Version... */
|
||||||
this->BSPVersion = BSPVERSION;
|
this->BSPVersion = BSPVERSION;
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ typedef struct wad_s {
|
||||||
struct wad_s *next;
|
struct wad_s *next;
|
||||||
} wad_t;
|
} wad_t;
|
||||||
|
|
||||||
wad_t *WADList_AddWad(const char *fpath, wad_t *current_wadlist);
|
wad_t *WADList_AddWad(const char *fpath, bool external, wad_t *current_wadlist);
|
||||||
wad_t *WADList_Init(const char *wadstring);
|
wad_t *WADList_Init(const char *wadstring);
|
||||||
void WADList_Process(const wad_t *wadlist);
|
void WADList_Process(const wad_t *wadlist);
|
||||||
void WADList_Free(wad_t *wadlist);
|
void WADList_Free(wad_t *wadlist);
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ using namespace polylib;
|
||||||
|
|
||||||
mutex radlights_lock;
|
mutex radlights_lock;
|
||||||
map<string, qvec3f> texturecolors;
|
map<string, qvec3f> texturecolors;
|
||||||
std::vector<bouncelight_t> radlights;
|
static std::vector<bouncelight_t> radlights;
|
||||||
std::map<int, std::vector<int>> radlightsByFacenum;
|
std::map<int, std::vector<int>> radlightsByFacenum;
|
||||||
|
|
||||||
class patch_t {
|
class patch_t {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ using strings = std::vector<std::string>;
|
||||||
std::vector<light_t> all_lights;
|
std::vector<light_t> all_lights;
|
||||||
std::vector<sun_t> all_suns;
|
std::vector<sun_t> all_suns;
|
||||||
std::vector<entdict_t> entdicts;
|
std::vector<entdict_t> entdicts;
|
||||||
|
static std::vector<entdict_t> radlights;
|
||||||
|
|
||||||
const std::vector<light_t>& GetLights() {
|
const std::vector<light_t>& GetLights() {
|
||||||
return all_lights;
|
return all_lights;
|
||||||
|
|
@ -1587,8 +1588,53 @@ static void GL_SubdivideSurface (const bsp2_dface_t *face, const modelinfo_t *fa
|
||||||
SubdividePolygon (face, face_modelinfo, bsp, face->numedges, verts[0], surflight_subdivide);
|
SubdividePolygon (face, face_modelinfo, bsp, face->numedges, verts[0], surflight_subdivide);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ParseLightsFile(const char *fname)
|
||||||
|
{ //note: this creates dupes. super bright light! (and super slow, too)
|
||||||
|
light_t l;
|
||||||
|
char buf[1024];
|
||||||
|
char gah[256];
|
||||||
|
const char *t;
|
||||||
|
float r, g, b;
|
||||||
|
FILE *f = fopen(fname, "r");
|
||||||
|
if(!f)
|
||||||
|
return false;
|
||||||
|
while(!feof(f))
|
||||||
|
{
|
||||||
|
fgets(buf, sizeof(buf), f);
|
||||||
|
t = buf;
|
||||||
|
|
||||||
|
t = COM_Parse(buf);
|
||||||
|
if (!t)
|
||||||
|
continue;
|
||||||
|
entdict_t d = {};
|
||||||
|
d["_surface"] = std::string(com_token);
|
||||||
|
t = COM_Parse(t);
|
||||||
|
r = atof(com_token);
|
||||||
|
t = COM_Parse(t);
|
||||||
|
g = atof(com_token);
|
||||||
|
t = COM_Parse(t);
|
||||||
|
b = atof(com_token);
|
||||||
|
q_snprintf(gah, sizeof(gah), "%f %f %f", r,g,b);
|
||||||
|
d["_color"] = std::string(gah);
|
||||||
|
t = COM_Parse(t);
|
||||||
|
d["light"] = std::string(com_token);
|
||||||
|
//might be hdr rgbi values here
|
||||||
|
|
||||||
|
radlights.push_back(d);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void MakeSurfaceLights(const mbsp_t *bsp)
|
static void MakeSurfaceLights(const mbsp_t *bsp)
|
||||||
{
|
{
|
||||||
|
for (entdict_t &l : radlights) {
|
||||||
|
light_t entity {};
|
||||||
|
entity.epairs = &l;
|
||||||
|
entity.settings().setSettings(*entity.epairs, false);
|
||||||
|
surfacelight_templates.push_back(entity);
|
||||||
|
}
|
||||||
|
|
||||||
for (light_t &entity : all_lights) {
|
for (light_t &entity : all_lights) {
|
||||||
std::string tex = ValueForKey(&entity, "_surface");
|
std::string tex = ValueForKey(&entity, "_surface");
|
||||||
if (!tex.empty()) {
|
if (!tex.empty()) {
|
||||||
|
|
|
||||||
|
|
@ -772,7 +772,8 @@ static void PrintUsage()
|
||||||
" -lux write .lux file\n"
|
" -lux write .lux file\n"
|
||||||
" -bspxlit writes rgb data into the bsp itself\n"
|
" -bspxlit writes rgb data into the bsp itself\n"
|
||||||
" -bspx writes both rgb and directions data into the bsp itself\n"
|
" -bspx writes both rgb and directions data into the bsp itself\n"
|
||||||
" -novanilla implies -bspxlit. don't write vanilla lighting\n");
|
" -novanilla implies -bspxlit. don't write vanilla lighting\n"
|
||||||
|
" -light filename.rad loads a <surfacename> <r> <g> <b> <intensity> file\n");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Overridable worldspawn keys:\n");
|
printf("Overridable worldspawn keys:\n");
|
||||||
|
|
@ -961,6 +962,9 @@ light_main(int argc, const char **argv)
|
||||||
write_luxfile |= 2;
|
write_luxfile |= 2;
|
||||||
} else if (!strcmp(argv[i], "-novanilla")) {
|
} else if (!strcmp(argv[i], "-novanilla")) {
|
||||||
scaledonly = true;
|
scaledonly = true;
|
||||||
|
} else if ( !strcmp( argv[ i ], "-light" ) ) {
|
||||||
|
if (!ParseLightsFile(argv[++i]))
|
||||||
|
logprint( "Unable to read surfacelights file %s\n", argv[i] );
|
||||||
} else if ( !strcmp( argv[ i ], "-lmscale" ) ) {
|
} else if ( !strcmp( argv[ i ], "-lmscale" ) ) {
|
||||||
lmscaleoverride = argv[++i];
|
lmscaleoverride = argv[++i];
|
||||||
} else if (!strcmp(argv[i], "-soft")) {
|
} else if (!strcmp(argv[i], "-soft")) {
|
||||||
|
|
@ -1141,6 +1145,14 @@ light_main(int argc, const char **argv)
|
||||||
remove(source);
|
remove(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
StripExtension(source);
|
||||||
|
DefaultExtension(source, ".rad");
|
||||||
|
if (strcmp(source, "lights.rad"))
|
||||||
|
ParseLightsFile("lights.rad"); //generic/default name
|
||||||
|
ParseLightsFile(source); //map-specific file name
|
||||||
|
}
|
||||||
|
|
||||||
StripExtension(source);
|
StripExtension(source);
|
||||||
DefaultExtension(source, ".bsp");
|
DefaultExtension(source, ".bsp");
|
||||||
LoadBSPFile(source, &bspdata);
|
LoadBSPFile(source, &bspdata);
|
||||||
|
|
@ -1189,7 +1201,7 @@ light_main(int argc, const char **argv)
|
||||||
|
|
||||||
if (!onlyents)
|
if (!onlyents)
|
||||||
{
|
{
|
||||||
if (loadversion != Q2_BSPVERSION) //mxd. No lit for Quake 2
|
if (loadversion != Q2_BSPVERSION && bsp->loadversion != BSPHLVERSION) //mxd. No lit for Quake 2
|
||||||
CheckLitNeeded(cfg);
|
CheckLitNeeded(cfg);
|
||||||
SetupDirt(cfg);
|
SetupDirt(cfg);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3026,7 +3026,7 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
|
||||||
int size = (lightsurf->texsize[0] + 1) * (lightsurf->texsize[1] + 1);
|
int size = (lightsurf->texsize[0] + 1) * (lightsurf->texsize[1] + 1);
|
||||||
|
|
||||||
// q2 support
|
// q2 support
|
||||||
if (bsp->loadversion == Q2_BSPVERSION)
|
if (bsp->loadversion == Q2_BSPVERSION || bsp->loadversion == BSPHLVERSION)
|
||||||
size *= 3;
|
size *= 3;
|
||||||
|
|
||||||
byte *out, *lit, *lux;
|
byte *out, *lit, *lux;
|
||||||
|
|
@ -3084,7 +3084,7 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
|
||||||
*lit++ = color[1];
|
*lit++ = color[1];
|
||||||
*lit++ = color[2];
|
*lit++ = color[2];
|
||||||
|
|
||||||
if (bsp->loadversion == Q2_BSPVERSION) {
|
if (bsp->loadversion == Q2_BSPVERSION || bsp->loadversion == BSPHLVERSION) {
|
||||||
*out++ = color[0];
|
*out++ = color[0];
|
||||||
*out++ = color[1];
|
*out++ = color[1];
|
||||||
*out++ = color[2];
|
*out++ = color[2];
|
||||||
|
|
|
||||||
24
man/qbsp.1
24
man/qbsp.1
|
|
@ -30,7 +30,8 @@ Print out more .map information
|
||||||
.IP "\fB-noverbose\fP"
|
.IP "\fB-noverbose\fP"
|
||||||
Print out almost no information at all
|
Print out almost no information at all
|
||||||
.IP "\fB-splitspecial\fP"
|
.IP "\fB-splitspecial\fP"
|
||||||
Doesn't combine sky and water faces into one large face
|
Doesn't combine sky and water faces into one large face.
|
||||||
|
This allows for statically lit water.
|
||||||
.IP "\fB-transwater\fP"
|
.IP "\fB-transwater\fP"
|
||||||
Computes portal information for transparent water (default)
|
Computes portal information for transparent water (default)
|
||||||
.IP "\fB-notranswater\fP"
|
.IP "\fB-notranswater\fP"
|
||||||
|
|
@ -53,19 +54,27 @@ Create an old-style QBSP .PTS file (default is new)
|
||||||
Makes it a compile error if a leak is detected.
|
Makes it a compile error if a leak is detected.
|
||||||
.IP "\fB-nopercent\fP"
|
.IP "\fB-nopercent\fP"
|
||||||
Prevents output of percent completion information
|
Prevents output of percent completion information
|
||||||
|
.IP "\fB-hexen2\fP"
|
||||||
|
Generate a hexen2 bsp. This can be used in addition to -bsp2 to avoid clipnode issues.
|
||||||
.IP "\fB-bsp2\fP"
|
.IP "\fB-bsp2\fP"
|
||||||
Create the output BSP file in BSP2 format. Allows the creation of much larger
|
Create the output BSP file in BSP2 format. Allows the creation of much larger
|
||||||
and more complex maps than the original BSP 29 format).
|
and more complex maps than the original BSP 29 format).
|
||||||
.IP "\fB-2psb\fP"
|
.IP "\fB-2psb\fP"
|
||||||
Create the output BSP file in 2PSB format. This an earlier version of the
|
Create the output BSP file in 2PSB format. This an earlier version of the
|
||||||
BSP2 format, supported by the RMQ engine (and thus is also known as the
|
BSP2 format, supported by the RMQ engine (and thus is also known as the
|
||||||
BSP2rmq or RMQe bsp format). original BSP 29 format).
|
BSP2rmq or RMQe bsp format).
|
||||||
|
.IP "\fB-hlbsp\fP"
|
||||||
|
Create the output BSP file in Half-Life's format.
|
||||||
|
Note that the hull size differences prevent this from being generally usable for the vanilla quake gamecode.
|
||||||
|
This cannot be used in combination with the -bsp2 argument.
|
||||||
.IP "\fB-leakdist [n]\fP"
|
.IP "\fB-leakdist [n]\fP"
|
||||||
Space between leakfile points (default 2)
|
Space between leakfile points (default 2)
|
||||||
.IP "\fB-subdivide [n]\fP"
|
.IP "\fB-subdivide [n]\fP"
|
||||||
Use different texture subdivision (default 240)
|
Use different texture subdivision (default 240). Lower values will harm framerates. Higher values may not be supported. DP+FTEQW+QSS support up to 4080 (unless lightmap scaling is in use), but such values will cause other engines to crash-to-console.
|
||||||
.IP "\fB-wadpath <dir>\fP"
|
.IP "\fB-wadpath <dir>\fP"
|
||||||
Search this directory for wad files (default is cwd)
|
Search this directory for wad files (default is cwd). Multiple -wadpath args may be used. This argument is ignored for wads specified using an absolute path.
|
||||||
|
.IP "\fB-xwadpath <dir>\fP"
|
||||||
|
Like -wadpath, except textures found using the specified path will NOT be embedded into the bsp (equivelent to -notex, but for only textures from specific wads). You should use this for wads like halflife's standard wad files, but q1bsps require an engine extension and players are not nearly as likely to have the same wad version.
|
||||||
.IP "\fB-oldrottex\fP"
|
.IP "\fB-oldrottex\fP"
|
||||||
Use old method of texturing rotate_ brushes where the mapper aligns
|
Use old method of texturing rotate_ brushes where the mapper aligns
|
||||||
textures for the object at (0 0 0).
|
textures for the object at (0 0 0).
|
||||||
|
|
@ -74,14 +83,13 @@ Switch to the cheap spatial subdivion bsp heuristic when splitting nodes
|
||||||
of this size (in any dimension). This gives much faster qbsp processing
|
of this size (in any dimension). This gives much faster qbsp processing
|
||||||
times on large maps and should generate better bsp trees as well.
|
times on large maps and should generate better bsp trees as well.
|
||||||
From txqbsp-xt, thanks rebb. (default 1024, 0 to disable)
|
From txqbsp-xt, thanks rebb. (default 1024, 0 to disable)
|
||||||
.IP "\fB-hexen2\fP"
|
|
||||||
Generate a hexen2 bsp.
|
|
||||||
.IP "\fB-wrbrushes\fP"
|
.IP "\fB-wrbrushes\fP"
|
||||||
(bspx) Includes a list of brushes for brush-based collision.
|
(bspx) Includes a list of brushes for brush-based collision.
|
||||||
|
This allows for arbitrary collision sizes in engines that support it, currently only FTEQW.
|
||||||
.IP "\fB-wrbrushesonly\fP"
|
.IP "\fB-wrbrushesonly\fP"
|
||||||
"-wrbrushes" combined with "-noclip" argument.
|
"-wrbrushes" combined with "-noclip" argument. This is NOT backwards compatible.
|
||||||
.IP "\fB-notex\fP"
|
.IP "\fB-notex\fP"
|
||||||
Write only placeholder textures, to depend upon replacements.
|
Write only placeholder textures, to depend upon replacements. This avoids inclusion of third-party copyrighted images inside your maps, but is not backwards compatible but will work in FTEQW and QSS.
|
||||||
.IP "\fB-omitdetail\fP"
|
.IP "\fB-omitdetail\fP"
|
||||||
Detail brushes are omitted from the compile.
|
Detail brushes are omitted from the compile.
|
||||||
.IP "\fB-convert <fmt>\fP"
|
.IP "\fB-convert <fmt>\fP"
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
typedef struct hullbrush_s {
|
typedef struct hullbrush_s {
|
||||||
const mapbrush_t *srcbrush;
|
const mapbrush_t *srcbrush;
|
||||||
|
int contents;
|
||||||
int numfaces;
|
int numfaces;
|
||||||
vec3_t mins;
|
vec3_t mins;
|
||||||
vec3_t maxs;
|
vec3_t maxs;
|
||||||
|
|
@ -382,12 +383,13 @@ CreateBrushFaces(hullbrush_t *hullbrush, const vec3_t rotate_offset,
|
||||||
|
|
||||||
mapface = hullbrush->faces;
|
mapface = hullbrush->faces;
|
||||||
for (i = 0; i < hullbrush->numfaces; i++, mapface++) {
|
for (i = 0; i < hullbrush->numfaces; i++, mapface++) {
|
||||||
if (!hullnum) {
|
if (!hullnum && hullbrush->contents == CONTENTS_HINT) {
|
||||||
/* Don't generate hintskip faces */
|
/* Don't generate hintskip faces */
|
||||||
const mtexinfo_t &texinfo = map.mtexinfos.at(mapface->texinfo);
|
const mtexinfo_t &texinfo = map.mtexinfos.at(mapface->texinfo);
|
||||||
const char *texname = map.miptex.at(texinfo.miptex).c_str();
|
const char *texname = map.miptex.at(texinfo.miptex).c_str();
|
||||||
if (!Q_strcasecmp(texname, "hintskip"))
|
|
||||||
continue;
|
if (Q_strcasecmp(texname, "hint"))
|
||||||
|
continue; // anything texname other than "hint" in a hint brush is treated as "hintskip", and discarded
|
||||||
}
|
}
|
||||||
|
|
||||||
w = BaseWindingForPlane(&mapface->plane);
|
w = BaseWindingForPlane(&mapface->plane);
|
||||||
|
|
@ -764,6 +766,8 @@ ExpandBrush(hullbrush_t *hullbrush, vec3_t hull_size[2], face_t *facelist)
|
||||||
// expand all of the planes
|
// expand all of the planes
|
||||||
mapface = hullbrush->faces;
|
mapface = hullbrush->faces;
|
||||||
for (i = 0; i < hullbrush->numfaces; i++, mapface++) {
|
for (i = 0; i < hullbrush->numfaces; i++, mapface++) {
|
||||||
|
if (mapface->flags & TEX_NOEXPAND)
|
||||||
|
continue;
|
||||||
VectorCopy(vec3_origin, corner);
|
VectorCopy(vec3_origin, corner);
|
||||||
for (x = 0; x < 3; x++) {
|
for (x = 0; x < 3; x++) {
|
||||||
if (mapface->plane.normal[x] > 0)
|
if (mapface->plane.normal[x] > 0)
|
||||||
|
|
@ -814,13 +818,17 @@ static int
|
||||||
Brush_GetContents(const mapbrush_t *mapbrush)
|
Brush_GetContents(const mapbrush_t *mapbrush)
|
||||||
{
|
{
|
||||||
const char *texname;
|
const char *texname;
|
||||||
const mapface_t &mapface = mapbrush->face(0);
|
|
||||||
|
//check for strong content indicators
|
||||||
|
for (int i = 0; i < mapbrush->numfaces; i++)
|
||||||
|
{
|
||||||
|
const mapface_t &mapface = mapbrush->face(i);
|
||||||
const mtexinfo_t &texinfo = map.mtexinfos.at(mapface.texinfo);
|
const mtexinfo_t &texinfo = map.mtexinfos.at(mapface.texinfo);
|
||||||
texname = map.miptex.at(texinfo.miptex).c_str();
|
texname = map.miptex.at(texinfo.miptex).c_str();
|
||||||
|
|
||||||
if (!Q_strcasecmp(texname, "origin"))
|
if (!Q_strcasecmp(texname, "origin"))
|
||||||
return CONTENTS_ORIGIN;
|
return CONTENTS_ORIGIN;
|
||||||
if (!Q_strcasecmp(texname, "hint") || !Q_strcasecmp(texname, "hintskip"))
|
if (!Q_strcasecmp(texname, "hint"))
|
||||||
return CONTENTS_HINT;
|
return CONTENTS_HINT;
|
||||||
if (!Q_strcasecmp(texname, "clip"))
|
if (!Q_strcasecmp(texname, "clip"))
|
||||||
return CONTENTS_CLIP;
|
return CONTENTS_CLIP;
|
||||||
|
|
@ -835,7 +843,8 @@ Brush_GetContents(const mapbrush_t *mapbrush)
|
||||||
|
|
||||||
if (!Q_strncasecmp(texname, "sky", 3))
|
if (!Q_strncasecmp(texname, "sky", 3))
|
||||||
return CONTENTS_SKY;
|
return CONTENTS_SKY;
|
||||||
|
}
|
||||||
|
//and anything else is assumed to be a regular solid.
|
||||||
return CONTENTS_SOLID;
|
return CONTENTS_SOLID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -847,7 +856,7 @@ LoadBrush
|
||||||
Converts a mapbrush to a bsp brush
|
Converts a mapbrush to a bsp brush
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
brush_t *LoadBrush(const mapbrush_t *mapbrush, const vec3_t rotate_offset, const int hullnum)
|
brush_t *LoadBrush(const mapbrush_t *mapbrush, int contents, const vec3_t rotate_offset, const int hullnum)
|
||||||
{
|
{
|
||||||
hullbrush_t hullbrush;
|
hullbrush_t hullbrush;
|
||||||
brush_t *brush;
|
brush_t *brush;
|
||||||
|
|
@ -858,6 +867,7 @@ brush_t *LoadBrush(const mapbrush_t *mapbrush, const vec3_t rotate_offset, const
|
||||||
Error("brush->faces >= MAX_FACES (%d), source brush on line %d",
|
Error("brush->faces >= MAX_FACES (%d), source brush on line %d",
|
||||||
MAX_FACES, mapbrush->face(0).linenum);
|
MAX_FACES, mapbrush->face(0).linenum);
|
||||||
|
|
||||||
|
hullbrush.contents = contents;
|
||||||
hullbrush.srcbrush = mapbrush;
|
hullbrush.srcbrush = mapbrush;
|
||||||
hullbrush.numfaces = mapbrush->numfaces;
|
hullbrush.numfaces = mapbrush->numfaces;
|
||||||
for (int i=0; i<mapbrush->numfaces; i++)
|
for (int i=0; i<mapbrush->numfaces; i++)
|
||||||
|
|
@ -877,7 +887,28 @@ brush_t *LoadBrush(const mapbrush_t *mapbrush, const vec3_t rotate_offset, const
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.hexen2)
|
if (options.BSPVersion == BSPHLVERSION)
|
||||||
|
{
|
||||||
|
if (hullnum == 1) {
|
||||||
|
vec3_t size[2] = { {-16, -16, -36}, {16, 16, 36} };
|
||||||
|
ExpandBrush(&hullbrush, size, facelist);
|
||||||
|
FreeBrushFaces(facelist);
|
||||||
|
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||||
|
}
|
||||||
|
else if (hullnum == 2) {
|
||||||
|
vec3_t size[2] = { {-32, -32, -32}, {32, 32, 32} };
|
||||||
|
ExpandBrush(&hullbrush, size, facelist);
|
||||||
|
FreeBrushFaces(facelist);
|
||||||
|
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||||
|
}
|
||||||
|
else if (hullnum == 3) {
|
||||||
|
vec3_t size[2] = { {-16, -16, -18}, {16, 16, 18} };
|
||||||
|
ExpandBrush(&hullbrush, size, facelist);
|
||||||
|
FreeBrushFaces(facelist);
|
||||||
|
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (options.hexen2)
|
||||||
{
|
{
|
||||||
if (hullnum == 1) {
|
if (hullnum == 1) {
|
||||||
vec3_t size[2] = { {-16, -16, -32}, {16, 16, 24} };
|
vec3_t size[2] = { {-16, -16, -32}, {16, 16, 24} };
|
||||||
|
|
@ -940,6 +971,7 @@ brush_t *LoadBrush(const mapbrush_t *mapbrush, const vec3_t rotate_offset, const
|
||||||
// create the brush
|
// create the brush
|
||||||
brush = (brush_t *)AllocMem(BRUSH, 1, true);
|
brush = (brush_t *)AllocMem(BRUSH, 1, true);
|
||||||
|
|
||||||
|
brush->contents = contents;
|
||||||
brush->faces = facelist;
|
brush->faces = facelist;
|
||||||
VectorCopy(hullbrush.mins, brush->mins);
|
VectorCopy(hullbrush.mins, brush->mins);
|
||||||
VectorCopy(hullbrush.maxs, brush->maxs);
|
VectorCopy(hullbrush.maxs, brush->maxs);
|
||||||
|
|
@ -1076,7 +1108,7 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
brush_t *brush = LoadBrush(mapbrush, vec3_origin, 0);
|
brush_t *brush = LoadBrush(mapbrush, contents, vec3_origin, 0);
|
||||||
if (brush) {
|
if (brush) {
|
||||||
vec3_t origin;
|
vec3_t origin;
|
||||||
VectorAdd(brush->mins, brush->maxs, origin);
|
VectorAdd(brush->mins, brush->maxs, origin);
|
||||||
|
|
@ -1200,7 +1232,7 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
|
||||||
*/
|
*/
|
||||||
if (contents == CONTENTS_CLIP) {
|
if (contents == CONTENTS_CLIP) {
|
||||||
if (hullnum <= 0) {
|
if (hullnum <= 0) {
|
||||||
brush_t *brush = LoadBrush(mapbrush, rotate_offset, hullnum);
|
brush_t *brush = LoadBrush(mapbrush, contents, rotate_offset, hullnum);
|
||||||
if (brush) {
|
if (brush) {
|
||||||
AddToBounds(dst, brush->mins);
|
AddToBounds(dst, brush->mins);
|
||||||
AddToBounds(dst, brush->maxs);
|
AddToBounds(dst, brush->maxs);
|
||||||
|
|
@ -1242,12 +1274,11 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
|
||||||
if (hullnum && contents == CONTENTS_SKY)
|
if (hullnum && contents == CONTENTS_SKY)
|
||||||
contents = CONTENTS_SOLID;
|
contents = CONTENTS_SOLID;
|
||||||
|
|
||||||
brush_t *brush = LoadBrush(mapbrush, rotate_offset, hullnum);
|
brush_t *brush = LoadBrush(mapbrush, contents, rotate_offset, hullnum);
|
||||||
if (!brush)
|
if (!brush)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dst->numbrushes++;
|
dst->numbrushes++;
|
||||||
brush->contents = contents;
|
|
||||||
brush->lmshift = lmshift;
|
brush->lmshift = lmshift;
|
||||||
brush->cflags = cflags;
|
brush->cflags = cflags;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ LoadBSPFile(void)
|
||||||
|
|
||||||
switch (header->version) {
|
switch (header->version) {
|
||||||
case BSPVERSION:
|
case BSPVERSION:
|
||||||
|
case BSPHLVERSION:
|
||||||
MemSize = MemSize_BSP29;
|
MemSize = MemSize_BSP29;
|
||||||
break;
|
break;
|
||||||
case BSP2RMQVERSION:
|
case BSP2RMQVERSION:
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ const char *rgszWarnings[cWarnings] = {
|
||||||
"Point (%.3f %.3f %.3f) off plane by %2.4f",
|
"Point (%.3f %.3f %.3f) off plane by %2.4f",
|
||||||
"Couldn't create brush faces",
|
"Couldn't create brush faces",
|
||||||
|
|
||||||
"Reached occupant at (%.0f %.0f %.0f), no filling performed.",
|
"Reached occupant \"%s\" at (%.0f %.0f %.0f), no filling performed.",
|
||||||
"Portal siding direction is wrong",
|
"Portal siding direction is wrong",
|
||||||
"New portal was clipped away in CutNodePortals_r near (%.3f %.3f %.3f)",
|
"New portal was clipped away in CutNodePortals_r near (%.3f %.3f %.3f)",
|
||||||
"Winding outside node",
|
"Winding outside node",
|
||||||
|
|
|
||||||
16
qbsp/map.cc
16
qbsp/map.cc
|
|
@ -204,6 +204,18 @@ IsSkipName(const char *name)
|
||||||
return true;
|
return true;
|
||||||
if (!Q_strcasecmp(name, "*lavaskip"))
|
if (!Q_strcasecmp(name, "*lavaskip"))
|
||||||
return true;
|
return true;
|
||||||
|
if (!Q_strcasecmp(name, "bevel")) //zhlt compat
|
||||||
|
return true;
|
||||||
|
if (!Q_strcasecmp(name, "null")) //zhlt compat
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsNoExpandName(const char *name)
|
||||||
|
{
|
||||||
|
if (!Q_strcasecmp(name, "bevel")) //zhlt compat
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -292,6 +304,8 @@ FindTexinfoEnt(mtexinfo_t *texinfo, const mapentity_t *entity)
|
||||||
flags |= TEX_HINT;
|
flags |= TEX_HINT;
|
||||||
if (IsSpecialName(texname))
|
if (IsSpecialName(texname))
|
||||||
flags |= TEX_SPECIAL;
|
flags |= TEX_SPECIAL;
|
||||||
|
if (IsNoExpandName(texname))
|
||||||
|
flags |= TEX_NOEXPAND;
|
||||||
if (atoi(ValueForKey(entity, "_dirt")) == -1)
|
if (atoi(ValueForKey(entity, "_dirt")) == -1)
|
||||||
flags |= TEX_NODIRT;
|
flags |= TEX_NODIRT;
|
||||||
if (atoi(ValueForKey(entity, "_bounce")) == -1)
|
if (atoi(ValueForKey(entity, "_bounce")) == -1)
|
||||||
|
|
@ -2331,7 +2345,7 @@ TestExpandBrushes(const mapentity_t *src)
|
||||||
|
|
||||||
for (int i = 0; i < src->nummapbrushes; i++) {
|
for (int i = 0; i < src->nummapbrushes; i++) {
|
||||||
const mapbrush_t *mapbrush = &src->mapbrush(i);
|
const mapbrush_t *mapbrush = &src->mapbrush(i);
|
||||||
brush_t *hull1brush = LoadBrush(mapbrush, vec3_origin, 1);
|
brush_t *hull1brush = LoadBrush(mapbrush, CONTENTS_SOLID, vec3_origin, 1);
|
||||||
|
|
||||||
if (hull1brush != nullptr)
|
if (hull1brush != nullptr)
|
||||||
hull1brushes.push_back(hull1brush);
|
hull1brushes.push_back(hull1brush);
|
||||||
|
|
|
||||||
|
|
@ -436,7 +436,7 @@ FillOutside(node_t *node, const int hullnum)
|
||||||
Q_assert(leakentity != nullptr);
|
Q_assert(leakentity != nullptr);
|
||||||
|
|
||||||
const vec_t *origin = leakentity->origin;
|
const vec_t *origin = leakentity->origin;
|
||||||
Message(msgWarning, warnMapLeak, origin[0], origin[1], origin[2]);
|
Message(msgWarning, warnMapLeak, ValueForKey(leakentity, "classname"), origin[0], origin[1], origin[2]);
|
||||||
if (map.leakfile)
|
if (map.leakfile)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
||||||
42
qbsp/qbsp.cc
42
qbsp/qbsp.cc
|
|
@ -567,7 +567,9 @@ CreateHulls(void)
|
||||||
CreateSingleHull(1);
|
CreateSingleHull(1);
|
||||||
CreateSingleHull(2);
|
CreateSingleHull(2);
|
||||||
|
|
||||||
if (options.hexen2)
|
if (options.BSPVersion == BSPHLVERSION)
|
||||||
|
CreateSingleHull(3);
|
||||||
|
else if (options.hexen2)
|
||||||
{ /*note: h2mp doesn't use hull 2 automatically, however gamecode can explicitly set ent.hull=3 to access it*/
|
{ /*note: h2mp doesn't use hull 2 automatically, however gamecode can explicitly set ent.hull=3 to access it*/
|
||||||
CreateSingleHull(3);
|
CreateSingleHull(3);
|
||||||
CreateSingleHull(4);
|
CreateSingleHull(4);
|
||||||
|
|
@ -680,14 +682,16 @@ PrintOptions(void)
|
||||||
" -nooldaxis Uses alternate texture alignment which was default in tyrutils-ericw v0.15.1 and older\n"
|
" -nooldaxis Uses alternate texture alignment which was default in tyrutils-ericw v0.15.1 and older\n"
|
||||||
" -forcegoodtree Force use of expensive processing for SolidBSP stage\n"
|
" -forcegoodtree Force use of expensive processing for SolidBSP stage\n"
|
||||||
" -nopercent Prevents output of percent completion information\n"
|
" -nopercent Prevents output of percent completion information\n"
|
||||||
" -hexen2 Generate a BSP compatible with hexen2 engines\n"
|
|
||||||
" -wrbrushes (bspx) Includes a list of brushes for brush-based collision\n"
|
" -wrbrushes (bspx) Includes a list of brushes for brush-based collision\n"
|
||||||
" -wrbrushesonly -wrbrushes with -noclip\n"
|
" -wrbrushesonly -wrbrushes with -noclip\n"
|
||||||
|
" -hexen2 Generate a BSP compatible with hexen2 engines\n"
|
||||||
|
" -hlbsp Request output in Half-Life bsp format\n"
|
||||||
" -bsp2 Request output in bsp2 format\n"
|
" -bsp2 Request output in bsp2 format\n"
|
||||||
" -2psb Request output in 2psb format (RMQ compatible)\n"
|
" -2psb Request output in 2psb format (RMQ compatible)\n"
|
||||||
" -leakdist [n] Space between leakfile points (default 2)\n"
|
" -leakdist [n] Space between leakfile points (default 2)\n"
|
||||||
" -subdivide [n] Use different texture subdivision (default 240)\n"
|
" -subdivide [n] Use different texture subdivision (default 240)\n"
|
||||||
" -wadpath <dir> Search this directory for wad files\n"
|
" -wadpath <dir> Search this directory for wad files (mips will be embedded unless -notex)\n"
|
||||||
|
" -xwadpath <dir> Search this directory for wad files (mips will NOT be embedded, avoiding texture license issues)\n"
|
||||||
" -oldrottex Use old rotate_ brush texturing aligned at (0 0 0)\n"
|
" -oldrottex Use old rotate_ brush texturing aligned at (0 0 0)\n"
|
||||||
" -maxnodesize [n]Triggers simpler BSP Splitting when node exceeds size (default 1024, 0 to disable)\n"
|
" -maxnodesize [n]Triggers simpler BSP Splitting when node exceeds size (default 1024, 0 to disable)\n"
|
||||||
" -epsilon [n] Customize ON_EPSILON (default 0.0001)\n"
|
" -epsilon [n] Customize ON_EPSILON (default 0.0001)\n"
|
||||||
|
|
@ -825,7 +829,10 @@ ParseOptions(char *szOptions)
|
||||||
options.fbspx_brushes = true;
|
options.fbspx_brushes = true;
|
||||||
options.fNoclip = true;
|
options.fNoclip = true;
|
||||||
}
|
}
|
||||||
else if (!Q_strcasecmp(szTok, "bsp2")) {
|
else if (!Q_strcasecmp(szTok, "hlbsp")) {
|
||||||
|
options.BSPVersion = BSPHLVERSION;
|
||||||
|
MemSize = MemSize_BSP29;
|
||||||
|
} else if (!Q_strcasecmp(szTok, "bsp2")) {
|
||||||
options.BSPVersion = BSP2VERSION;
|
options.BSPVersion = BSP2VERSION;
|
||||||
MemSize = MemSize_BSP2;
|
MemSize = MemSize_BSP2;
|
||||||
} else if (!Q_strcasecmp(szTok, "2psb")) {
|
} else if (!Q_strcasecmp(szTok, "2psb")) {
|
||||||
|
|
@ -843,15 +850,25 @@ ParseOptions(char *szOptions)
|
||||||
Error("Invalid argument to option %s", szTok);
|
Error("Invalid argument to option %s", szTok);
|
||||||
options.dxSubdivide = atoi(szTok2);
|
options.dxSubdivide = atoi(szTok2);
|
||||||
szTok = szTok2;
|
szTok = szTok2;
|
||||||
} else if (!Q_strcasecmp(szTok, "wadpath")) {
|
} else if (!Q_strcasecmp(szTok, "wadpath") || !Q_strcasecmp(szTok, "xwadpath")) {
|
||||||
szTok2 = GetTok(szTok + strlen(szTok) + 1, szEnd);
|
szTok2 = GetTok(szTok + strlen(szTok) + 1, szEnd);
|
||||||
if (!szTok2)
|
if (!szTok2)
|
||||||
Error("Invalid argument to option %s", szTok);
|
Error("Invalid argument to option %s", szTok);
|
||||||
strcpy(options.wadPath, szTok2);
|
int i;
|
||||||
szTok = szTok2;
|
for (i = 0; i < sizeof(options.wadPaths)/sizeof(options.wadPaths[0]); i++)
|
||||||
|
{
|
||||||
|
if (options.wadPaths[i].path)
|
||||||
|
continue;
|
||||||
|
options.wadPaths[i].external = !!Q_strcasecmp(szTok, "wadpath");
|
||||||
|
options.wadPaths[i].path = strdup(szTok2);
|
||||||
/* Remove trailing /, if any */
|
/* Remove trailing /, if any */
|
||||||
if (options.wadPath[strlen(options.wadPath) - 1] == '/')
|
if (options.wadPaths[i].path[strlen(options.wadPaths[i].path) - 1] == '/')
|
||||||
options.wadPath[strlen(options.wadPath) - 1] = 0;
|
options.wadPaths[i].path[strlen(options.wadPaths[i].path) - 1] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == sizeof(options.wadPaths)/sizeof(options.wadPaths[0]))
|
||||||
|
Error("too many -wadpath args");
|
||||||
|
szTok = szTok2;
|
||||||
} else if (!Q_strcasecmp(szTok, "oldrottex")) {
|
} else if (!Q_strcasecmp(szTok, "oldrottex")) {
|
||||||
options.fixRotateObjTexture = false;
|
options.fixRotateObjTexture = false;
|
||||||
} else if (!Q_strcasecmp(szTok, "maxnodesize")) {
|
} else if (!Q_strcasecmp(szTok, "maxnodesize")) {
|
||||||
|
|
@ -990,9 +1007,10 @@ InitQBSP(int argc, const char **argv)
|
||||||
Message(msgFile, IntroString);
|
Message(msgFile, IntroString);
|
||||||
|
|
||||||
/* If no wadpath given, default to the map directory */
|
/* If no wadpath given, default to the map directory */
|
||||||
if (options.wadPath[0] == 0) {
|
if (!options.wadPaths[0].path) {
|
||||||
strcpy(options.wadPath, options.szMapName);
|
options.wadPaths[0].external = false;
|
||||||
StripFilename(options.wadPath);
|
options.wadPaths[0].path = strdup(options.szMapName);
|
||||||
|
StripFilename(options.wadPaths[0].path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove already existing files
|
// Remove already existing files
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,7 @@ GetEdge(mapentity_t *entity, const vec3_t p1, const vec3_t p2,
|
||||||
// search for an existing edge from v2->v1
|
// search for an existing edge from v2->v1
|
||||||
const std::pair<int,int> edge_hash_key = std::make_pair(v2, v1);
|
const std::pair<int,int> edge_hash_key = std::make_pair(v2, v1);
|
||||||
|
|
||||||
if (options.BSPVersion == BSPVERSION) {
|
if (options.BSPVersion == BSPVERSION || options.BSPVersion == BSPHLVERSION) {
|
||||||
bsp29_dedge_t *edge;
|
bsp29_dedge_t *edge;
|
||||||
|
|
||||||
auto it = hashedges.find(edge_hash_key);
|
auto it = hashedges.find(edge_hash_key);
|
||||||
|
|
@ -464,7 +464,7 @@ EmitFace_Internal(mapentity_t *entity, face_t *face)
|
||||||
static void
|
static void
|
||||||
EmitFace(mapentity_t *entity, face_t *face)
|
EmitFace(mapentity_t *entity, face_t *face)
|
||||||
{
|
{
|
||||||
if (options.BSPVersion == BSPVERSION)
|
if (options.BSPVersion == BSPVERSION || options.BSPVersion == BSPHLVERSION)
|
||||||
EmitFace_Internal<bsp29_dface_t>(entity, face);
|
EmitFace_Internal<bsp29_dface_t>(entity, face);
|
||||||
else
|
else
|
||||||
EmitFace_Internal<bsp2_dface_t>(entity, face);
|
EmitFace_Internal<bsp2_dface_t>(entity, face);
|
||||||
|
|
@ -594,7 +594,7 @@ MakeFaceEdges(mapentity_t *entity, node_t *headnode)
|
||||||
edges->count = edges->index;
|
edges->count = edges->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map.cTotal[LUMP_VERTEXES] > 65535 && options.BSPVersion == BSPVERSION)
|
if (map.cTotal[LUMP_VERTEXES] > 65535 && (options.BSPVersion == BSPVERSION || options.BSPVersion == BSPHLVERSION))
|
||||||
Error("Too many vertices (%d > 65535). Recompile with the \"-bsp2\" flag to lift this restriction.", map.cTotal[LUMP_VERTEXES]);
|
Error("Too many vertices (%d > 65535). Recompile with the \"-bsp2\" flag to lift this restriction.", map.cTotal[LUMP_VERTEXES]);
|
||||||
|
|
||||||
surfedges->data = AllocMem(BSP_SURFEDGE, surfedges->count, true);
|
surfedges->data = AllocMem(BSP_SURFEDGE, surfedges->count, true);
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ TEST(qbsp, duplicatePlanes) {
|
||||||
EXPECT_EQ(0, worldspawn.numbrushes);
|
EXPECT_EQ(0, worldspawn.numbrushes);
|
||||||
EXPECT_EQ(6, worldspawn.mapbrush(0).numfaces);
|
EXPECT_EQ(6, worldspawn.mapbrush(0).numfaces);
|
||||||
|
|
||||||
brush_t *brush = LoadBrush(&worldspawn.mapbrush(0), vec3_origin, 0);
|
brush_t *brush = LoadBrush(&worldspawn.mapbrush(0), CONTENTS_SOLID, vec3_origin, 0);
|
||||||
ASSERT_NE(nullptr, brush);
|
ASSERT_NE(nullptr, brush);
|
||||||
EXPECT_EQ(6, Brush_NumFaces(brush));
|
EXPECT_EQ(6, Brush_NumFaces(brush));
|
||||||
FreeBrush(brush);
|
FreeBrush(brush);
|
||||||
|
|
@ -141,7 +141,7 @@ static brush_t *load128x128x32Brush()
|
||||||
mapentity_t worldspawn = LoadMap(map);
|
mapentity_t worldspawn = LoadMap(map);
|
||||||
Q_assert(1 == worldspawn.nummapbrushes);
|
Q_assert(1 == worldspawn.nummapbrushes);
|
||||||
|
|
||||||
brush_t *brush = LoadBrush(&worldspawn.mapbrush(0), vec3_origin, 0);
|
brush_t *brush = LoadBrush(&worldspawn.mapbrush(0), CONTENTS_SOLID, vec3_origin, 0);
|
||||||
Q_assert(nullptr != brush);
|
Q_assert(nullptr != brush);
|
||||||
|
|
||||||
brush->contents = CONTENTS_SOLID;
|
brush->contents = CONTENTS_SOLID;
|
||||||
|
|
|
||||||
115
qbsp/wad.cc
115
qbsp/wad.cc
|
|
@ -31,14 +31,26 @@ static void WADList_AddAnimationFrames(const wad_t *wadlist);
|
||||||
|
|
||||||
static texture_t *textures;
|
static texture_t *textures;
|
||||||
|
|
||||||
|
byte thepalette[768] = // Quake palette
|
||||||
|
{
|
||||||
|
0,0,0,15,15,15,31,31,31,47,47,47,63,63,63,75,75,75,91,91,91,107,107,107,123,123,123,139,139,139,155,155,155,171,171,171,187,187,187,203,203,203,219,219,219,235,235,235,15,11,7,23,15,11,31,23,11,39,27,15,47,35,19,55,43,23,63,47,23,75,55,27,83,59,27,91,67,31,99,75,31,107,83,31,115,87,31,123,95,35,131,103,35,143,111,35,11,11,15,19,19,27,27,27,39,39,39,51,47,47,63,55,55,75,63,63,87,71,71,103,79,79,115,91,91,127,99,99,
|
||||||
|
139,107,107,151,115,115,163,123,123,175,131,131,187,139,139,203,0,0,0,7,7,0,11,11,0,19,19,0,27,27,0,35,35,0,43,43,7,47,47,7,55,55,7,63,63,7,71,71,7,75,75,11,83,83,11,91,91,11,99,99,11,107,107,15,7,0,0,15,0,0,23,0,0,31,0,0,39,0,0,47,0,0,55,0,0,63,0,0,71,0,0,79,0,0,87,0,0,95,0,0,103,0,0,111,0,0,119,0,0,127,0,0,19,19,0,27,27,0,35,35,0,47,43,0,55,47,0,67,
|
||||||
|
55,0,75,59,7,87,67,7,95,71,7,107,75,11,119,83,15,131,87,19,139,91,19,151,95,27,163,99,31,175,103,35,35,19,7,47,23,11,59,31,15,75,35,19,87,43,23,99,47,31,115,55,35,127,59,43,143,67,51,159,79,51,175,99,47,191,119,47,207,143,43,223,171,39,239,203,31,255,243,27,11,7,0,27,19,0,43,35,15,55,43,19,71,51,27,83,55,35,99,63,43,111,71,51,127,83,63,139,95,71,155,107,83,167,123,95,183,135,107,195,147,123,211,163,139,227,179,151,
|
||||||
|
171,139,163,159,127,151,147,115,135,139,103,123,127,91,111,119,83,99,107,75,87,95,63,75,87,55,67,75,47,55,67,39,47,55,31,35,43,23,27,35,19,19,23,11,11,15,7,7,187,115,159,175,107,143,163,95,131,151,87,119,139,79,107,127,75,95,115,67,83,107,59,75,95,51,63,83,43,55,71,35,43,59,31,35,47,23,27,35,19,19,23,11,11,15,7,7,219,195,187,203,179,167,191,163,155,175,151,139,163,135,123,151,123,111,135,111,95,123,99,83,107,87,71,95,75,59,83,63,
|
||||||
|
51,67,51,39,55,43,31,39,31,23,27,19,15,15,11,7,111,131,123,103,123,111,95,115,103,87,107,95,79,99,87,71,91,79,63,83,71,55,75,63,47,67,55,43,59,47,35,51,39,31,43,31,23,35,23,15,27,19,11,19,11,7,11,7,255,243,27,239,223,23,219,203,19,203,183,15,187,167,15,171,151,11,155,131,7,139,115,7,123,99,7,107,83,0,91,71,0,75,55,0,59,43,0,43,31,0,27,15,0,11,7,0,0,0,255,11,11,239,19,19,223,27,27,207,35,35,191,43,
|
||||||
|
43,175,47,47,159,47,47,143,47,47,127,47,47,111,47,47,95,43,43,79,35,35,63,27,27,47,19,19,31,11,11,15,43,0,0,59,0,0,75,7,0,95,7,0,111,15,0,127,23,7,147,31,7,163,39,11,183,51,15,195,75,27,207,99,43,219,127,59,227,151,79,231,171,95,239,191,119,247,211,139,167,123,59,183,155,55,199,195,55,231,227,87,127,191,255,171,231,255,215,255,255,103,0,0,139,0,0,179,0,0,215,0,0,255,0,0,255,243,147,255,247,199,255,255,255,159,91,83
|
||||||
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
WAD_LoadInfo(wad_t *wad)
|
WAD_LoadInfo(wad_t *wad, bool external)
|
||||||
{
|
{
|
||||||
wadinfo_t *hdr = &wad->header;
|
wadinfo_t *hdr = &wad->header;
|
||||||
int i, len, lumpinfosize, disksize;
|
int i, len, lumpinfosize;
|
||||||
dmiptex_t miptex;
|
dmiptex_t miptex;
|
||||||
texture_t *tex;
|
texture_t *tex;
|
||||||
|
|
||||||
|
external |= options.fNoTextures;
|
||||||
|
|
||||||
len = fread(hdr, 1, sizeof(wadinfo_t), wad->file);
|
len = fread(hdr, 1, sizeof(wadinfo_t), wad->file);
|
||||||
if (len != sizeof(wadinfo_t))
|
if (len != sizeof(wadinfo_t))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -62,8 +74,16 @@ WAD_LoadInfo(wad_t *wad)
|
||||||
for (i = 0; i < wad->header.numlumps; i++) {
|
for (i = 0; i < wad->header.numlumps; i++) {
|
||||||
fseek(wad->file, wad->lumps[i].filepos, SEEK_SET);
|
fseek(wad->file, wad->lumps[i].filepos, SEEK_SET);
|
||||||
len = fread(&miptex, 1, sizeof(miptex), wad->file);
|
len = fread(&miptex, 1, sizeof(miptex), wad->file);
|
||||||
|
|
||||||
if (len == sizeof(miptex))
|
if (len == sizeof(miptex))
|
||||||
{
|
{
|
||||||
|
int w = LittleLong(miptex.width);
|
||||||
|
int h = LittleLong(miptex.height);
|
||||||
|
wad->lumps[i].size = sizeof(miptex) + (w>>0)*(h>>0) + (w>>1)*(h>>1) + (w>>2)*(h>>2) + (w>>3)*(h>>3);
|
||||||
|
if (options.BSPVersion == BSPHLVERSION)
|
||||||
|
wad->lumps[i].size += 2+3*256; //palette size+palette data
|
||||||
|
wad->lumps[i].size = (wad->lumps[i].size+3) & ~3; //keep things aligned if we can.
|
||||||
|
|
||||||
tex = (texture_t *)AllocMem(OTHER, sizeof(texture_t), true);
|
tex = (texture_t *)AllocMem(OTHER, sizeof(texture_t), true);
|
||||||
tex->next = textures;
|
tex->next = textures;
|
||||||
textures = tex;
|
textures = tex;
|
||||||
|
|
@ -72,31 +92,20 @@ WAD_LoadInfo(wad_t *wad)
|
||||||
tex->width = miptex.width;
|
tex->width = miptex.width;
|
||||||
tex->height = miptex.height;
|
tex->height = miptex.height;
|
||||||
|
|
||||||
|
//if we're not going to embed it into the bsp, set its size now so we know how much to actually store.
|
||||||
|
if (external)
|
||||||
|
wad->lumps[i].size = wad->lumps[i].disksize = sizeof(dmiptex_t);
|
||||||
|
|
||||||
//printf("Created texture_t %s %d %d\n", tex->name, tex->width, tex->height);
|
//printf("Created texture_t %s %d %d\n", tex->name, tex->width, tex->height);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
wad->lumps[i].size = 0;
|
||||||
if (wad->version == 2)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* WAD3 format includes a palette after the mipmap data.
|
|
||||||
* Reduce the disksize in the lumpinfo so we can treat it like WAD2.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < wad->header.numlumps; i++) {
|
|
||||||
fseek(wad->file, wad->lumps[i].filepos, SEEK_SET);
|
|
||||||
len = fread(&miptex, 1, sizeof(miptex), wad->file);
|
|
||||||
if (len != sizeof(miptex))
|
|
||||||
return false;
|
|
||||||
disksize = sizeof(miptex) + (miptex.width * miptex.height / 64 * 85);
|
|
||||||
if (disksize < wad->lumps[i].disksize)
|
|
||||||
wad->lumps[i].disksize = disksize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
wad_t *WADList_AddWad(const char *fpath, wad_t *current_wadlist)
|
wad_t *WADList_AddWad(const char *fpath, bool external, wad_t *current_wadlist)
|
||||||
{
|
{
|
||||||
wad_t wad = {0};
|
wad_t wad = {0};
|
||||||
|
|
||||||
|
|
@ -104,12 +113,13 @@ wad_t *WADList_AddWad(const char *fpath, wad_t *current_wadlist)
|
||||||
if (wad.file) {
|
if (wad.file) {
|
||||||
if (options.fVerbose)
|
if (options.fVerbose)
|
||||||
Message(msgLiteral, "Opened WAD: %s\n", fpath);
|
Message(msgLiteral, "Opened WAD: %s\n", fpath);
|
||||||
if (WAD_LoadInfo(&wad)) {
|
if (WAD_LoadInfo(&wad, external)) {
|
||||||
wad_t *newwad = (wad_t *)AllocMem(OTHER, sizeof(wad), true);
|
wad_t *newwad = (wad_t *)AllocMem(OTHER, sizeof(wad), true);
|
||||||
memcpy(newwad, &wad, sizeof(wad));
|
memcpy(newwad, &wad, sizeof(wad));
|
||||||
newwad->next = current_wadlist;
|
newwad->next = current_wadlist;
|
||||||
|
|
||||||
// FIXME: leaves file open?
|
// FIXME: leaves file open?
|
||||||
|
// (currently needed so that mips can be loaded later, as needed)
|
||||||
|
|
||||||
return newwad;
|
return newwad;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -141,18 +151,22 @@ WADList_Init(const char *wadstring)
|
||||||
while (*pos && *pos != ';')
|
while (*pos && *pos != ';')
|
||||||
pos++;
|
pos++;
|
||||||
|
|
||||||
if (!options.wadPath[0] || IsAbsolutePath(fname)) {
|
if (!options.wadPaths[0].path || IsAbsolutePath(fname)) {
|
||||||
fpath = (char *)AllocMem(OTHER, (pos - fname) + 1, false);
|
fpath = (char *)AllocMem(OTHER, (pos - fname) + 1, false);
|
||||||
q_snprintf(fpath, (pos - fname) + 1, "%s", fname);
|
q_snprintf(fpath, (pos - fname) + 1, "%s", fname);
|
||||||
|
wadlist = WADList_AddWad(fpath, false, wadlist);
|
||||||
|
FreeMem(fpath, OTHER, strlen(fpath) + 1);
|
||||||
} else {
|
} else {
|
||||||
pathlen = strlen(options.wadPath) + 1 + (pos - fname);
|
for (int i = 0; i < sizeof(options.wadPaths)/sizeof(options.wadPaths[0]) && options.wadPaths[i].path; i++)
|
||||||
|
{
|
||||||
|
pathlen = strlen(options.wadPaths[i].path) + 1 + (pos - fname);
|
||||||
fpath = (char *)AllocMem(OTHER, pathlen + 1, true);
|
fpath = (char *)AllocMem(OTHER, pathlen + 1, true);
|
||||||
q_snprintf(fpath, pathlen + 1, "%s/%s", options.wadPath, fname);
|
q_snprintf(fpath, pathlen + 1, "%s/%s", options.wadPaths[i].path, fname);
|
||||||
|
wadlist = WADList_AddWad(fpath, options.wadPaths[i].external, wadlist);
|
||||||
|
FreeMem(fpath, OTHER, strlen(fpath) + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wadlist = WADList_AddWad(fpath, wadlist);
|
|
||||||
|
|
||||||
FreeMem(fpath, OTHER, strlen(fpath) + 1);
|
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,10 +218,7 @@ WADList_Process(const wad_t *wadlist)
|
||||||
for (i = 0; i < map.nummiptex(); i++) {
|
for (i = 0; i < map.nummiptex(); i++) {
|
||||||
texture = WADList_FindTexture(wadlist, map.miptex.at(i).c_str());
|
texture = WADList_FindTexture(wadlist, map.miptex.at(i).c_str());
|
||||||
if (texture) {
|
if (texture) {
|
||||||
if (options.fNoTextures)
|
texdata->count += texture->size;
|
||||||
texdata->count += sizeof(dmiptex_t);
|
|
||||||
else
|
|
||||||
texdata->count += texture->disksize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,7 +276,7 @@ WAD_LoadLump(const wad_t *wad, const char *name, byte *dest)
|
||||||
for (i = 0; i < wad->header.numlumps; i++) {
|
for (i = 0; i < wad->header.numlumps; i++) {
|
||||||
if (!Q_strcasecmp(name, wad->lumps[i].name)) {
|
if (!Q_strcasecmp(name, wad->lumps[i].name)) {
|
||||||
fseek(wad->file, wad->lumps[i].filepos, SEEK_SET);
|
fseek(wad->file, wad->lumps[i].filepos, SEEK_SET);
|
||||||
if (options.fNoTextures)
|
if (wad->lumps[i].disksize == sizeof(dmiptex_t))
|
||||||
{
|
{
|
||||||
size = fread(dest, 1, sizeof(dmiptex_t), wad->file);
|
size = fread(dest, 1, sizeof(dmiptex_t), wad->file);
|
||||||
if (size != sizeof(dmiptex_t))
|
if (size != sizeof(dmiptex_t))
|
||||||
|
|
@ -274,10 +285,46 @@ WAD_LoadLump(const wad_t *wad, const char *name, byte *dest)
|
||||||
((dmiptex_t*)dest)->offsets[i] = 0;
|
((dmiptex_t*)dest)->offsets[i] = 0;
|
||||||
return sizeof(dmiptex_t);
|
return sizeof(dmiptex_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wad->lumps[i].size != wad->lumps[i].disksize)
|
||||||
|
{
|
||||||
|
logprint("Texture %s is %i bytes in wad, packed to %i bytes in bsp\n", name, wad->lumps[i].disksize, wad->lumps[i].size);
|
||||||
|
std::vector<byte> data(wad->lumps[i].disksize);
|
||||||
|
size = fread(data.data(), 1, wad->lumps[i].disksize, wad->file);
|
||||||
|
if (size != wad->lumps[i].disksize)
|
||||||
|
Error("Failure reading from file");
|
||||||
|
auto out = (dmiptex_t *)dest;
|
||||||
|
auto in = (dmiptex_t *)data.data();
|
||||||
|
*out = *in;
|
||||||
|
out->offsets[0] = sizeof(*out);
|
||||||
|
out->offsets[1] = out->offsets[0] + (in->width>>0)*(in->height>>0);
|
||||||
|
out->offsets[2] = out->offsets[1] + (in->width>>1)*(in->height>>1);
|
||||||
|
out->offsets[3] = out->offsets[2] + (in->width>>2)*(in->height>>2);
|
||||||
|
auto palofs = out->offsets[3] + (in->width>>3)*(in->height>>3);
|
||||||
|
memcpy(dest+out->offsets[0], data.data()+(in->offsets[0]), (in->width>>0)*(in->height>>0));
|
||||||
|
memcpy(dest+out->offsets[1], data.data()+(in->offsets[1]), (in->width>>1)*(in->height>>1));
|
||||||
|
memcpy(dest+out->offsets[2], data.data()+(in->offsets[2]), (in->width>>2)*(in->height>>2));
|
||||||
|
memcpy(dest+out->offsets[3], data.data()+(in->offsets[3]), (in->width>>3)*(in->height>>3));
|
||||||
|
|
||||||
|
if (options.BSPVersion == BSPHLVERSION)
|
||||||
|
{ //palette size. 256 in little endian.
|
||||||
|
dest[palofs+0] = ((256>>0)&0xff);
|
||||||
|
dest[palofs+1] = ((256>>8)&0xff);
|
||||||
|
|
||||||
|
//now the palette
|
||||||
|
if (wad->version == 3)
|
||||||
|
memcpy(dest+palofs+2, data.data()+(in->offsets[3]+(in->width>>3)*(in->height>>3)+2), 3*256);
|
||||||
|
else
|
||||||
|
memcpy(dest+palofs+2, thepalette, 3*256); //FIXME: quake palette or something.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
size = fread(dest, 1, wad->lumps[i].disksize, wad->file);
|
size = fread(dest, 1, wad->lumps[i].disksize, wad->file);
|
||||||
if (size != wad->lumps[i].disksize)
|
if (size != wad->lumps[i].disksize)
|
||||||
Error("Failure reading from file");
|
Error("Failure reading from file");
|
||||||
return wad->lumps[i].disksize;
|
}
|
||||||
|
return wad->lumps[i].size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -292,7 +339,7 @@ WADList_AddAnimationFrames(const wad_t *wadlist)
|
||||||
oldcount = map.nummiptex();
|
oldcount = map.nummiptex();
|
||||||
|
|
||||||
for (i = 0; i < oldcount; i++) {
|
for (i = 0; i < oldcount; i++) {
|
||||||
if (map.miptex.at(i)[0] != '+')
|
if (map.miptex.at(i)[0] != '+' && (options.BSPVersion!=BSPHLVERSION||map.miptex.at(i)[0] != '-'))
|
||||||
continue;
|
continue;
|
||||||
std::string name = map.miptex.at(i);
|
std::string name = map.miptex.at(i);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -298,7 +298,7 @@ ExportClipNodes(mapentity_t *entity, node_t *nodes, const int hullnum)
|
||||||
model->headnode[hullnum] = clipcount + oldcount;
|
model->headnode[hullnum] = clipcount + oldcount;
|
||||||
|
|
||||||
CountClipNodes_r(entity, nodes);
|
CountClipNodes_r(entity, nodes);
|
||||||
if (clipnodes->count > MAX_BSP_CLIPNODES && options.BSPVersion == BSPVERSION)
|
if (clipnodes->count > MAX_BSP_CLIPNODES && (options.BSPVersion == BSPVERSION || options.BSPVersion == BSPHLVERSION))
|
||||||
Error("Clipnode count exceeds bsp 29 max (%d > %d)",
|
Error("Clipnode count exceeds bsp 29 max (%d > %d)",
|
||||||
clipnodes->count, MAX_BSP_CLIPNODES);
|
clipnodes->count, MAX_BSP_CLIPNODES);
|
||||||
|
|
||||||
|
|
@ -313,7 +313,7 @@ ExportClipNodes(mapentity_t *entity, node_t *nodes, const int hullnum)
|
||||||
if (diff != 0) {
|
if (diff != 0) {
|
||||||
for (i = 1; i < hullnum; i++)
|
for (i = 1; i < hullnum; i++)
|
||||||
model->headnode[i] += diff;
|
model->headnode[i] += diff;
|
||||||
if (options.BSPVersion == BSPVERSION) {
|
if (options.BSPVersion == BSPVERSION || options.BSPVersion == BSPHLVERSION) {
|
||||||
bsp29_dclipnode_t *clipnode = (bsp29_dclipnode_t *)clipnodes->data;
|
bsp29_dclipnode_t *clipnode = (bsp29_dclipnode_t *)clipnodes->data;
|
||||||
for (i = 0; i < oldcount; i++, clipnode++) {
|
for (i = 0; i < oldcount; i++, clipnode++) {
|
||||||
if (clipnode->children[0] < MAX_BSP_CLIPNODES)
|
if (clipnode->children[0] < MAX_BSP_CLIPNODES)
|
||||||
|
|
@ -334,7 +334,7 @@ ExportClipNodes(mapentity_t *entity, node_t *nodes, const int hullnum)
|
||||||
}
|
}
|
||||||
|
|
||||||
map.cTotal[LUMP_CLIPNODES] = clipcount + oldcount;
|
map.cTotal[LUMP_CLIPNODES] = clipcount + oldcount;
|
||||||
if (options.BSPVersion == BSPVERSION)
|
if (options.BSPVersion == BSPVERSION || options.BSPVersion == BSPHLVERSION)
|
||||||
ExportClipNodes_BSP29(entity, nodes);
|
ExportClipNodes_BSP29(entity, nodes);
|
||||||
else
|
else
|
||||||
ExportClipNodes_BSP2(entity, nodes);
|
ExportClipNodes_BSP2(entity, nodes);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue