hexen2 support, patch from Spike

This commit is contained in:
Eric Wasylishen 2015-10-16 15:07:21 -06:00
parent a75de817b1
commit a3b985e721
9 changed files with 224 additions and 32 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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];
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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++) {