From 85ebca99797050ebcef38b7bc33db010ffe354e1 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sun, 3 Sep 2023 13:56:19 +0300 Subject: [PATCH] ref_gl1: Load IBSQ map format --- src/client/refresh/files/models.c | 122 ++++++++ src/client/refresh/gl1/gl1_model.c | 373 ++++++++++++++++++++++- src/client/refresh/ref_shared.h | 11 +- src/common/collision.c | 463 +++++++++++++++++++++-------- src/common/header/files.h | 63 +++- 5 files changed, 886 insertions(+), 146 deletions(-) diff --git a/src/client/refresh/files/models.c b/src/client/refresh/files/models.c index 9d7d644b..167d80bb 100644 --- a/src/client/refresh/files/models.c +++ b/src/client/refresh/files/models.c @@ -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_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 @@ -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 ; iv[0] = (unsigned int)LittleLong(in->v[0]); + out->v[1] = (unsigned int)LittleLong(in->v[1]); + } +} + /* ================= Mod_LoadPlanes diff --git a/src/client/refresh/gl1/gl1_model.c b/src/client/refresh/gl1/gl1_model.c index c280774d..cdf30df9 100644 --- a/src/client/refresh/gl1/gl1_model.c +++ b/src/client/refresh/gl1/gl1_model.c @@ -237,6 +237,8 @@ Mod_ForName (char *name, model_t *parent_model, qboolean crash) break; case IDBSPHEADER: + /* fall through */ + case QDBSPHEADER: Mod_LoadBrushModel(mod, buf, modfilelen); 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); 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; } -// 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 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(); } +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 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 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 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; + 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); if (i != BSPVERSION) @@ -749,18 +1043,41 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen) // calculate the needed hunksize from the lumps int hunkSize = 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() int surfEdgeCount = (header->lumps[LUMP_SURFEDGES].filelen+sizeof(int)-1)/sizeof(int); 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_LIGHTING], 1, 1, 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]); - hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_LEAFFACES], sizeof(short), sizeof(msurface_t *), 0); // yes, out is indeed a pointer! + if (header->ident == IDBSPHEADER) + { + 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_LEAFS], sizeof(dleaf_t), sizeof(mleaf_t), 0); - hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_NODES], sizeof(dnode_t), sizeof(mnode_t), 0); + if (header->ident == IDBSPHEADER) + { + 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); mod->extradata = Hunk_Begin(hunkSize); @@ -773,8 +1090,16 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen) /* load into heap */ Mod_LoadVertexes(mod->name, &mod->vertexes, &mod->numvertexes, mod_base, &header->lumps[LUMP_VERTEXES], 0); - Mod_LoadEdges(mod->name, &mod->edges, &mod->numedges, - mod_base, &header->lumps[LUMP_EDGES], 1); + if (header->ident == IDBSPHEADER) + { + 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_base, &header->lumps[LUMP_SURFEDGES], 0); 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_base, &header->lumps[LUMP_TEXINFO], (findimage_t)R_FindImage, r_notexture, 0); - Mod_LoadFaces(mod, mod_base, &header->lumps[LUMP_FACES], bspx_header); - Mod_LoadMarksurfaces(mod, mod_base, &header->lumps[LUMP_LEAFFACES]); + if (header->ident == IDBSPHEADER) + { + 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_LoadLeafs(mod, mod_base, &header->lumps[LUMP_LEAFS]); - Mod_LoadNodes(mod->name, mod->planes, mod->numplanes, mod->leafs, - mod->numleafs, &mod->nodes, &mod->numnodes, mod_base, - &header->lumps[LUMP_NODES]); + if (header->ident == IDBSPHEADER) + { + Mod_LoadLeafs(mod, mod_base, &header->lumps[LUMP_LEAFS]); + 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->numframes = 2; /* regular and alternate animation */ } diff --git a/src/client/refresh/ref_shared.h b/src/client/refresh/ref_shared.h index c0e0b051..79063178 100644 --- a/src/client/refresh/ref_shared.h +++ b/src/client/refresh/ref_shared.h @@ -125,7 +125,7 @@ typedef struct mvertex_s typedef struct medge_s { - unsigned short v[2]; + unsigned int v[2]; unsigned int cachededgeoffset; } medge_t; @@ -153,8 +153,8 @@ typedef struct mnode_s cplane_t *plane; struct mnode_s *children[2]; - unsigned short firstsurface; - unsigned short numsurfaces; + unsigned int firstsurface; + unsigned int numsurfaces; } mnode_t; 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, mleaf_t *leafs, int numleafs, mnode_t **nodes, int *numnodes, 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, 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); @@ -203,6 +206,8 @@ extern void Mod_LoadTexinfo(const char *name, mtexinfo_t **texinfo, int *numtexi struct image_s *notexture, int extra); extern void Mod_LoadEdges(const char *name, medge_t **edges, int *numedges, 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, const byte *mod_base, const lump_t *l, int extra); extern void Mod_LoadSurfedges (const char *name, int **surfedges, int *numsurfedges, diff --git a/src/common/collision.c b/src/common/collision.c index b2787b7c..a8072e0a 100644 --- a/src/common/collision.c +++ b/src/common/collision.c @@ -46,8 +46,8 @@ typedef struct int contents; int cluster; int area; - unsigned short firstleafbrush; - unsigned short numleafbrushes; + unsigned int firstleafbrush; + unsigned int numleafbrushes; } cleaf_t; typedef struct @@ -66,57 +66,57 @@ typedef struct int floodvalid; } carea_t; -byte *cmod_base; -byte map_visibility[MAX_MAP_VISIBILITY]; +static byte *cmod_base; +static byte map_visibility[MAX_MAP_VISIBILITY]; // DG: is casted to int32_t* in SV_FatPVS() so align accordingly static YQ2_ALIGNAS_TYPE(int32_t) byte pvsrow[MAX_MAP_LEAFS / 8]; -byte phsrow[MAX_MAP_LEAFS / 8]; -carea_t map_areas[MAX_MAP_AREAS]; -cbrush_t map_brushes[MAX_MAP_BRUSHES]; -cbrushside_t map_brushsides[MAX_MAP_BRUSHSIDES]; -char map_name[MAX_QPATH]; -char map_entitystring[MAX_MAP_ENTSTRING]; -cbrush_t *box_brush; -cleaf_t *box_leaf; -cleaf_t map_leafs[MAX_MAP_LEAFS]; -cmodel_t map_cmodels[MAX_MAP_MODELS]; -cnode_t map_nodes[MAX_MAP_NODES+6]; /* extra for box hull */ -cplane_t *box_planes; -cplane_t map_planes[MAX_MAP_PLANES+6]; /* extra for box hull */ -cvar_t *map_noareas; -dareaportal_t map_areaportals[MAX_MAP_AREAPORTALS]; -dvis_t *map_vis = (dvis_t *)map_visibility; -int box_headnode; -int checkcount; -int emptyleaf, solidleaf; -int floodvalid; -float *leaf_mins, *leaf_maxs; -int leaf_count, leaf_maxcount; -int *leaf_list; -int leaf_topnode; -int numareaportals; -int numareas = 1; -int numbrushes; -int numbrushsides; -int numclusters = 1; -int numcmodels; -int numentitychars; -int numleafbrushes; -int numleafs = 1; /* allow leaf funcs to be called without a map */ -int numnodes; -int numplanes; +static byte phsrow[MAX_MAP_LEAFS / 8]; +static carea_t map_areas[MAX_MAP_AREAS]; +static cbrush_t map_brushes[MAX_MAP_BRUSHES]; +static cbrushside_t map_brushsides[MAX_MAP_BRUSHSIDES]; +static char map_name[MAX_QPATH]; +static char map_entitystring[MAX_MAP_ENTSTRING]; +static cbrush_t *box_brush; +static cleaf_t *box_leaf; +static cleaf_t map_leafs[MAX_MAP_LEAFS]; +static cmodel_t map_cmodels[MAX_MAP_MODELS]; +static cnode_t map_nodes[MAX_MAP_NODES+6]; /* extra for box hull */ +static cplane_t *box_planes; +static cplane_t map_planes[MAX_MAP_PLANES+6]; /* extra for box hull */ +static cvar_t *map_noareas; +static dareaportal_t map_areaportals[MAX_MAP_AREAPORTALS]; +static dvis_t *map_vis = (dvis_t *)map_visibility; +static int box_headnode; +static int checkcount; +static int emptyleaf, solidleaf; +static int floodvalid; +static float *leaf_mins, *leaf_maxs; +static int leaf_count, leaf_maxcount; +static int *leaf_list; +static int leaf_topnode; +static int numareaportals; +static int numareas = 1; +static int numbrushes; +static int numbrushsides; +static int numclusters = 1; +static int numcmodels; +static int numentitychars; +static int numleafbrushes; +static int numleafs = 1; /* allow leaf funcs to be called without a map */ +static int numnodes; +static int numplanes; int numtexinfo; -int numvisibility; -int trace_contents; +static int numvisibility; +static int trace_contents; mapsurface_t map_surfaces[MAX_MAP_TEXINFO]; -mapsurface_t nullsurface; -qboolean portalopen[MAX_MAP_AREAPORTALS]; -qboolean trace_ispoint; /* optimized case */ -trace_t trace_trace; -unsigned short map_leafbrushes[MAX_MAP_LEAFBRUSHES]; -vec3_t trace_start, trace_end; -vec3_t trace_mins, trace_maxs; -vec3_t trace_extents; +static mapsurface_t nullsurface; +static qboolean portalopen[MAX_MAP_AREAPORTALS]; +static qboolean trace_ispoint; /* optimized case */ +static trace_t trace_trace; +static unsigned int map_leafbrushes[MAX_MAP_LEAFBRUSHES]; +static vec3_t trace_start, trace_end; +static vec3_t trace_mins, trace_maxs; +static vec3_t trace_extents; #ifndef DEDICATED_ONLY int c_pointcontents; @@ -126,7 +126,7 @@ int c_traces, c_brush_traces; /* 1/32 epsilon to keep floating point happy */ #define DIST_EPSILON (0.03125f) -void +static void FloodArea_r(carea_t *area, int floodnum) { int i; @@ -139,7 +139,7 @@ FloodArea_r(carea_t *area, int floodnum) return; } - Com_Error(ERR_DROP, "FloodArea_r: reflooded"); + Com_Error(ERR_DROP, "%s: reflooded", __func__); } area->floodnum = floodnum; @@ -155,7 +155,7 @@ FloodArea_r(carea_t *area, int floodnum) } } -void +static void FloodAreaConnections(void) { int i; @@ -186,7 +186,7 @@ CM_SetAreaPortalState(int portalnum, qboolean open) { if (portalnum > numareaportals) { - Com_Error(ERR_DROP, "areaportal > numareaportals"); + Com_Error(ERR_DROP, "%s: areaportal > numareaportals", __func__); } portalopen[portalnum] = open; @@ -203,7 +203,7 @@ CM_AreasConnected(int area1, int area2) 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) @@ -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 * can just be stored out and get a proper clipping hull structure. */ -void +static void CM_InitBoxHull(void) { int i; @@ -334,7 +334,7 @@ CM_InitBoxHull(void) (numbrushsides + 6 > MAX_MAP_BRUSHSIDES) || (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]; @@ -411,7 +411,7 @@ CM_HeadnodeForBox(vec3_t mins, vec3_t maxs) return box_headnode; } -int +static int CM_PointLeafnum_r(vec3_t p, int num) { float d; @@ -465,8 +465,7 @@ CM_PointLeafnum(vec3_t p) /* * Fills in a list of all the leafs touched */ - -void +static void CM_BoxLeafnums_r(int nodenum) { 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, int listsize, int headnode, int *topnode) { @@ -591,7 +590,7 @@ CM_TransformedPointContents(vec3_t p, int headnode, return map_leafs[l].contents; } -void +static void CM_ClipBoxToBrush(vec3_t mins, vec3_t maxs, vec3_t p1, 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) { - Com_Error(ERR_FATAL, "clipplane was NULL!\n"); + Com_Error(ERR_FATAL, "%s: clipplane was NULL!\n", __func__); } 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, 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; } -void +static void CM_TraceToLeaf(int leafnum) { int k; @@ -838,7 +837,7 @@ CM_TraceToLeaf(int leafnum) } } -void +static void CM_TestInLeaf(int leafnum) { 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) { cnode_t *node; @@ -1178,7 +1177,7 @@ CM_TransformedBoxTrace(vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, return trace; } -void +static void CMod_LoadSubmodels(lump_t *l) { dmodel_t *in; @@ -1189,19 +1188,19 @@ CMod_LoadSubmodels(lump_t *l) 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); 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) { - Com_Error(ERR_DROP, "Map has too many models"); + Com_Error(ERR_DROP, "%s: Map has too many models", __func__); } numcmodels = count; @@ -1222,7 +1221,7 @@ CMod_LoadSubmodels(lump_t *l) } } -void +static void CMod_LoadSurfaces(lump_t *l) { texinfo_t *in; @@ -1233,19 +1232,19 @@ CMod_LoadSurfaces(lump_t *l) 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); 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) { - Com_Error(ERR_DROP, "Map has too many surfaces"); + Com_Error(ERR_DROP, "%s: Map has too many surfaces", __func__); } numtexinfo = count; @@ -1260,7 +1259,7 @@ CMod_LoadSurfaces(lump_t *l) } } -void +static void CMod_LoadNodes(lump_t *l) { dnode_t *in; @@ -1272,19 +1271,19 @@ CMod_LoadNodes(lump_t *l) 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); 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) { - Com_Error(ERR_DROP, "Map has too many nodes"); + Com_Error(ERR_DROP, "%s: Map has too many nodes", __func__); } 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) { dbrush_t *in; @@ -1314,14 +1356,14 @@ CMod_LoadBrushes(lump_t *l) 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); 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; @@ -1336,7 +1378,7 @@ CMod_LoadBrushes(lump_t *l) } } -void +static void CMod_LoadLeafs(lump_t *l) { int i; @@ -1348,20 +1390,20 @@ CMod_LoadLeafs(lump_t *l) 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); 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 */ 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; @@ -1384,7 +1426,7 @@ CMod_LoadLeafs(lump_t *l) 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; @@ -1401,11 +1443,80 @@ CMod_LoadLeafs(lump_t *l) 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) { int i, j; @@ -1418,20 +1529,20 @@ CMod_LoadPlanes(lump_t *l) 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); 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 */ 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; @@ -1457,11 +1568,11 @@ CMod_LoadPlanes(lump_t *l) } } -void +static void CMod_LoadLeafBrushes(lump_t *l) { int i; - unsigned short *out; + unsigned int *out; unsigned short *in; int count; @@ -1469,20 +1580,20 @@ CMod_LoadLeafBrushes(lump_t *l) 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); 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 */ 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; @@ -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) { int i, j; @@ -1507,7 +1655,7 @@ CMod_LoadBrushSides(lump_t *l) 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); @@ -1515,7 +1663,7 @@ CMod_LoadBrushSides(lump_t *l) /* need to save space for box planes */ 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; @@ -1529,14 +1677,55 @@ CMod_LoadBrushSides(lump_t *l) 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; } } -void +static void CMod_LoadAreas(lump_t *l) { int i; @@ -1548,14 +1737,14 @@ CMod_LoadAreas(lump_t *l) 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); 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; @@ -1570,7 +1759,7 @@ CMod_LoadAreas(lump_t *l) } } -void +static void CMod_LoadAreaPortals(lump_t *l) { dareaportal_t *out; @@ -1581,14 +1770,14 @@ CMod_LoadAreaPortals(lump_t *l) 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); 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; @@ -1597,14 +1786,14 @@ CMod_LoadAreaPortals(lump_t *l) memcpy(out, in, sizeof(dareaportal_t) * count); } -void +static void CMod_LoadVisibility(lump_t *l) { numvisibility = l->filelen; 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); @@ -1612,7 +1801,7 @@ CMod_LoadVisibility(lump_t *l) map_vis->numclusters = LittleLong(map_vis->numclusters); } -void +static void CMod_LoadEntityString(lump_t *l, char *name) { if (sv_entfile->value) @@ -1655,7 +1844,7 @@ CMod_LoadEntityString(lump_t *l, char *name) 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); @@ -1713,7 +1902,7 @@ CM_LoadMap(char *name, qboolean clientload, unsigned *checksum) 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)); @@ -1726,24 +1915,52 @@ CM_LoadMap(char *name, qboolean clientload, unsigned *checksum) ((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) { Com_Error(ERR_DROP, - "CMod_LoadBrushModel: %s has wrong version number (%i should be %i)", - name, header.version, BSPVERSION); + "%s: %s has wrong version number (%i should be %i)", + __func__, name, header.version, BSPVERSION); } cmod_base = (byte *)buf; /* load into heap */ CMod_LoadSurfaces(&header.lumps[LUMP_TEXINFO]); - CMod_LoadLeafs(&header.lumps[LUMP_LEAFS]); - CMod_LoadLeafBrushes(&header.lumps[LUMP_LEAFBRUSHES]); + if (header.ident == IDBSPHEADER) + { + 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_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_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_LoadAreaPortals(&header.lumps[LUMP_AREAPORTALS]); CMod_LoadVisibility(&header.lumps[LUMP_VISIBILITY]); @@ -1769,14 +1986,14 @@ CM_InlineModel(char *name) 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); 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]; @@ -1805,7 +2022,7 @@ CM_LeafContents(int leafnum) { 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; @@ -1816,7 +2033,7 @@ CM_LeafCluster(int leafnum) { 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; @@ -1827,13 +2044,13 @@ CM_LeafArea(int leafnum) { 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; } -void +static void CM_DecompressVis(byte *in, byte *out) { int c; diff --git a/src/common/header/files.h b/src/common/header/files.h index d4fac59c..35bf1386 100644 --- a/src/common/header/files.h +++ b/src/common/header/files.h @@ -232,22 +232,23 @@ typedef struct m32tex_s /* .BSP file format */ #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 BSPVERSION 38 /* upper design bounds: leaffaces, leafbrushes, planes, and * verts are still bounded by 16 bit short limits */ #define MAX_MAP_MODELS 1024 -#define MAX_MAP_BRUSHES 8192 +#define MAX_MAP_BRUSHES 16384 #define MAX_MAP_ENTITIES 2048 #define MAX_MAP_ENTSTRING 0x40000 -#define MAX_MAP_TEXINFO 8192 +#define MAX_MAP_TEXINFO 32768 #define MAX_MAP_AREAS 256 #define MAX_MAP_AREAPORTALS 1024 -#define MAX_MAP_PLANES 65536 +#define MAX_MAP_PLANES 131072 #define MAX_MAP_NODES 65536 -#define MAX_MAP_BRUSHSIDES 65536 +#define MAX_MAP_BRUSHSIDES 131072 #define MAX_MAP_LEAFS 65536 #define MAX_MAP_VERTS 65536 #define MAX_MAP_FACES 65536 @@ -257,7 +258,7 @@ typedef struct m32tex_s #define MAX_MAP_EDGES 128000 #define MAX_MAP_SURFEDGES 256000 #define MAX_MAP_LIGHTING 0x200000 -#define MAX_MAP_VISIBILITY 0x100000 +#define MAX_MAP_VISIBILITY 0x200000 /* key / value pair sizes */ @@ -400,6 +401,16 @@ typedef struct unsigned short numfaces; /* counting both sides */ } 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 { float vecs[2][4]; /* [s/t][xyz offset] */ @@ -417,6 +428,11 @@ typedef struct unsigned short v[2]; /* vertex numbers */ } dedge_t; +typedef struct +{ + unsigned int v[2]; /* vertex numbers */ +} dqedge_t; + #define MAXLIGHTMAPS 4 typedef struct { @@ -432,6 +448,20 @@ typedef struct int lightofs; /* start of [numstyles*surfsize] samples */ } 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 { unsigned short lmwidth; unsigned short lmheight; @@ -456,12 +486,35 @@ typedef struct unsigned short numleafbrushes; } 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 { unsigned short planenum; /* facing out of the leaf */ short texinfo; } dbrushside_t; +typedef struct +{ + unsigned int planenum; /* facing out of the leaf */ + int texinfo; +} dqbrushside_t; + typedef struct { int firstside;