hexen2 support, patch from Spike
This commit is contained in:
parent
a75de817b1
commit
a3b985e721
110
common/bspfile.c
110
common/bspfile.c
|
|
@ -904,6 +904,17 @@ ConvertBSPFormat(int32_t version, bspdata_t *bspdata)
|
|||
BSPVersionString(bspdata->version), BSPVersionString(version));
|
||||
}
|
||||
|
||||
static int
|
||||
isHexen2(const dheader_t *header)
|
||||
{
|
||||
/*
|
||||
the world should always have some face.
|
||||
however, if the sizes are wrong then we're actually reading headnode[6]. hexen2 only used 5 hulls, so this should be 0 in hexen2, and not in quake.
|
||||
*/
|
||||
const dmodelq1_t *modelsq1 = (const dmodelq1_t*)((const byte *)header + header->lumps[LUMP_MODELS].fileofs);
|
||||
return !modelsq1->numfaces;
|
||||
}
|
||||
|
||||
/*
|
||||
* =========================================================================
|
||||
* ...
|
||||
|
|
@ -990,20 +1001,54 @@ CopyLump(const dheader_t *header, int lumpnum, void *destptr)
|
|||
length = header->lumps[lumpnum].filelen;
|
||||
ofs = header->lumps[lumpnum].fileofs;
|
||||
|
||||
if (length % lumpspec->size)
|
||||
Error("%s: odd %s lump size", __func__, lumpspec->name);
|
||||
|
||||
if (buffer)
|
||||
free(buffer);
|
||||
|
||||
buffer = *bufferptr = malloc(length + 1);
|
||||
if (!buffer)
|
||||
Error("%s: allocation of %i bytes failed.", __func__, length);
|
||||
if (lumpnum == LUMP_MODELS && !isHexen2(header))
|
||||
{ /*convert in-place. no need to care about endian here.*/
|
||||
const dmodelq1_t *in = (const dmodelq1_t*)((const byte *)header + ofs);
|
||||
dmodel_t *out;
|
||||
int i, j;
|
||||
if (length % sizeof(dmodelq1_t))
|
||||
Error("%s: odd %s lump size", __func__, lumpspec->name);
|
||||
length /= sizeof(dmodelq1_t);
|
||||
|
||||
memcpy(buffer, (const byte *)header + ofs, length);
|
||||
buffer[length] = 0; /* In case of corrupt entity lump */
|
||||
buffer = *bufferptr = malloc(length * sizeof(dmodel_t));
|
||||
if (!buffer)
|
||||
Error("%s: allocation of %i bytes failed.", __func__, length);
|
||||
out = (dmodel_t*)buffer;
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
out[i].mins[j] = in[i].mins[j];
|
||||
out[i].maxs[j] = in[i].maxs[j];
|
||||
out[i].origin[j] = in[i].origin[j];
|
||||
}
|
||||
for (j = 0; j < MAX_MAP_HULLS_Q1; j++)
|
||||
out[i].headnode[j] = in[i].headnode[j];
|
||||
for ( ; j < MAX_MAP_HULLS_H2; j++)
|
||||
out[i].headnode[j] = 0;
|
||||
out[i].visleafs = in[i].visleafs;
|
||||
out[i].firstface = in[i].firstface;
|
||||
out[i].numfaces = in[i].numfaces;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (length % lumpspec->size)
|
||||
Error("%s: odd %s lump size", __func__, lumpspec->name);
|
||||
|
||||
return length / lumpspec->size;
|
||||
buffer = *bufferptr = malloc(length + 1);
|
||||
if (!buffer)
|
||||
Error("%s: allocation of %i bytes failed.", __func__, length);
|
||||
|
||||
memcpy(buffer, (const byte *)header + ofs, length);
|
||||
buffer[length] = 0; /* In case of corrupt entity lump */
|
||||
|
||||
return length / lumpspec->size;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1032,6 +1077,14 @@ LoadBSPFile(const char *filename, bspdata_t *bspdata)
|
|||
header->lumps[i].filelen = LittleLong(header->lumps[i].filelen);
|
||||
}
|
||||
|
||||
if (isHexen2(header))
|
||||
{
|
||||
logprint("BSP appears to be from hexen2\n");
|
||||
bspdata->hullcount = MAX_MAP_HULLS_H2;
|
||||
}
|
||||
else
|
||||
bspdata->hullcount = MAX_MAP_HULLS_Q1;
|
||||
|
||||
/* copy the data */
|
||||
if (header->version == BSPVERSION) {
|
||||
bsp29_t *bsp = &bspdata->data.bsp29;
|
||||
|
|
@ -1147,6 +1200,39 @@ AddLump(bspfile_t *bspfile, int lumpnum, const void *data, int count)
|
|||
SafeWrite(bspfile->file, pad, size % 4);
|
||||
}
|
||||
|
||||
static void
|
||||
AddModelsLump(bspfile_t *bspfile, bspdata_t *bspdata, const void *data, int count)
|
||||
{
|
||||
if (bspdata->hullcount == MAX_MAP_HULLS_Q1)
|
||||
{ /*convert in-place. no need to care about endian here.*/
|
||||
lump_t *lump = &bspfile->header.lumps[LUMP_MODELS];
|
||||
const dmodel_t *in = data;
|
||||
dmodelq1_t *out = malloc(count * sizeof(dmodelq1_t));
|
||||
int i, j;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
out[i].mins[j] = in[i].mins[j];
|
||||
out[i].maxs[j] = in[i].maxs[j];
|
||||
out[i].origin[j] = in[i].origin[j];
|
||||
}
|
||||
for (j = 0; j < MAX_MAP_HULLS_Q1; j++)
|
||||
out[i].headnode[j] = in[i].headnode[j];
|
||||
out[i].visleafs = in[i].visleafs;
|
||||
out[i].firstface = in[i].firstface;
|
||||
out[i].numfaces = in[i].numfaces;
|
||||
}
|
||||
lump->fileofs = LittleLong(ftell(bspfile->file));
|
||||
lump->filelen = LittleLong(sizeof(dmodelq1_t) * count);
|
||||
SafeWrite(bspfile->file, out, lump->filelen);
|
||||
free(out);
|
||||
return;
|
||||
}
|
||||
else
|
||||
AddLump(bspfile, LUMP_MODELS, data, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* =============
|
||||
* WriteBSPFile
|
||||
|
|
@ -1182,7 +1268,7 @@ WriteBSPFile(const char *filename, bspdata_t *bspdata)
|
|||
AddLump(&bspfile, LUMP_MARKSURFACES, bsp->dmarksurfaces, bsp->nummarksurfaces);
|
||||
AddLump(&bspfile, LUMP_SURFEDGES, bsp->dsurfedges, bsp->numsurfedges);
|
||||
AddLump(&bspfile, LUMP_EDGES, bsp->dedges, bsp->numedges);
|
||||
AddLump(&bspfile, LUMP_MODELS, bsp->dmodels, bsp->nummodels);
|
||||
AddModelsLump(&bspfile, bspdata, bsp->dmodels, bsp->nummodels);
|
||||
|
||||
AddLump(&bspfile, LUMP_LIGHTING, bsp->dlightdata, bsp->lightdatasize);
|
||||
AddLump(&bspfile, LUMP_VISIBILITY, bsp->dvisdata, bsp->visdatasize);
|
||||
|
|
@ -1203,7 +1289,7 @@ WriteBSPFile(const char *filename, bspdata_t *bspdata)
|
|||
AddLump(&bspfile, LUMP_MARKSURFACES, bsp->dmarksurfaces, bsp->nummarksurfaces);
|
||||
AddLump(&bspfile, LUMP_SURFEDGES, bsp->dsurfedges, bsp->numsurfedges);
|
||||
AddLump(&bspfile, LUMP_EDGES, bsp->dedges, bsp->numedges);
|
||||
AddLump(&bspfile, LUMP_MODELS, bsp->dmodels, bsp->nummodels);
|
||||
AddModelsLump(&bspfile, bspdata, bsp->dmodels, bsp->nummodels);
|
||||
|
||||
AddLump(&bspfile, LUMP_LIGHTING, bsp->dlightdata, bsp->lightdatasize);
|
||||
AddLump(&bspfile, LUMP_VISIBILITY, bsp->dvisdata, bsp->visdatasize);
|
||||
|
|
@ -1224,7 +1310,7 @@ WriteBSPFile(const char *filename, bspdata_t *bspdata)
|
|||
AddLump(&bspfile, LUMP_MARKSURFACES, bsp->dmarksurfaces, bsp->nummarksurfaces);
|
||||
AddLump(&bspfile, LUMP_SURFEDGES, bsp->dsurfedges, bsp->numsurfedges);
|
||||
AddLump(&bspfile, LUMP_EDGES, bsp->dedges, bsp->numedges);
|
||||
AddLump(&bspfile, LUMP_MODELS, bsp->dmodels, bsp->nummodels);
|
||||
AddModelsLump(&bspfile, bspdata, bsp->dmodels, bsp->nummodels);
|
||||
|
||||
AddLump(&bspfile, LUMP_LIGHTING, bsp->dlightdata, bsp->lightdatasize);
|
||||
AddLump(&bspfile, LUMP_VISIBILITY, bsp->dvisdata, bsp->visdatasize);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,10 @@
|
|||
|
||||
/* upper design bounds */
|
||||
|
||||
#define MAX_MAP_HULLS 4
|
||||
#define MAX_MAP_HULLS_Q1 4
|
||||
#define MAX_MAP_HULLS_H2 8
|
||||
#define MAX_MAP_HULLS MAX_MAP_HULLS_H2
|
||||
|
||||
#define MAX_MAP_MODELS 256
|
||||
#define MAX_MAP_BRUSHES 4096
|
||||
#define MAX_MAP_PLANES 16384
|
||||
|
|
@ -88,11 +91,21 @@ typedef struct {
|
|||
float mins[3];
|
||||
float maxs[3];
|
||||
float origin[3];
|
||||
int32_t headnode[MAX_MAP_HULLS];
|
||||
int32_t headnode[MAX_MAP_HULLS_Q1];
|
||||
int32_t visleafs; /* not including the solid leaf 0 */
|
||||
int32_t firstface;
|
||||
int32_t numfaces;
|
||||
} dmodel_t;
|
||||
} dmodelq1_t;
|
||||
typedef struct {
|
||||
float mins[3];
|
||||
float maxs[3];
|
||||
float origin[3];
|
||||
int32_t headnode[MAX_MAP_HULLS_H2];
|
||||
int32_t visleafs; /* not including the solid leaf 0 */
|
||||
int32_t firstface;
|
||||
int32_t numfaces;
|
||||
} dmodelh2_t;
|
||||
typedef dmodelh2_t dmodel_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t nummiptex;
|
||||
|
|
@ -418,6 +431,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
int32_t version;
|
||||
int hullcount;
|
||||
union {
|
||||
bsp29_t bsp29;
|
||||
bsp2rmq_t bsp2rmq;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ Switch to the cheap spatial subdivion bsp heuristic when splitting nodes
|
|||
of this size (in any dimension). This gives much faster qbsp processing
|
||||
times on large maps and should generate better bsp trees as well.
|
||||
From txqbsp-xt, thanks rebb. (default 1024, 0 to disable)
|
||||
.IP "\fB\-hexen2\fP"
|
||||
Generate a hexen2 bsp.
|
||||
|
||||
.SH "SPECIAL TEXTURE NAMES"
|
||||
.PP
|
||||
|
|
|
|||
66
qbsp/brush.c
66
qbsp/brush.c
|
|
@ -838,18 +838,64 @@ LoadBrush(const mapbrush_t *mapbrush, const vec3_t rotate_offset,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (hullnum == 1) {
|
||||
vec3_t size[2] = { {-16, -16, -32}, {16, 16, 24} };
|
||||
if (options.hexen2)
|
||||
{
|
||||
if (hullnum == 1) {
|
||||
vec3_t size[2] = { {-16, -16, -32}, {16, 16, 24} };
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
}
|
||||
else if (hullnum == 2) {
|
||||
vec3_t size[2] = { {-24, -24, -20}, {24, 24, 20} };
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
}
|
||||
else if (hullnum == 3) {
|
||||
vec3_t size[2] = { {-16, -16, -12}, {16, 16, 16} };
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
}
|
||||
else if (hullnum == 4) {
|
||||
#if 0
|
||||
if (options.hexen2 == 1) { /*original game*/
|
||||
vec3_t size[2] = { {-40, -40, -42}, {40, 40, 42} };
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
} else
|
||||
#endif
|
||||
{ /*mission pack*/
|
||||
vec3_t size[2] = { {-8, -8, -8}, {8, 8, 8} };
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
}
|
||||
}
|
||||
else if (hullnum == 5) {
|
||||
vec3_t size[2] = { {-48, -48, -50}, {48, 48, 50} };
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hullnum == 1) {
|
||||
vec3_t size[2] = { {-16, -16, -32}, {16, 16, 24} };
|
||||
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
} else if (hullnum == 2) {
|
||||
vec3_t size[2] = { {-32, -32, -64}, {32, 32, 24} };
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
} else if (hullnum == 2) {
|
||||
vec3_t size[2] = { {-32, -32, -64}, {32, 32, 24} };
|
||||
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
ExpandBrush(&hullbrush, size, facelist);
|
||||
FreeBrushFaces(facelist);
|
||||
facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
|
||||
}
|
||||
}
|
||||
|
||||
// create the brush
|
||||
|
|
|
|||
|
|
@ -96,10 +96,33 @@ AddLump(FILE *f, int Type)
|
|||
for (i = 0, entity = map.entities; i < map.numentities; i++, entity++) {
|
||||
entities = &entity->lumps[Type];
|
||||
if (entities->data) {
|
||||
ret = fwrite(entities->data, MemSize[Type], entities->count, f);
|
||||
if (ret != entities->count)
|
||||
Error("Failure writing to file");
|
||||
cLen += entities->count * MemSize[Type];
|
||||
if (Type == LUMP_MODELS && !options.hexen2) {
|
||||
const dmodel_t *in = entities->data;
|
||||
dmodelq1_t out;
|
||||
int j, k;
|
||||
for (j = 0; j < entities->count; j++)
|
||||
{
|
||||
for (k = 0; k < 3; k++) {
|
||||
out.mins[k] = in[j].mins[k];
|
||||
out.maxs[k] = in[j].maxs[k];
|
||||
out.origin[k] = in[j].origin[k];
|
||||
}
|
||||
for (k = 0; k < MAX_MAP_HULLS_Q1; k++)
|
||||
out.headnode[k] = in[j].headnode[k];
|
||||
out.visleafs = in[j].visleafs;
|
||||
out.firstface = in[j].firstface;
|
||||
out.numfaces = in[j].numfaces;
|
||||
ret = fwrite(&out, sizeof(out), 1, f);
|
||||
if (ret != 1)
|
||||
Error("Failure writing to file");
|
||||
}
|
||||
cLen += entities->count * sizeof(out);
|
||||
} else {
|
||||
ret = fwrite(entities->data, MemSize[Type], entities->count, f);
|
||||
if (ret != entities->count)
|
||||
Error("Failure writing to file");
|
||||
cLen += entities->count * MemSize[Type];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,12 +56,22 @@ typedef struct {
|
|||
#define BSP_LUMPS 15
|
||||
|
||||
typedef struct {
|
||||
#define MAX_MAP_HULLS_Q1 4
|
||||
float mins[3], maxs[3];
|
||||
float origin[3];
|
||||
int32_t headnode[4]; /* 4 for backward compat, only 3 hulls exist */
|
||||
int32_t headnode[MAX_MAP_HULLS_Q1]; /* 4 for backward compat, only 3 hulls exist */
|
||||
int32_t visleafs; /* not including the solid leaf 0 */
|
||||
int32_t firstface, numfaces;
|
||||
} dmodel_t;
|
||||
} dmodelq1_t;
|
||||
typedef struct {
|
||||
#define MAX_MAP_HULLS_H2 8
|
||||
float mins[3], maxs[3];
|
||||
float origin[3];
|
||||
int32_t headnode[MAX_MAP_HULLS_H2]; /* hexen2 only uses 6 */
|
||||
int32_t visleafs; /* not including the solid leaf 0 */
|
||||
int32_t firstface, numfaces;
|
||||
} dmodelh2_t;
|
||||
typedef dmodelh2_t dmodel_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t version;
|
||||
|
|
|
|||
|
|
@ -289,6 +289,13 @@ CreateHulls(void)
|
|||
|
||||
CreateSingleHull(1);
|
||||
CreateSingleHull(2);
|
||||
|
||||
if (options.hexen2)
|
||||
{ /*note: h2mp doesn't use hull 2 automatically, however gamecode can explicitly set ent.hull=3 to access it*/
|
||||
CreateSingleHull(3);
|
||||
CreateSingleHull(4);
|
||||
CreateSingleHull(5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -504,6 +511,8 @@ ParseOptions(char *szOptions)
|
|||
options.fOldleak = true;
|
||||
else if (!strcasecmp(szTok, "nopercent"))
|
||||
options.fNopercent = true;
|
||||
else if (!strcasecmp(szTok, "hexen2"))
|
||||
options.hexen2 = true;
|
||||
else if (!strcasecmp(szTok, "bsp2")) {
|
||||
options.BSPVersion = BSP2VERSION;
|
||||
MemSize = MemSize_BSP2;
|
||||
|
|
|
|||
|
|
@ -448,6 +448,7 @@ typedef struct options_s {
|
|||
bool fNopercent;
|
||||
bool forceGoodTree;
|
||||
bool fixRotateObjTexture;
|
||||
int hexen2;/*2 if the worldspawn mission pack flag was set*/
|
||||
int BSPVersion;
|
||||
int dxSubdivide;
|
||||
int dxLeakDist;
|
||||
|
|
|
|||
|
|
@ -235,7 +235,8 @@ ExportClipNodes(mapentity_t *entity, node_t *nodes, const int hullnum)
|
|||
/* Worth special-casing for entity 0 (no modification needed) */
|
||||
diff = clipcount - model->headnode[1];
|
||||
if (diff != 0) {
|
||||
model->headnode[1] += diff;
|
||||
for (i = 1; i < hullnum; i++)
|
||||
model->headnode[i] += diff;
|
||||
if (options.BSPVersion == BSPVERSION) {
|
||||
bsp29_dclipnode_t *clipnode = clipnodes->data;
|
||||
for (i = 0; i < oldcount; i++, clipnode++) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue