ref_gl1: Load IBSQ map format

This commit is contained in:
Denis Pauk 2023-09-03 13:56:19 +03:00
parent 10e791471e
commit 85ebca9979
5 changed files with 886 additions and 146 deletions

View file

@ -447,6 +447,93 @@ Mod_LoadNodes(const char *name, cplane_t *planes, int numplanes, mleaf_t *leafs,
Mod_NumberLeafs (leafs, *nodes, r_leaftovis, r_vistoleaf, &numvisleafs); Mod_NumberLeafs (leafs, *nodes, r_leaftovis, r_vistoleaf, &numvisleafs);
} }
/*
=================
Mod_LoadQNodes
=================
*/
void
Mod_LoadQNodes(const char *name, cplane_t *planes, int numplanes, mleaf_t *leafs,
int numleafs, mnode_t **nodes, int *numnodes, const byte *mod_base,
const lump_t *l)
{
int r_leaftovis[MAX_MAP_LEAFS], r_vistoleaf[MAX_MAP_LEAFS];
int i, count, numvisleafs;
dqnode_t *in;
mnode_t *out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "%s: funny lump size in %s",
__func__, name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
*nodes = out;
*numnodes = count;
for (i = 0; i < count; i++, in++, out++)
{
int j, planenum;
for (j = 0; j < 3; j++)
{
out->minmaxs[j] = LittleFloat(in->mins[j]);
out->minmaxs[3 + j] = LittleFloat(in->maxs[j]);
}
planenum = LittleLong(in->planenum);
if (planenum < 0 || planenum >= numplanes)
{
ri.Sys_Error(ERR_DROP, "%s: Incorrect %d < %d planenum.",
__func__, planenum, numplanes);
}
out->plane = planes + planenum;
out->firstsurface = LittleLong(in->firstface);
out->numsurfaces = LittleLong(in->numfaces);
out->contents = CONTENTS_NODE; /* differentiate from leafs */
for (j = 0; j < 2; j++)
{
int leafnum;
leafnum = LittleLong(in->children[j]);
if (leafnum >= 0)
{
if (leafnum < 0 || leafnum >= *numnodes)
{
ri.Sys_Error(ERR_DROP, "%s: Incorrect %d nodenum as leaf.",
__func__, leafnum);
}
out->children[j] = *nodes + leafnum;
}
else
{
leafnum = -1 - leafnum;
if (leafnum < 0 || leafnum >= numleafs)
{
ri.Sys_Error(ERR_DROP, "%s: Incorrect %d leafnum.",
__func__, leafnum);
}
out->children[j] = (mnode_t *)(leafs + leafnum);
}
}
}
Mod_SetParent(*nodes, NULL); /* sets nodes and leafs */
numvisleafs = 0;
Mod_NumberLeafs (leafs, *nodes, r_leaftovis, r_vistoleaf, &numvisleafs);
}
/* /*
================= =================
Mod_LoadVisibility Mod_LoadVisibility
@ -657,6 +744,41 @@ Mod_LoadEdges(const char *name, medge_t **edges, int *numedges,
} }
} }
/*
=================
Mod_LoadQEdges
extra is used for skybox, which adds 6 surfaces
=================
*/
void
Mod_LoadQEdges(const char *name, medge_t **edges, int *numedges,
const byte *mod_base, const lump_t *l, int extra)
{
dqedge_t *in;
medge_t *out;
int i, count;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "%s: funny lump size in %s",
__func__, name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc((count + extra) * sizeof(*out));
*edges = out;
*numedges = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
out->v[0] = (unsigned int)LittleLong(in->v[0]);
out->v[1] = (unsigned int)LittleLong(in->v[1]);
}
}
/* /*
================= =================
Mod_LoadPlanes Mod_LoadPlanes

View file

@ -237,6 +237,8 @@ Mod_ForName (char *name, model_t *parent_model, qboolean crash)
break; break;
case IDBSPHEADER: case IDBSPHEADER:
/* fall through */
case QDBSPHEADER:
Mod_LoadBrushModel(mod, buf, modfilelen); Mod_LoadBrushModel(mod, buf, modfilelen);
break; break;
@ -371,7 +373,8 @@ Mod_CalcSurfaceExtents(model_t *loadmodel, msurface_t *s)
} }
} }
static int calcTexinfoAndFacesSize(byte *mod_base, const lump_t *fl, const lump_t *tl) static int
calcTexinfoAndFacesSize(byte *mod_base, const lump_t *fl, const lump_t *tl)
{ {
dface_t* face_in = (void *)(mod_base + fl->fileofs); dface_t* face_in = (void *)(mod_base + fl->fileofs);
texinfo_t* texinfo_in = (void *)(mod_base + tl->fileofs); texinfo_t* texinfo_in = (void *)(mod_base + tl->fileofs);
@ -446,7 +449,83 @@ static int calcTexinfoAndFacesSize(byte *mod_base, const lump_t *fl, const lump_
return ret; return ret;
} }
// Extension to support lightmaps that aren't tied to texture scale. static int
calcTexinfoAndQFacesSize(byte *mod_base, const lump_t *fl, const lump_t *tl)
{
dqface_t* face_in = (void *)(mod_base + fl->fileofs);
texinfo_t* texinfo_in = (void *)(mod_base + tl->fileofs);
if (fl->filelen % sizeof(*face_in) || tl->filelen % sizeof(*texinfo_in))
{
// will error out when actually loading it
return 0;
}
int ret = 0;
int face_count = fl->filelen / sizeof(*face_in);
int texinfo_count = tl->filelen / sizeof(*texinfo_in);
{
// out = Hunk_Alloc(count * sizeof(*out));
int baseSize = face_count * sizeof(msurface_t);
baseSize = (baseSize + 31) & ~31;
ret += baseSize;
int ti_size = texinfo_count * sizeof(mtexinfo_t);
ti_size = (ti_size + 31) & ~31;
ret += ti_size;
}
int numWarpFaces = 0;
for (int surfnum = 0; surfnum < face_count; surfnum++, face_in++)
{
int numverts = LittleLong(face_in->numedges);
int ti = LittleLong(face_in->texinfo);
if ((ti < 0) || (ti >= texinfo_count))
{
return 0; // will error out
}
int texFlags = LittleLong(texinfo_in[ti].flags);
/* set the drawing flags */
if (texFlags & SURF_WARP)
{
if (numverts > 60)
return 0; // will error out in R_SubdividePolygon()
// GL3_SubdivideSurface(out, loadmodel); /* cut up polygon for warps */
// for each (pot. recursive) call to R_SubdividePolygon():
// sizeof(glpoly_t) + ((numverts - 4) + 2) * sizeof(gl3_3D_vtx_t)
// this is tricky, how much is allocated depends on the size of the surface
// which we don't know (we'd need the vertices etc to know, but we can't load
// those without allocating...)
// so we just count warped faces and use a generous estimate below
++numWarpFaces;
}
else
{
// LM_BuildPolygonFromSurface(out);
// => poly = Hunk_Alloc(sizeof(glpoly_t) + (numverts - 4) * VERTEXSIZE * sizeof(float));
int polySize = sizeof(glpoly_t) + (numverts - 4) * VERTEXSIZE * sizeof(float);
polySize = (polySize + 31) & ~31;
ret += polySize;
}
}
// yeah, this is a bit hacky, but it looks like for each warped face
// 256-55000 bytes are allocated (usually on the lower end),
// so just assume 48k per face to be safe
ret += numWarpFaces * 49152;
ret += 5000000; // and 5MB extra just in case
return ret;
}
/* Extension to support lightmaps that aren't tied to texture scale. */
static int static int
Mod_LoadBSPXDecoupledLM(const dlminfo_t* lminfos, int surfnum, msurface_t *out) Mod_LoadBSPXDecoupledLM(const dlminfo_t* lminfos, int surfnum, msurface_t *out)
{ {
@ -632,6 +711,129 @@ Mod_LoadFaces(model_t *loadmodel, const byte *mod_base, const lump_t *l,
LM_EndBuildingLightmaps(); LM_EndBuildingLightmaps();
} }
static void
Mod_LoadQFaces(model_t *loadmodel, const byte *mod_base, const lump_t *l,
const bspx_header_t *bspx_header)
{
int i, count, surfnum, lminfosize, lightofs;
const dlminfo_t *lminfos;
msurface_t *out;
dqface_t *in;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "%s: funny lump size in %s",
__func__, loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->surfaces = out;
loadmodel->numsurfaces = count;
lminfos = Mod_LoadBSPXFindLump(bspx_header, "DECOUPLED_LM", &lminfosize, mod_base);
if (lminfos != NULL && lminfosize / sizeof(dlminfo_t) != loadmodel->numsurfaces) {
R_Printf(PRINT_ALL, "%s: [%s] decoupled_lm size %ld does not match surface count %d\n",
__func__, loadmodel->name, lminfosize / sizeof(dlminfo_t), loadmodel->numsurfaces);
lminfos = NULL;
}
LM_BeginBuildingLightmaps(loadmodel);
for (surfnum = 0; surfnum < count; surfnum++, in++, out++)
{
int side, ti, planenum;
out->firstedge = LittleLong(in->firstedge);
out->numedges = LittleLong(in->numedges);
if (out->numedges < 3)
{
ri.Sys_Error(ERR_DROP, "%s: Surface with %d edges",
__func__, out->numedges);
}
out->flags = 0;
out->polys = NULL;
planenum = LittleLong(in->planenum);
side = LittleLong(in->side);
if (side)
{
out->flags |= SURF_PLANEBACK;
}
if (planenum < 0 || planenum >= loadmodel->numplanes)
{
ri.Sys_Error(ERR_DROP, "%s: Incorrect %d planenum.",
__func__, planenum);
}
out->plane = loadmodel->planes + planenum;
ti = LittleLong(in->texinfo);
if ((ti < 0) || (ti >= loadmodel->numtexinfo))
{
ri.Sys_Error(ERR_DROP, "%s: bad texinfo number",
__func__);
}
out->texinfo = loadmodel->texinfo + ti;
lightofs = Mod_LoadBSPXDecoupledLM(lminfos, surfnum, out);
if (lightofs < 0) {
memcpy(out->lmvecs, out->texinfo->vecs, sizeof(out->lmvecs));
out->lmshift = DEFAULT_LMSHIFT;
out->lmvlen[0] = 1.0f;
out->lmvlen[1] = 1.0f;
Mod_CalcSurfaceExtents(loadmodel, out);
lightofs = in->lightofs;
}
SetSurfaceLighting(loadmodel, out, in->styles, lightofs);
/* set the drawing flags */
if (out->texinfo->flags & SURF_WARP)
{
out->flags |= SURF_DRAWTURB;
for (i = 0; i < 2; i++)
{
out->extents[i] = 16384;
out->texturemins[i] = -8192;
}
R_SubdivideSurface(loadmodel, out); /* cut up polygon for warps */
}
if (r_fixsurfsky->value)
{
if (out->texinfo->flags & SURF_SKY)
{
out->flags |= SURF_DRAWSKY;
}
}
/* create lightmaps and polygons */
if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)))
{
LM_CreateSurfaceLightmap(out);
}
if (!(out->texinfo->flags & SURF_WARP))
{
LM_BuildPolygonFromSurface(loadmodel, out);
}
}
LM_EndBuildingLightmaps();
}
static void static void
Mod_LoadLeafs(model_t *loadmodel, const byte *mod_base, const lump_t *l) Mod_LoadLeafs(model_t *loadmodel, const byte *mod_base, const lump_t *l)
{ {
@ -680,6 +882,54 @@ Mod_LoadLeafs(model_t *loadmodel, const byte *mod_base, const lump_t *l)
} }
} }
static void
Mod_LoadQLeafs(model_t *loadmodel, const byte *mod_base, const lump_t *l)
{
dqleaf_t *in;
mleaf_t *out;
int i, j, count;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "%s: funny lump size in %s",
__func__, loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->leafs = out;
loadmodel->numleafs = count;
for (i = 0; i < count; i++, in++, out++)
{
unsigned firstleafface;
for (j = 0; j < 3; j++)
{
out->minmaxs[j] = LittleFloat(in->mins[j]);
out->minmaxs[3 + j] = LittleFloat(in->maxs[j]);
}
out->contents = LittleLong(in->contents);
out->cluster = LittleLong(in->cluster);
out->area = LittleLong(in->area);
// make unsigned long from signed short
firstleafface = LittleLong(in->firstleafface) & 0xFFFF;
out->nummarksurfaces = LittleLong(in->numleaffaces) & 0xFFFF;
out->firstmarksurface = loadmodel->marksurfaces + firstleafface;
if ((firstleafface + out->nummarksurfaces) > loadmodel->nummarksurfaces)
{
ri.Sys_Error(ERR_DROP, "%s: wrong marksurfaces position in %s",
__func__, loadmodel->name);
}
}
}
static void static void
Mod_LoadMarksurfaces(model_t *loadmodel, const byte *mod_base, const lump_t *l) Mod_LoadMarksurfaces(model_t *loadmodel, const byte *mod_base, const lump_t *l)
{ {
@ -715,6 +965,42 @@ Mod_LoadMarksurfaces(model_t *loadmodel, const byte *mod_base, const lump_t *l)
} }
} }
static void
Mod_LoadQMarksurfaces(model_t *loadmodel, const byte *mod_base, const lump_t *l)
{
int i, count;
int *in;
msurface_t **out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "%s: funny lump size in %s",
__func__, loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->marksurfaces = out;
loadmodel->nummarksurfaces = count;
for (i = 0; i < count; i++)
{
int j;
j = LittleLong(in[i]);
if ((j < 0) || (j >= loadmodel->numsurfaces))
{
ri.Sys_Error(ERR_DROP, "%s: bad surface number",
__func__);
}
out[i] = loadmodel->surfaces + j;
}
}
static void static void
Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen) Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
{ {
@ -730,6 +1016,14 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
header = (dheader_t *)buffer; header = (dheader_t *)buffer;
i = LittleLong(header->ident);
if (i != IDBSPHEADER && i != QDBSPHEADER)
{
ri.Sys_Error(ERR_DROP, "%s: %s has wrong ident (%i should be %i)",
__func__, mod->name, i, IDBSPHEADER);
}
i = LittleLong(header->version); i = LittleLong(header->version);
if (i != BSPVERSION) if (i != BSPVERSION)
@ -749,18 +1043,41 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
// calculate the needed hunksize from the lumps // calculate the needed hunksize from the lumps
int hunkSize = 0; int hunkSize = 0;
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_VERTEXES], sizeof(dvertex_t), sizeof(mvertex_t), 0); hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_VERTEXES], sizeof(dvertex_t), sizeof(mvertex_t), 0);
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_EDGES], sizeof(dedge_t), sizeof(medge_t), 0); if (header->ident == IDBSPHEADER)
{
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_EDGES], sizeof(dedge_t), sizeof(medge_t), 0);
}
else
{
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_EDGES], sizeof(dqedge_t), sizeof(medge_t), 0);
}
hunkSize += sizeof(medge_t) + 31; // for count+1 in Mod_LoadEdges() hunkSize += sizeof(medge_t) + 31; // for count+1 in Mod_LoadEdges()
int surfEdgeCount = (header->lumps[LUMP_SURFEDGES].filelen+sizeof(int)-1)/sizeof(int); int surfEdgeCount = (header->lumps[LUMP_SURFEDGES].filelen+sizeof(int)-1)/sizeof(int);
if(surfEdgeCount < MAX_MAP_SURFEDGES) // else it errors out later anyway if(surfEdgeCount < MAX_MAP_SURFEDGES) // else it errors out later anyway
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_SURFEDGES], sizeof(int), sizeof(int), 0); hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_SURFEDGES], sizeof(int), sizeof(int), 0);
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_LIGHTING], 1, 1, 0); hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_LIGHTING], 1, 1, 0);
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_PLANES], sizeof(dplane_t), sizeof(cplane_t)*2, 0); hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_PLANES], sizeof(dplane_t), sizeof(cplane_t)*2, 0);
hunkSize += calcTexinfoAndFacesSize(mod_base, &header->lumps[LUMP_FACES], &header->lumps[LUMP_TEXINFO]); if (header->ident == IDBSPHEADER)
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_LEAFFACES], sizeof(short), sizeof(msurface_t *), 0); // yes, out is indeed a pointer! {
hunkSize += calcTexinfoAndFacesSize(mod_base, &header->lumps[LUMP_FACES], &header->lumps[LUMP_TEXINFO]);
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_LEAFFACES], sizeof(short), sizeof(msurface_t *), 0); // yes, out is indeed a pointer!
}
else
{
hunkSize += calcTexinfoAndQFacesSize(mod_base, &header->lumps[LUMP_FACES], &header->lumps[LUMP_TEXINFO]);
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_LEAFFACES], sizeof(int), sizeof(msurface_t *), 0); // yes, out is indeed a pointer!
}
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_VISIBILITY], 1, 1, 0); hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_VISIBILITY], 1, 1, 0);
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_LEAFS], sizeof(dleaf_t), sizeof(mleaf_t), 0); if (header->ident == IDBSPHEADER)
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_NODES], sizeof(dnode_t), sizeof(mnode_t), 0); {
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_LEAFS], sizeof(dleaf_t), sizeof(mleaf_t), 0);
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_NODES], sizeof(dnode_t), sizeof(mnode_t), 0);
}
else
{
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_LEAFS], sizeof(dqleaf_t), sizeof(mleaf_t), 0);
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_NODES], sizeof(dqnode_t), sizeof(mnode_t), 0);
}
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_MODELS], sizeof(dmodel_t), sizeof(model_t), 0); hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_MODELS], sizeof(dmodel_t), sizeof(model_t), 0);
mod->extradata = Hunk_Begin(hunkSize); mod->extradata = Hunk_Begin(hunkSize);
@ -773,8 +1090,16 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
/* load into heap */ /* load into heap */
Mod_LoadVertexes(mod->name, &mod->vertexes, &mod->numvertexes, mod_base, Mod_LoadVertexes(mod->name, &mod->vertexes, &mod->numvertexes, mod_base,
&header->lumps[LUMP_VERTEXES], 0); &header->lumps[LUMP_VERTEXES], 0);
Mod_LoadEdges(mod->name, &mod->edges, &mod->numedges, if (header->ident == IDBSPHEADER)
mod_base, &header->lumps[LUMP_EDGES], 1); {
Mod_LoadEdges(mod->name, &mod->edges, &mod->numedges,
mod_base, &header->lumps[LUMP_EDGES], 1);
}
else
{
Mod_LoadQEdges(mod->name, &mod->edges, &mod->numedges,
mod_base, &header->lumps[LUMP_EDGES], 1);
}
Mod_LoadSurfedges(mod->name, &mod->surfedges, &mod->numsurfedges, Mod_LoadSurfedges(mod->name, &mod->surfedges, &mod->numsurfedges,
mod_base, &header->lumps[LUMP_SURFEDGES], 0); mod_base, &header->lumps[LUMP_SURFEDGES], 0);
Mod_LoadLighting(&mod->lightdata, mod_base, &header->lumps[LUMP_LIGHTING]); Mod_LoadLighting(&mod->lightdata, mod_base, &header->lumps[LUMP_LIGHTING]);
@ -783,13 +1108,31 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
Mod_LoadTexinfo(mod->name, &mod->texinfo, &mod->numtexinfo, Mod_LoadTexinfo(mod->name, &mod->texinfo, &mod->numtexinfo,
mod_base, &header->lumps[LUMP_TEXINFO], (findimage_t)R_FindImage, mod_base, &header->lumps[LUMP_TEXINFO], (findimage_t)R_FindImage,
r_notexture, 0); r_notexture, 0);
Mod_LoadFaces(mod, mod_base, &header->lumps[LUMP_FACES], bspx_header); if (header->ident == IDBSPHEADER)
Mod_LoadMarksurfaces(mod, mod_base, &header->lumps[LUMP_LEAFFACES]); {
Mod_LoadFaces(mod, mod_base, &header->lumps[LUMP_FACES], bspx_header);
Mod_LoadMarksurfaces(mod, mod_base, &header->lumps[LUMP_LEAFFACES]);
}
else
{
Mod_LoadQFaces(mod, mod_base, &header->lumps[LUMP_FACES], bspx_header);
Mod_LoadQMarksurfaces(mod, mod_base, &header->lumps[LUMP_LEAFFACES]);
}
Mod_LoadVisibility(&mod->vis, mod_base, &header->lumps[LUMP_VISIBILITY]); Mod_LoadVisibility(&mod->vis, mod_base, &header->lumps[LUMP_VISIBILITY]);
Mod_LoadLeafs(mod, mod_base, &header->lumps[LUMP_LEAFS]); if (header->ident == IDBSPHEADER)
Mod_LoadNodes(mod->name, mod->planes, mod->numplanes, mod->leafs, {
mod->numleafs, &mod->nodes, &mod->numnodes, mod_base, Mod_LoadLeafs(mod, mod_base, &header->lumps[LUMP_LEAFS]);
&header->lumps[LUMP_NODES]); Mod_LoadNodes(mod->name, mod->planes, mod->numplanes, mod->leafs,
mod->numleafs, &mod->nodes, &mod->numnodes, mod_base,
&header->lumps[LUMP_NODES]);
}
else
{
Mod_LoadQLeafs(mod, mod_base, &header->lumps[LUMP_LEAFS]);
Mod_LoadQNodes(mod->name, mod->planes, mod->numplanes, mod->leafs,
mod->numleafs, &mod->nodes, &mod->numnodes, mod_base,
&header->lumps[LUMP_NODES]);
}
Mod_LoadSubmodels (mod, mod_base, &header->lumps[LUMP_MODELS]); Mod_LoadSubmodels (mod, mod_base, &header->lumps[LUMP_MODELS]);
mod->numframes = 2; /* regular and alternate animation */ mod->numframes = 2; /* regular and alternate animation */
} }

View file

@ -125,7 +125,7 @@ typedef struct mvertex_s
typedef struct medge_s typedef struct medge_s
{ {
unsigned short v[2]; unsigned int v[2];
unsigned int cachededgeoffset; unsigned int cachededgeoffset;
} medge_t; } medge_t;
@ -153,8 +153,8 @@ typedef struct mnode_s
cplane_t *plane; cplane_t *plane;
struct mnode_s *children[2]; struct mnode_s *children[2];
unsigned short firstsurface; unsigned int firstsurface;
unsigned short numsurfaces; unsigned int numsurfaces;
} mnode_t; } mnode_t;
typedef struct mleaf_s typedef struct mleaf_s
@ -194,6 +194,9 @@ extern struct image_s* R_LoadImage(const char *name, const char* namewe, const c
extern void Mod_LoadNodes(const char *name, cplane_t *planes, int numplanes, extern void Mod_LoadNodes(const char *name, cplane_t *planes, int numplanes,
mleaf_t *leafs, int numleafs, mnode_t **nodes, int *numnodes, mleaf_t *leafs, int numleafs, mnode_t **nodes, int *numnodes,
const byte *mod_base, const lump_t *l); const byte *mod_base, const lump_t *l);
extern void Mod_LoadQNodes(const char *name, cplane_t *planes, int numplanes,
mleaf_t *leafs, int numleafs, mnode_t **nodes, int *numnodes,
const byte *mod_base, const lump_t *l);
extern void Mod_LoadVertexes(const char *name, mvertex_t **vertexes, int *numvertexes, extern void Mod_LoadVertexes(const char *name, mvertex_t **vertexes, int *numvertexes,
const byte *mod_base, const lump_t *l, int extra); const byte *mod_base, const lump_t *l, int extra);
extern void Mod_LoadVisibility(dvis_t **vis, const byte *mod_base, const lump_t *l); extern void Mod_LoadVisibility(dvis_t **vis, const byte *mod_base, const lump_t *l);
@ -203,6 +206,8 @@ extern void Mod_LoadTexinfo(const char *name, mtexinfo_t **texinfo, int *numtexi
struct image_s *notexture, int extra); struct image_s *notexture, int extra);
extern void Mod_LoadEdges(const char *name, medge_t **edges, int *numedges, extern void Mod_LoadEdges(const char *name, medge_t **edges, int *numedges,
const byte *mod_base, const lump_t *l, int extra); const byte *mod_base, const lump_t *l, int extra);
extern void Mod_LoadQEdges(const char *name, medge_t **edges, int *numedges,
const byte *mod_base, const lump_t *l, int extra);
extern void Mod_LoadPlanes (const char *name, cplane_t **planes, int *numplanes, extern void Mod_LoadPlanes (const char *name, cplane_t **planes, int *numplanes,
const byte *mod_base, const lump_t *l, int extra); const byte *mod_base, const lump_t *l, int extra);
extern void Mod_LoadSurfedges (const char *name, int **surfedges, int *numsurfedges, extern void Mod_LoadSurfedges (const char *name, int **surfedges, int *numsurfedges,

View file

@ -46,8 +46,8 @@ typedef struct
int contents; int contents;
int cluster; int cluster;
int area; int area;
unsigned short firstleafbrush; unsigned int firstleafbrush;
unsigned short numleafbrushes; unsigned int numleafbrushes;
} cleaf_t; } cleaf_t;
typedef struct typedef struct
@ -66,57 +66,57 @@ typedef struct
int floodvalid; int floodvalid;
} carea_t; } carea_t;
byte *cmod_base; static byte *cmod_base;
byte map_visibility[MAX_MAP_VISIBILITY]; static byte map_visibility[MAX_MAP_VISIBILITY];
// DG: is casted to int32_t* in SV_FatPVS() so align accordingly // DG: is casted to int32_t* in SV_FatPVS() so align accordingly
static YQ2_ALIGNAS_TYPE(int32_t) byte pvsrow[MAX_MAP_LEAFS / 8]; static YQ2_ALIGNAS_TYPE(int32_t) byte pvsrow[MAX_MAP_LEAFS / 8];
byte phsrow[MAX_MAP_LEAFS / 8]; static byte phsrow[MAX_MAP_LEAFS / 8];
carea_t map_areas[MAX_MAP_AREAS]; static carea_t map_areas[MAX_MAP_AREAS];
cbrush_t map_brushes[MAX_MAP_BRUSHES]; static cbrush_t map_brushes[MAX_MAP_BRUSHES];
cbrushside_t map_brushsides[MAX_MAP_BRUSHSIDES]; static cbrushside_t map_brushsides[MAX_MAP_BRUSHSIDES];
char map_name[MAX_QPATH]; static char map_name[MAX_QPATH];
char map_entitystring[MAX_MAP_ENTSTRING]; static char map_entitystring[MAX_MAP_ENTSTRING];
cbrush_t *box_brush; static cbrush_t *box_brush;
cleaf_t *box_leaf; static cleaf_t *box_leaf;
cleaf_t map_leafs[MAX_MAP_LEAFS]; static cleaf_t map_leafs[MAX_MAP_LEAFS];
cmodel_t map_cmodels[MAX_MAP_MODELS]; static cmodel_t map_cmodels[MAX_MAP_MODELS];
cnode_t map_nodes[MAX_MAP_NODES+6]; /* extra for box hull */ static cnode_t map_nodes[MAX_MAP_NODES+6]; /* extra for box hull */
cplane_t *box_planes; static cplane_t *box_planes;
cplane_t map_planes[MAX_MAP_PLANES+6]; /* extra for box hull */ static cplane_t map_planes[MAX_MAP_PLANES+6]; /* extra for box hull */
cvar_t *map_noareas; static cvar_t *map_noareas;
dareaportal_t map_areaportals[MAX_MAP_AREAPORTALS]; static dareaportal_t map_areaportals[MAX_MAP_AREAPORTALS];
dvis_t *map_vis = (dvis_t *)map_visibility; static dvis_t *map_vis = (dvis_t *)map_visibility;
int box_headnode; static int box_headnode;
int checkcount; static int checkcount;
int emptyleaf, solidleaf; static int emptyleaf, solidleaf;
int floodvalid; static int floodvalid;
float *leaf_mins, *leaf_maxs; static float *leaf_mins, *leaf_maxs;
int leaf_count, leaf_maxcount; static int leaf_count, leaf_maxcount;
int *leaf_list; static int *leaf_list;
int leaf_topnode; static int leaf_topnode;
int numareaportals; static int numareaportals;
int numareas = 1; static int numareas = 1;
int numbrushes; static int numbrushes;
int numbrushsides; static int numbrushsides;
int numclusters = 1; static int numclusters = 1;
int numcmodels; static int numcmodels;
int numentitychars; static int numentitychars;
int numleafbrushes; static int numleafbrushes;
int numleafs = 1; /* allow leaf funcs to be called without a map */ static int numleafs = 1; /* allow leaf funcs to be called without a map */
int numnodes; static int numnodes;
int numplanes; static int numplanes;
int numtexinfo; int numtexinfo;
int numvisibility; static int numvisibility;
int trace_contents; static int trace_contents;
mapsurface_t map_surfaces[MAX_MAP_TEXINFO]; mapsurface_t map_surfaces[MAX_MAP_TEXINFO];
mapsurface_t nullsurface; static mapsurface_t nullsurface;
qboolean portalopen[MAX_MAP_AREAPORTALS]; static qboolean portalopen[MAX_MAP_AREAPORTALS];
qboolean trace_ispoint; /* optimized case */ static qboolean trace_ispoint; /* optimized case */
trace_t trace_trace; static trace_t trace_trace;
unsigned short map_leafbrushes[MAX_MAP_LEAFBRUSHES]; static unsigned int map_leafbrushes[MAX_MAP_LEAFBRUSHES];
vec3_t trace_start, trace_end; static vec3_t trace_start, trace_end;
vec3_t trace_mins, trace_maxs; static vec3_t trace_mins, trace_maxs;
vec3_t trace_extents; static vec3_t trace_extents;
#ifndef DEDICATED_ONLY #ifndef DEDICATED_ONLY
int c_pointcontents; int c_pointcontents;
@ -126,7 +126,7 @@ int c_traces, c_brush_traces;
/* 1/32 epsilon to keep floating point happy */ /* 1/32 epsilon to keep floating point happy */
#define DIST_EPSILON (0.03125f) #define DIST_EPSILON (0.03125f)
void static void
FloodArea_r(carea_t *area, int floodnum) FloodArea_r(carea_t *area, int floodnum)
{ {
int i; int i;
@ -139,7 +139,7 @@ FloodArea_r(carea_t *area, int floodnum)
return; return;
} }
Com_Error(ERR_DROP, "FloodArea_r: reflooded"); Com_Error(ERR_DROP, "%s: reflooded", __func__);
} }
area->floodnum = floodnum; area->floodnum = floodnum;
@ -155,7 +155,7 @@ FloodArea_r(carea_t *area, int floodnum)
} }
} }
void static void
FloodAreaConnections(void) FloodAreaConnections(void)
{ {
int i; int i;
@ -186,7 +186,7 @@ CM_SetAreaPortalState(int portalnum, qboolean open)
{ {
if (portalnum > numareaportals) if (portalnum > numareaportals)
{ {
Com_Error(ERR_DROP, "areaportal > numareaportals"); Com_Error(ERR_DROP, "%s: areaportal > numareaportals", __func__);
} }
portalopen[portalnum] = open; portalopen[portalnum] = open;
@ -203,7 +203,7 @@ CM_AreasConnected(int area1, int area2)
if ((area1 > numareas) || (area2 > numareas)) if ((area1 > numareas) || (area2 > numareas))
{ {
Com_Error(ERR_DROP, "area > numareas"); Com_Error(ERR_DROP, "%s: area > numareas", __func__);
} }
if (map_areas[area1].floodnum == map_areas[area2].floodnum) if (map_areas[area1].floodnum == map_areas[area2].floodnum)
@ -316,7 +316,7 @@ CM_HeadnodeVisible(int nodenum, byte *visbits)
* Set up the planes and nodes so that the six floats of a bounding box * Set up the planes and nodes so that the six floats of a bounding box
* can just be stored out and get a proper clipping hull structure. * can just be stored out and get a proper clipping hull structure.
*/ */
void static void
CM_InitBoxHull(void) CM_InitBoxHull(void)
{ {
int i; int i;
@ -334,7 +334,7 @@ CM_InitBoxHull(void)
(numbrushsides + 6 > MAX_MAP_BRUSHSIDES) || (numbrushsides + 6 > MAX_MAP_BRUSHSIDES) ||
(numplanes + 12 > MAX_MAP_PLANES)) (numplanes + 12 > MAX_MAP_PLANES))
{ {
Com_Error(ERR_DROP, "Not enough room for box tree"); Com_Error(ERR_DROP, "%s: Not enough room for box tree", __func__);
} }
box_brush = &map_brushes[numbrushes]; box_brush = &map_brushes[numbrushes];
@ -411,7 +411,7 @@ CM_HeadnodeForBox(vec3_t mins, vec3_t maxs)
return box_headnode; return box_headnode;
} }
int static int
CM_PointLeafnum_r(vec3_t p, int num) CM_PointLeafnum_r(vec3_t p, int num)
{ {
float d; float d;
@ -465,8 +465,7 @@ CM_PointLeafnum(vec3_t p)
/* /*
* Fills in a list of all the leafs touched * Fills in a list of all the leafs touched
*/ */
static void
void
CM_BoxLeafnums_r(int nodenum) CM_BoxLeafnums_r(int nodenum)
{ {
cplane_t *plane; cplane_t *plane;
@ -514,7 +513,7 @@ CM_BoxLeafnums_r(int nodenum)
} }
} }
int static int
CM_BoxLeafnums_headnode(vec3_t mins, vec3_t maxs, int *list, CM_BoxLeafnums_headnode(vec3_t mins, vec3_t maxs, int *list,
int listsize, int headnode, int *topnode) int listsize, int headnode, int *topnode)
{ {
@ -591,7 +590,7 @@ CM_TransformedPointContents(vec3_t p, int headnode,
return map_leafs[l].contents; return map_leafs[l].contents;
} }
void static void
CM_ClipBoxToBrush(vec3_t mins, vec3_t maxs, vec3_t p1, CM_ClipBoxToBrush(vec3_t mins, vec3_t maxs, vec3_t p1,
vec3_t p2, trace_t *trace, cbrush_t *brush) vec3_t p2, trace_t *trace, cbrush_t *brush)
{ {
@ -729,7 +728,7 @@ CM_ClipBoxToBrush(vec3_t mins, vec3_t maxs, vec3_t p1,
if (clipplane == NULL) if (clipplane == NULL)
{ {
Com_Error(ERR_FATAL, "clipplane was NULL!\n"); Com_Error(ERR_FATAL, "%s: clipplane was NULL!\n", __func__);
} }
trace->fraction = enterfrac; trace->fraction = enterfrac;
@ -740,7 +739,7 @@ CM_ClipBoxToBrush(vec3_t mins, vec3_t maxs, vec3_t p1,
} }
} }
void static void
CM_TestBoxInBrush(vec3_t mins, vec3_t maxs, vec3_t p1, CM_TestBoxInBrush(vec3_t mins, vec3_t maxs, vec3_t p1,
trace_t *trace, cbrush_t *brush) trace_t *trace, cbrush_t *brush)
{ {
@ -795,7 +794,7 @@ CM_TestBoxInBrush(vec3_t mins, vec3_t maxs, vec3_t p1,
trace->contents = brush->contents; trace->contents = brush->contents;
} }
void static void
CM_TraceToLeaf(int leafnum) CM_TraceToLeaf(int leafnum)
{ {
int k; int k;
@ -838,7 +837,7 @@ CM_TraceToLeaf(int leafnum)
} }
} }
void static void
CM_TestInLeaf(int leafnum) CM_TestInLeaf(int leafnum)
{ {
int k; int k;
@ -880,7 +879,7 @@ CM_TestInLeaf(int leafnum)
} }
} }
void static void
CM_RecursiveHullCheck(int num, float p1f, float p2f, vec3_t p1, vec3_t p2) CM_RecursiveHullCheck(int num, float p1f, float p2f, vec3_t p1, vec3_t p2)
{ {
cnode_t *node; cnode_t *node;
@ -1178,7 +1177,7 @@ CM_TransformedBoxTrace(vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs,
return trace; return trace;
} }
void static void
CMod_LoadSubmodels(lump_t *l) CMod_LoadSubmodels(lump_t *l)
{ {
dmodel_t *in; dmodel_t *in;
@ -1189,19 +1188,19 @@ CMod_LoadSubmodels(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadSubmodels: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size", __func__);
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count < 1) if (count < 1)
{ {
Com_Error(ERR_DROP, "Map with no models"); Com_Error(ERR_DROP, "%s: Map with no models", __func__);
} }
if (count > MAX_MAP_MODELS) if (count > MAX_MAP_MODELS)
{ {
Com_Error(ERR_DROP, "Map has too many models"); Com_Error(ERR_DROP, "%s: Map has too many models", __func__);
} }
numcmodels = count; numcmodels = count;
@ -1222,7 +1221,7 @@ CMod_LoadSubmodels(lump_t *l)
} }
} }
void static void
CMod_LoadSurfaces(lump_t *l) CMod_LoadSurfaces(lump_t *l)
{ {
texinfo_t *in; texinfo_t *in;
@ -1233,19 +1232,19 @@ CMod_LoadSurfaces(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadSurfaces: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size", __func__);
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count < 1) if (count < 1)
{ {
Com_Error(ERR_DROP, "Map with no surfaces"); Com_Error(ERR_DROP, "%s: Map with no surfaces", __func__);
} }
if (count > MAX_MAP_TEXINFO) if (count > MAX_MAP_TEXINFO)
{ {
Com_Error(ERR_DROP, "Map has too many surfaces"); Com_Error(ERR_DROP, "%s: Map has too many surfaces", __func__);
} }
numtexinfo = count; numtexinfo = count;
@ -1260,7 +1259,7 @@ CMod_LoadSurfaces(lump_t *l)
} }
} }
void static void
CMod_LoadNodes(lump_t *l) CMod_LoadNodes(lump_t *l)
{ {
dnode_t *in; dnode_t *in;
@ -1272,19 +1271,19 @@ CMod_LoadNodes(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadNodes: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size %ld", __func__, sizeof(*in));
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count < 1) if (count < 1)
{ {
Com_Error(ERR_DROP, "Map has no nodes"); Com_Error(ERR_DROP, "%s: Map has no nodes", __func__);
} }
if (count > MAX_MAP_NODES) if (count > MAX_MAP_NODES)
{ {
Com_Error(ERR_DROP, "Map has too many nodes"); Com_Error(ERR_DROP, "%s: Map has too many nodes", __func__);
} }
out = map_nodes; out = map_nodes;
@ -1303,7 +1302,50 @@ CMod_LoadNodes(lump_t *l)
} }
} }
void static void
CMod_LoadQNodes(lump_t *l)
{
dqnode_t *in;
int child;
cnode_t *out;
int i, j, count;
in = (void *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Com_Error(ERR_DROP, "%s: funny lump size %ld", __func__, sizeof(*in));
}
count = l->filelen / sizeof(*in);
if (count < 1)
{
Com_Error(ERR_DROP, "%s: Map has no nodes", __func__);
}
if (count > MAX_MAP_NODES)
{
Com_Error(ERR_DROP, "%s: Map has too many nodes", __func__);
}
out = map_nodes;
numnodes = count;
for (i = 0; i < count; i++, out++, in++)
{
out->plane = map_planes + LittleLong(in->planenum);
for (j = 0; j < 2; j++)
{
child = LittleLong(in->children[j]);
out->children[j] = child;
}
}
}
static void
CMod_LoadBrushes(lump_t *l) CMod_LoadBrushes(lump_t *l)
{ {
dbrush_t *in; dbrush_t *in;
@ -1314,14 +1356,14 @@ CMod_LoadBrushes(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadBrushes: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size", __func__);
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count > MAX_MAP_BRUSHES) if (count > MAX_MAP_BRUSHES)
{ {
Com_Error(ERR_DROP, "Map has too many brushes"); Com_Error(ERR_DROP, "%s: Map has too many brushes", __func__);
} }
out = map_brushes; out = map_brushes;
@ -1336,7 +1378,7 @@ CMod_LoadBrushes(lump_t *l)
} }
} }
void static void
CMod_LoadLeafs(lump_t *l) CMod_LoadLeafs(lump_t *l)
{ {
int i; int i;
@ -1348,20 +1390,20 @@ CMod_LoadLeafs(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadLeafs: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size", __func__);
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count < 1) if (count < 1)
{ {
Com_Error(ERR_DROP, "Map with no leafs"); Com_Error(ERR_DROP, "%s: Map with no leafs", __func__);
} }
/* need to save space for box planes */ /* need to save space for box planes */
if (count > MAX_MAP_PLANES) if (count > MAX_MAP_PLANES)
{ {
Com_Error(ERR_DROP, "Map has too many planes"); Com_Error(ERR_DROP, "%s: Map has too many planes", __func__);
} }
out = map_leafs; out = map_leafs;
@ -1384,7 +1426,7 @@ CMod_LoadLeafs(lump_t *l)
if (map_leafs[0].contents != CONTENTS_SOLID) if (map_leafs[0].contents != CONTENTS_SOLID)
{ {
Com_Error(ERR_DROP, "Map leaf 0 is not CONTENTS_SOLID"); Com_Error(ERR_DROP, "%s: Map leaf 0 is not CONTENTS_SOLID", __func__);
} }
solidleaf = 0; solidleaf = 0;
@ -1401,11 +1443,80 @@ CMod_LoadLeafs(lump_t *l)
if (emptyleaf == -1) if (emptyleaf == -1)
{ {
Com_Error(ERR_DROP, "Map does not have an empty leaf"); Com_Error(ERR_DROP, "%s: Map does not have an empty leaf", __func__);
} }
} }
void static void
CMod_LoadQLeafs(lump_t *l)
{
int i;
cleaf_t *out;
dqleaf_t *in;
int count;
in = (void *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Com_Error(ERR_DROP, "%s: funny lump size", __func__);
}
count = l->filelen / sizeof(*in);
if (count < 1)
{
Com_Error(ERR_DROP, "%s: Map with no leafs", __func__);
}
/* need to save space for box planes */
if (count > MAX_MAP_PLANES)
{
Com_Error(ERR_DROP, "%s: Map has too many planes", __func__);
}
out = map_leafs;
numleafs = count;
numclusters = 0;
for (i = 0; i < count; i++, in++, out++)
{
out->contents = LittleLong(in->contents);
out->cluster = LittleLong(in->cluster);
out->area = LittleLong(in->area);
out->firstleafbrush = LittleFloat(in->firstleafbrush);
out->numleafbrushes = LittleFloat(in->numleafbrushes);
if (out->cluster >= numclusters)
{
numclusters = out->cluster + 1;
}
}
if (map_leafs[0].contents != CONTENTS_SOLID)
{
Com_Error(ERR_DROP, "%s: Map leaf 0 is not CONTENTS_SOLID", __func__);
}
solidleaf = 0;
emptyleaf = -1;
for (i = 1; i < numleafs; i++)
{
if (!map_leafs[i].contents)
{
emptyleaf = i;
break;
}
}
if (emptyleaf == -1)
{
Com_Error(ERR_DROP, "%s: Map does not have an empty leaf", __func__);
}
}
static void
CMod_LoadPlanes(lump_t *l) CMod_LoadPlanes(lump_t *l)
{ {
int i, j; int i, j;
@ -1418,20 +1529,20 @@ CMod_LoadPlanes(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadPlanes: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size", __func__);
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count < 1) if (count < 1)
{ {
Com_Error(ERR_DROP, "Map with no planes"); Com_Error(ERR_DROP, "%s: Map with no planes", __func__);
} }
/* need to save space for box planes */ /* need to save space for box planes */
if (count > MAX_MAP_PLANES) if (count > MAX_MAP_PLANES)
{ {
Com_Error(ERR_DROP, "Map has too many planes"); Com_Error(ERR_DROP, "%s: Map has too many planes", __func__);
} }
out = map_planes; out = map_planes;
@ -1457,11 +1568,11 @@ CMod_LoadPlanes(lump_t *l)
} }
} }
void static void
CMod_LoadLeafBrushes(lump_t *l) CMod_LoadLeafBrushes(lump_t *l)
{ {
int i; int i;
unsigned short *out; unsigned int *out;
unsigned short *in; unsigned short *in;
int count; int count;
@ -1469,20 +1580,20 @@ CMod_LoadLeafBrushes(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadLeafBrushes: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size", __func__);
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count < 1) if (count < 1)
{ {
Com_Error(ERR_DROP, "Map with no planes"); Com_Error(ERR_DROP, "%s: Map with no planes", __func__);
} }
/* need to save space for box planes */ /* need to save space for box planes */
if (count > MAX_MAP_LEAFBRUSHES) if (count > MAX_MAP_LEAFBRUSHES)
{ {
Com_Error(ERR_DROP, "Map has too many leafbrushes"); Com_Error(ERR_DROP, "%s: Map has too many leafbrushes", __func__);
} }
out = map_leafbrushes; out = map_leafbrushes;
@ -1494,7 +1605,44 @@ CMod_LoadLeafBrushes(lump_t *l)
} }
} }
void static void
CMod_LoadQLeafBrushes(lump_t *l)
{
int i;
unsigned int *out;
unsigned int *in;
int count;
in = (void *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Com_Error(ERR_DROP, "%s: funny lump size", __func__);
}
count = l->filelen / sizeof(*in);
if (count < 1)
{
Com_Error(ERR_DROP, "%s: Map with no planes", __func__);
}
/* need to save space for box planes */
if (count > MAX_MAP_LEAFBRUSHES)
{
Com_Error(ERR_DROP, "%s: Map has too many leafbrushes", __func__);
}
out = map_leafbrushes;
numleafbrushes = count;
for (i = 0; i < count; i++, in++, out++)
{
*out = LittleLong(*in);
}
}
static void
CMod_LoadBrushSides(lump_t *l) CMod_LoadBrushSides(lump_t *l)
{ {
int i, j; int i, j;
@ -1507,7 +1655,7 @@ CMod_LoadBrushSides(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadBrushSides: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size", __func__);
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
@ -1515,7 +1663,7 @@ CMod_LoadBrushSides(lump_t *l)
/* need to save space for box planes */ /* need to save space for box planes */
if (count > MAX_MAP_BRUSHSIDES) if (count > MAX_MAP_BRUSHSIDES)
{ {
Com_Error(ERR_DROP, "Map has too many planes"); Com_Error(ERR_DROP, "%s: Map has too many planes", __func__);
} }
out = map_brushsides; out = map_brushsides;
@ -1529,14 +1677,55 @@ CMod_LoadBrushSides(lump_t *l)
if (j >= numtexinfo) if (j >= numtexinfo)
{ {
Com_Error(ERR_DROP, "Bad brushside texinfo"); Com_Error(ERR_DROP, "%s: Bad brushside texinfo", __func__);
}
out->surface = (j >= 0) ? &map_surfaces[j] : &nullsurface;
}
}
static void
CMod_LoadQBrushSides(lump_t *l)
{
int i, j;
cbrushside_t *out;
dqbrushside_t *in;
int count;
int num;
in = (void *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Com_Error(ERR_DROP, "%s: funny lump size", __func__);
}
count = l->filelen / sizeof(*in);
/* need to save space for box planes */
if (count > MAX_MAP_BRUSHSIDES)
{
Com_Error(ERR_DROP, "%s: Map has too many planes", __func__);
}
out = map_brushsides;
numbrushsides = count;
for (i = 0; i < count; i++, in++, out++)
{
num = LittleLong(in->planenum);
out->plane = &map_planes[num];
j = LittleLong(in->texinfo);
if (j >= numtexinfo)
{
Com_Error(ERR_DROP, "%s: Bad brushside texinfo", __func__);
} }
out->surface = (j >= 0) ? &map_surfaces[j] : &nullsurface; out->surface = (j >= 0) ? &map_surfaces[j] : &nullsurface;
} }
} }
void static void
CMod_LoadAreas(lump_t *l) CMod_LoadAreas(lump_t *l)
{ {
int i; int i;
@ -1548,14 +1737,14 @@ CMod_LoadAreas(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadAreas: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size", __func__);
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count > MAX_MAP_AREAS) if (count > MAX_MAP_AREAS)
{ {
Com_Error(ERR_DROP, "Map has too many areas"); Com_Error(ERR_DROP, "%s: Map has too many areas", __func__);
} }
out = map_areas; out = map_areas;
@ -1570,7 +1759,7 @@ CMod_LoadAreas(lump_t *l)
} }
} }
void static void
CMod_LoadAreaPortals(lump_t *l) CMod_LoadAreaPortals(lump_t *l)
{ {
dareaportal_t *out; dareaportal_t *out;
@ -1581,14 +1770,14 @@ CMod_LoadAreaPortals(lump_t *l)
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
{ {
Com_Error(ERR_DROP, "Mod_LoadAreaPortals: funny lump size"); Com_Error(ERR_DROP, "%s: funny lump size", __func__);
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count > MAX_MAP_AREAS) if (count > MAX_MAP_AREAS)
{ {
Com_Error(ERR_DROP, "Map has too many areas"); Com_Error(ERR_DROP, "%s: Map has too many areas", __func__);
} }
out = map_areaportals; out = map_areaportals;
@ -1597,14 +1786,14 @@ CMod_LoadAreaPortals(lump_t *l)
memcpy(out, in, sizeof(dareaportal_t) * count); memcpy(out, in, sizeof(dareaportal_t) * count);
} }
void static void
CMod_LoadVisibility(lump_t *l) CMod_LoadVisibility(lump_t *l)
{ {
numvisibility = l->filelen; numvisibility = l->filelen;
if (l->filelen > MAX_MAP_VISIBILITY) if (l->filelen > MAX_MAP_VISIBILITY)
{ {
Com_Error(ERR_DROP, "Map has too large visibility lump"); Com_Error(ERR_DROP, "%s: Map has too large visibility lump", __func__);
} }
memcpy(map_visibility, cmod_base + l->fileofs, l->filelen); memcpy(map_visibility, cmod_base + l->fileofs, l->filelen);
@ -1612,7 +1801,7 @@ CMod_LoadVisibility(lump_t *l)
map_vis->numclusters = LittleLong(map_vis->numclusters); map_vis->numclusters = LittleLong(map_vis->numclusters);
} }
void static void
CMod_LoadEntityString(lump_t *l, char *name) CMod_LoadEntityString(lump_t *l, char *name)
{ {
if (sv_entfile->value) if (sv_entfile->value)
@ -1655,7 +1844,7 @@ CMod_LoadEntityString(lump_t *l, char *name)
if (l->filelen + 1 > sizeof(map_entitystring)) if (l->filelen + 1 > sizeof(map_entitystring))
{ {
Com_Error(ERR_DROP, "Map has too large entity lump"); Com_Error(ERR_DROP, "%s: Map has too large entity lump", __func__);
} }
memcpy(map_entitystring, cmod_base + l->fileofs, l->filelen); memcpy(map_entitystring, cmod_base + l->fileofs, l->filelen);
@ -1713,7 +1902,7 @@ CM_LoadMap(char *name, qboolean clientload, unsigned *checksum)
if (!buf) if (!buf)
{ {
Com_Error(ERR_DROP, "Couldn't load %s", name); Com_Error(ERR_DROP, "%s: Couldn't load %s", name, __func__);
} }
last_checksum = LittleLong(Com_BlockChecksum(buf, length)); last_checksum = LittleLong(Com_BlockChecksum(buf, length));
@ -1726,24 +1915,52 @@ CM_LoadMap(char *name, qboolean clientload, unsigned *checksum)
((int *)&header)[i] = LittleLong(((int *)&header)[i]); ((int *)&header)[i] = LittleLong(((int *)&header)[i]);
} }
if (header.ident != IDBSPHEADER && header.ident != QDBSPHEADER)
{
Com_Error(ERR_DROP, "%s: %s has wrong ident (%i should be %i)",
__func__, name, header.ident, IDBSPHEADER);
}
if (header.version != BSPVERSION) if (header.version != BSPVERSION)
{ {
Com_Error(ERR_DROP, Com_Error(ERR_DROP,
"CMod_LoadBrushModel: %s has wrong version number (%i should be %i)", "%s: %s has wrong version number (%i should be %i)",
name, header.version, BSPVERSION); __func__, name, header.version, BSPVERSION);
} }
cmod_base = (byte *)buf; cmod_base = (byte *)buf;
/* load into heap */ /* load into heap */
CMod_LoadSurfaces(&header.lumps[LUMP_TEXINFO]); CMod_LoadSurfaces(&header.lumps[LUMP_TEXINFO]);
CMod_LoadLeafs(&header.lumps[LUMP_LEAFS]); if (header.ident == IDBSPHEADER)
CMod_LoadLeafBrushes(&header.lumps[LUMP_LEAFBRUSHES]); {
CMod_LoadLeafs(&header.lumps[LUMP_LEAFS]);
CMod_LoadLeafBrushes(&header.lumps[LUMP_LEAFBRUSHES]);
}
else
{
CMod_LoadQLeafs(&header.lumps[LUMP_LEAFS]);
CMod_LoadQLeafBrushes(&header.lumps[LUMP_LEAFBRUSHES]);
}
CMod_LoadPlanes(&header.lumps[LUMP_PLANES]); CMod_LoadPlanes(&header.lumps[LUMP_PLANES]);
CMod_LoadBrushes(&header.lumps[LUMP_BRUSHES]); CMod_LoadBrushes(&header.lumps[LUMP_BRUSHES]);
CMod_LoadBrushSides(&header.lumps[LUMP_BRUSHSIDES]); if (header.ident == IDBSPHEADER)
{
CMod_LoadBrushSides(&header.lumps[LUMP_BRUSHSIDES]);
}
else
{
CMod_LoadQBrushSides(&header.lumps[LUMP_BRUSHSIDES]);
}
CMod_LoadSubmodels(&header.lumps[LUMP_MODELS]); CMod_LoadSubmodels(&header.lumps[LUMP_MODELS]);
CMod_LoadNodes(&header.lumps[LUMP_NODES]); if (header.ident == IDBSPHEADER)
{
CMod_LoadNodes(&header.lumps[LUMP_NODES]);
}
else
{
CMod_LoadQNodes(&header.lumps[LUMP_NODES]);
}
CMod_LoadAreas(&header.lumps[LUMP_AREAS]); CMod_LoadAreas(&header.lumps[LUMP_AREAS]);
CMod_LoadAreaPortals(&header.lumps[LUMP_AREAPORTALS]); CMod_LoadAreaPortals(&header.lumps[LUMP_AREAPORTALS]);
CMod_LoadVisibility(&header.lumps[LUMP_VISIBILITY]); CMod_LoadVisibility(&header.lumps[LUMP_VISIBILITY]);
@ -1769,14 +1986,14 @@ CM_InlineModel(char *name)
if (!name || (name[0] != '*')) if (!name || (name[0] != '*'))
{ {
Com_Error(ERR_DROP, "CM_InlineModel: bad name"); Com_Error(ERR_DROP, "%s: bad name", __func__);
} }
num = (int)strtol(name + 1, (char **)NULL, 10); num = (int)strtol(name + 1, (char **)NULL, 10);
if ((num < 1) || (num >= numcmodels)) if ((num < 1) || (num >= numcmodels))
{ {
Com_Error(ERR_DROP, "CM_InlineModel: bad number"); Com_Error(ERR_DROP, "%s: bad number", __func__);
} }
return &map_cmodels[num]; return &map_cmodels[num];
@ -1805,7 +2022,7 @@ CM_LeafContents(int leafnum)
{ {
if ((leafnum < 0) || (leafnum >= numleafs)) if ((leafnum < 0) || (leafnum >= numleafs))
{ {
Com_Error(ERR_DROP, "CM_LeafContents: bad number"); Com_Error(ERR_DROP, "%s: bad number", __func__);
} }
return map_leafs[leafnum].contents; return map_leafs[leafnum].contents;
@ -1816,7 +2033,7 @@ CM_LeafCluster(int leafnum)
{ {
if ((leafnum < 0) || (leafnum >= numleafs)) if ((leafnum < 0) || (leafnum >= numleafs))
{ {
Com_Error(ERR_DROP, "CM_LeafCluster: bad number"); Com_Error(ERR_DROP, "%s: bad number", __func__);
} }
return map_leafs[leafnum].cluster; return map_leafs[leafnum].cluster;
@ -1827,13 +2044,13 @@ CM_LeafArea(int leafnum)
{ {
if ((leafnum < 0) || (leafnum >= numleafs)) if ((leafnum < 0) || (leafnum >= numleafs))
{ {
Com_Error(ERR_DROP, "CM_LeafArea: bad number"); Com_Error(ERR_DROP, "%s: bad number", __func__);
} }
return map_leafs[leafnum].area; return map_leafs[leafnum].area;
} }
void static void
CM_DecompressVis(byte *in, byte *out) CM_DecompressVis(byte *in, byte *out)
{ {
int c; int c;

View file

@ -232,22 +232,23 @@ typedef struct m32tex_s
/* .BSP file format */ /* .BSP file format */
#define IDBSPHEADER (('P' << 24) + ('S' << 16) + ('B' << 8) + 'I') /* little-endian "IBSP" */ #define IDBSPHEADER (('P' << 24) + ('S' << 16) + ('B' << 8) + 'I') /* little-endian "IBSP" */
#define QDBSPHEADER (('P' << 24) + ('S' << 16) + ('B' << 8) + 'Q') /* little-endian "IBSQ" */
#define BSPXHEADER (('X' << 24) + ('P' << 16) + ('S' << 8) + 'B') /* little-endian "BSPX" */ #define BSPXHEADER (('X' << 24) + ('P' << 16) + ('S' << 8) + 'B') /* little-endian "BSPX" */
#define BSPVERSION 38 #define BSPVERSION 38
/* upper design bounds: leaffaces, leafbrushes, planes, and /* upper design bounds: leaffaces, leafbrushes, planes, and
* verts are still bounded by 16 bit short limits */ * verts are still bounded by 16 bit short limits */
#define MAX_MAP_MODELS 1024 #define MAX_MAP_MODELS 1024
#define MAX_MAP_BRUSHES 8192 #define MAX_MAP_BRUSHES 16384
#define MAX_MAP_ENTITIES 2048 #define MAX_MAP_ENTITIES 2048
#define MAX_MAP_ENTSTRING 0x40000 #define MAX_MAP_ENTSTRING 0x40000
#define MAX_MAP_TEXINFO 8192 #define MAX_MAP_TEXINFO 32768
#define MAX_MAP_AREAS 256 #define MAX_MAP_AREAS 256
#define MAX_MAP_AREAPORTALS 1024 #define MAX_MAP_AREAPORTALS 1024
#define MAX_MAP_PLANES 65536 #define MAX_MAP_PLANES 131072
#define MAX_MAP_NODES 65536 #define MAX_MAP_NODES 65536
#define MAX_MAP_BRUSHSIDES 65536 #define MAX_MAP_BRUSHSIDES 131072
#define MAX_MAP_LEAFS 65536 #define MAX_MAP_LEAFS 65536
#define MAX_MAP_VERTS 65536 #define MAX_MAP_VERTS 65536
#define MAX_MAP_FACES 65536 #define MAX_MAP_FACES 65536
@ -257,7 +258,7 @@ typedef struct m32tex_s
#define MAX_MAP_EDGES 128000 #define MAX_MAP_EDGES 128000
#define MAX_MAP_SURFEDGES 256000 #define MAX_MAP_SURFEDGES 256000
#define MAX_MAP_LIGHTING 0x200000 #define MAX_MAP_LIGHTING 0x200000
#define MAX_MAP_VISIBILITY 0x100000 #define MAX_MAP_VISIBILITY 0x200000
/* key / value pair sizes */ /* key / value pair sizes */
@ -400,6 +401,16 @@ typedef struct
unsigned short numfaces; /* counting both sides */ unsigned short numfaces; /* counting both sides */
} dnode_t; } dnode_t;
typedef struct
{
int planenum;
int children[2]; /* negative numbers are -(leafs+1), not nodes */
float mins[3]; /* for frustom culling */
float maxs[3];
unsigned int firstface;
unsigned int numfaces; /* counting both sides */
} dqnode_t;
typedef struct texinfo_s typedef struct texinfo_s
{ {
float vecs[2][4]; /* [s/t][xyz offset] */ float vecs[2][4]; /* [s/t][xyz offset] */
@ -417,6 +428,11 @@ typedef struct
unsigned short v[2]; /* vertex numbers */ unsigned short v[2]; /* vertex numbers */
} dedge_t; } dedge_t;
typedef struct
{
unsigned int v[2]; /* vertex numbers */
} dqedge_t;
#define MAXLIGHTMAPS 4 #define MAXLIGHTMAPS 4
typedef struct typedef struct
{ {
@ -432,6 +448,20 @@ typedef struct
int lightofs; /* start of [numstyles*surfsize] samples */ int lightofs; /* start of [numstyles*surfsize] samples */
} dface_t; } dface_t;
typedef struct
{
unsigned int planenum;
int side;
int firstedge; /* we must support > 64k edges */
int numedges;
int texinfo;
/* lighting info */
byte styles[MAXLIGHTMAPS];
int lightofs; /* start of [numstyles*surfsize] samples */
} dqface_t;
typedef struct { typedef struct {
unsigned short lmwidth; unsigned short lmwidth;
unsigned short lmheight; unsigned short lmheight;
@ -456,12 +486,35 @@ typedef struct
unsigned short numleafbrushes; unsigned short numleafbrushes;
} dleaf_t; } dleaf_t;
typedef struct
{
int contents; /* OR of all brushes (not needed?) */
int cluster;
int area;
float mins[3]; /* for frustum culling */
float maxs[3];
unsigned int firstleafface;
unsigned int numleaffaces;
unsigned int firstleafbrush;
unsigned int numleafbrushes;
} dqleaf_t;
typedef struct typedef struct
{ {
unsigned short planenum; /* facing out of the leaf */ unsigned short planenum; /* facing out of the leaf */
short texinfo; short texinfo;
} dbrushside_t; } dbrushside_t;
typedef struct
{
unsigned int planenum; /* facing out of the leaf */
int texinfo;
} dqbrushside_t;
typedef struct typedef struct
{ {
int firstside; int firstside;