Clean up bsp limits.

Delete all bogus bsp limits, fixing the code that depended on them.
Document those limits that are dictated by the format.
This commit is contained in:
Bill Currie 2010-12-07 15:41:57 +09:00
parent 0bd960d6cc
commit a0828ddd06
9 changed files with 98 additions and 94 deletions

View file

@ -33,35 +33,15 @@
// upper design bounds // upper design bounds
#define MAX_MAP_HULLS 4 #define MAX_MAP_HULLS 4 // format limit (array)
#define MAX_MAP_MODELS 256
#define MAX_MAP_BRUSHES 4096
#define MAX_MAP_ENTITIES 1024
#define MAX_MAP_ENTSTRING 65536
#define MAX_MAP_PLANES 32767
#define MAX_MAP_NODES 32767 // because negative shorts are contents
#define MAX_MAP_CLIPNODES 32767 //
#define MAX_MAP_LEAFS 32767 //
#define MAX_MAP_VERTS 65535
#define MAX_MAP_FACES 65535
#define MAX_MAP_MARKSURFACES 65535
#define MAX_MAP_TEXINFO 4096
#define MAX_MAP_EDGES 256000
#define MAX_MAP_SURFEDGES 512000
#define MAX_MAP_TEXTURES 512
#define MAX_MAP_MIPTEX 0x200000
#define MAX_MAP_LIGHTING 0x100000
#define MAX_MAP_VISIBILITY 0x100000
#define MAX_MAP_PORTALS 65536
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
#define MAX_MAP_PLANES 32767 // format limit (s16) FIXME u16 ok?
#define MAX_MAP_NODES 65520 // because negative shorts are contents
#define MAX_MAP_CLIPNODES 65520 // but contents "max" is -15, so
#define MAX_MAP_LEAFS 65520 // -32768 to -17 are available
#define MAX_MAP_VERTS 65535 // format limit (u16)
#define MAX_MAP_FACES 65535 // format limit (u16)
#define MAX_MAP_MARKSURFACES 65535 // format limit (u16)
//============================================================================= //=============================================================================
@ -109,9 +89,10 @@ typedef struct dmiptexlump_s {
int32_t dataofs[4]; // [nummiptex] int32_t dataofs[4]; // [nummiptex]
} dmiptexlump_t; } dmiptexlump_t;
#define MIPTEXNAME 16
#define MIPLEVELS 4 #define MIPLEVELS 4
typedef struct miptex_s { typedef struct miptex_s {
char name[16]; char name[MIPTEXNAME];
uint32_t width, height; uint32_t width, height;
uint32_t offsets[MIPLEVELS]; // four mip maps stored uint32_t offsets[MIPLEVELS]; // four mip maps stored
} miptex_t; } miptex_t;

View file

@ -57,18 +57,15 @@ typedef struct {
epair_t *epairs; ///< Nul terminated list of key=value pairs. epair_t *epairs; ///< Nul terminated list of key=value pairs.
} entity_t; } entity_t;
extern int nummapbrushes;
extern mbrush_t mapbrushes[MAX_MAP_BRUSHES];
extern int num_entities; extern int num_entities;
extern entity_t entities[MAX_MAP_ENTITIES]; extern entity_t *entities;
extern int nummiptex; extern int nummiptexnames;
extern char miptex[MAX_MAP_TEXINFO][16]; extern const char **miptexnames;
/** Load and parse the map script. /** Load and parse the map script.
Fills in the ::mapbrushes, ::entities and ::miptex arrays. Fills in the ::entities and ::miptexnames arrays.
\param filename Path of the map script to parse. \param filename Path of the map script to parse.
*/ */

View file

@ -34,9 +34,13 @@ struct visfacet_s;
struct node_s; struct node_s;
struct surface_s; struct surface_s;
typedef struct edgeface_s {
struct visfacet_s *f[2];
} edgeface_t;
extern int c_cornerverts; extern int c_cornerverts;
extern int c_tryedges; extern int c_tryedges;
extern struct visfacet_s *edgefaces[MAX_MAP_EDGES][2]; extern edgeface_t *edgefaces;
extern int firstmodeledge; extern int firstmodeledge;
extern int firstmodelface; extern int firstmodelface;

View file

@ -694,7 +694,7 @@ LoadBrush (const mbrush_t *mb, int hullnum)
return NULL; return NULL;
contents = CONTENTS_EMPTY; contents = CONTENTS_EMPTY;
} else { } else {
name = miptex[bsp->texinfo[mb->faces->texinfo].miptex]; name = miptexnames[bsp->texinfo[mb->faces->texinfo].miptex];
if (!strcasecmp (name, "clip") && hullnum == 0) if (!strcasecmp (name, "clip") && hullnum == 0)
return NULL; // "clip" brushes don't show up in the draw hull return NULL; // "clip" brushes don't show up in the draw hull

View file

@ -35,6 +35,7 @@ static __attribute__ ((used)) const char rcsid[] =
#include <ctype.h> #include <ctype.h>
#include "QF/dstring.h" #include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/quakefs.h" #include "QF/quakefs.h"
#include "QF/script.h" #include "QF/script.h"
#include "QF/sys.h" #include "QF/sys.h"
@ -50,13 +51,17 @@ static __attribute__ ((used)) const char rcsid[] =
int nummapbrushfaces; int nummapbrushfaces;
int nummapbrushes; int nummapbrushes;
mbrush_t mapbrushes[MAX_MAP_BRUSHES];
#define ENTITIES_CHUNK 16
int num_entities; int num_entities;
entity_t entities[MAX_MAP_ENTITIES]; int max_entities;
entity_t *entities;
int nummiptex; #define MIPTEXNAME_CHUNK 16
char miptex[MAX_MAP_TEXINFO][16]; int nummiptexnames;
int maxmiptexnames;
const char **miptexnames;
hashtab_t *miptex_hash;
int numdetailbrushes; int numdetailbrushes;
@ -75,24 +80,41 @@ map_error (const char *fmt, ...)
exit (1); exit (1);
} }
static const char *
miptex_getkey (void *key, void *unused)
{
intptr_t index = (intptr_t) key;
return miptexnames[index - 1];
}
int int
FindMiptex (const char *name) FindMiptex (const char *name)
{ {
int i; intptr_t index;
char mpname[MIPTEXNAME];
strncpy (mpname, name, MIPTEXNAME - 1);
mpname[MIPTEXNAME - 1] = 0;
if (strcmp (name, "hint") == 0) if (strcmp (name, "hint") == 0)
return TEX_HINT; return TEX_HINT;
if (strcmp (name, "skip") == 0) if (strcmp (name, "skip") == 0)
return TEX_SKIP; return TEX_SKIP;
for (i = 0; i < nummiptex; i++) { if (!miptex_hash)
if (!strcmp (name, miptex[i])) miptex_hash = Hash_NewTable (1023, miptex_getkey, 0, 0);
return i; if (miptexnames) {
index = (intptr_t) Hash_Find (miptex_hash, mpname);
if (index)
return index - 1;
} }
if (nummiptex == MAX_MAP_TEXINFO) if (nummiptexnames == maxmiptexnames) {
map_error ("nummiptex == MAX_MAP_TEXINFO"); maxmiptexnames += MIPTEXNAME_CHUNK;
strcpy (miptex[i], name); miptexnames = realloc (miptexnames,
nummiptex++; maxmiptexnames * sizeof (const char *));
return i; }
index = nummiptexnames++;
miptexnames[index] = strdup (mpname);
Hash_Add (miptex_hash, (void *) (index + 1));
return index;
} }
/* /*
@ -110,8 +132,8 @@ FindTexinfo (texinfo_t *t)
return t->miptex; // it's HINT or SKIP return t->miptex; // it's HINT or SKIP
// set the special flag // set the special flag
if (miptex[t->miptex][0] == '*' if (miptexnames[t->miptex][0] == '*'
|| !strncasecmp (miptex[t->miptex], "sky", 3)) || !strncasecmp (miptexnames[t->miptex], "sky", 3))
t->flags |= TEX_SPECIAL; t->flags |= TEX_SPECIAL;
tex = bsp->texinfo; tex = bsp->texinfo;
@ -222,8 +244,8 @@ ParseBrush (void)
vec3_t t1, t2, *verts = 0; vec3_t t1, t2, *verts = 0;
vec_t d, vecs[2][4]; vec_t d, vecs[2][4];
b = &mapbrushes[nummapbrushes];
nummapbrushes++; nummapbrushes++;
b = calloc (1, sizeof (mbrush_t));
b->next = mapent->brushes; b->next = mapent->brushes;
mapent->brushes = b; mapent->brushes = b;
@ -430,11 +452,14 @@ ParseEntity (void)
if (strcmp (map_script->token->str, "{")) if (strcmp (map_script->token->str, "{"))
map_error ("ParseEntity: { not found"); map_error ("ParseEntity: { not found");
if (num_entities == MAX_MAP_ENTITIES) if (num_entities == max_entities) {
map_error ("num_entities == MAX_MAP_ENTITIES"); max_entities += ENTITIES_CHUNK;
entities = realloc (entities, max_entities * sizeof (entity_t));
}
mapent = &entities[num_entities]; mapent = &entities[num_entities];
num_entities++; num_entities++;
memset (mapent, 0, sizeof (entity_t));
do { do {
if (!Script_GetToken (map_script, true)) if (!Script_GetToken (map_script, true))
@ -512,7 +537,7 @@ LoadMapFile (const char *filename)
qprintf ("%5i faces\n", nummapbrushfaces); qprintf ("%5i faces\n", nummapbrushfaces);
qprintf ("%5i brushes (%i detail)\n", nummapbrushes, numdetailbrushes); qprintf ("%5i brushes (%i detail)\n", nummapbrushes, numdetailbrushes);
qprintf ("%5i entities\n", num_entities); qprintf ("%5i entities\n", num_entities);
qprintf ("%5i textures\n", nummiptex); qprintf ("%5i textures\n", nummiptexnames);
qprintf ("%5i texinfo\n", bsp->numtexinfo); qprintf ("%5i texinfo\n", bsp->numtexinfo);
} }

View file

@ -352,20 +352,20 @@ static byte default_palette[] = {
static const char * static const char *
unique_name (wad_t *wad, const char *name) unique_name (wad_t *wad, const char *name)
{ {
char uname[16]; char uname[MIPTEXNAME];
int i = 0; int i = 0;
const char *tag; const char *tag;
if (!wad_find_lump (wad, name)) if (!wad_find_lump (wad, name))
return name; return name;
do { do {
strncpy (uname, name, 16); strncpy (uname, name, MIPTEXNAME);
uname[15] = 0; uname[(MIPTEXNAME - 1)] = 0;
tag = va ("~%x", i++); tag = va ("~%x", i++);
if (strlen (uname) + strlen (tag) <= 15) if (strlen (uname) + strlen (tag) <= (MIPTEXNAME - 1))
strcat (uname, tag); strcat (uname, tag);
else else
strcpy (uname + 15 - strlen (tag), tag); strcpy (uname + (MIPTEXNAME - 1) - strlen (tag), tag);
} while (wad_find_lump (wad, uname)); } while (wad_find_lump (wad, uname));
return va ("%s", uname); // just to make a safe returnable that doesn't return va ("%s", uname); // just to make a safe returnable that doesn't
// need to be freed // need to be freed

View file

@ -139,33 +139,30 @@ RecursiveGrowRegion (dface_t *r, face_t *f)
// add edges // add edges
for (i = 0; i < f->points->numpoints; i++) { for (i = 0; i < f->points->numpoints; i++) {
e = f->edges[i]; e = f->edges[i];
if (!edgefaces[abs (e)][0]) if (!edgefaces[abs (e)].f[0])
continue; // edge has allready been removed continue; // edge has allready been removed
if (e > 0) if (e > 0)
f2 = edgefaces[e][1]; f2 = edgefaces[e].f[1];
else else
f2 = edgefaces[-e][0]; f2 = edgefaces[-e].f[0];
if (f2 && f2->outputnumber == bsp->numfaces) { if (f2 && f2->outputnumber == bsp->numfaces) {
edgefaces[abs (e)][0] = NULL; edgefaces[abs (e)].f[0] = NULL;
edgefaces[abs (e)][1] = NULL; edgefaces[abs (e)].f[1] = NULL;
continue; // allready merged continue; // allready merged
} }
if (f2 && CanJoinFaces (f, f2)) { // remove the edge and merge the if (f2 && CanJoinFaces (f, f2)) { // remove the edge and merge the
// faces // faces
edgefaces[abs (e)][0] = NULL; edgefaces[abs (e)].f[0] = NULL;
edgefaces[abs (e)][1] = NULL; edgefaces[abs (e)].f[1] = NULL;
RecursiveGrowRegion (r, f2); RecursiveGrowRegion (r, f2);
} else { } else {
// emit a surfedge // emit a surfedge
if (bsp->numsurfedges == MAX_MAP_SURFEDGES)
Sys_Error ("numsurfedges == MAX_MAP_SURFEDGES");
BSP_AddSurfEdge (bsp, e); BSP_AddSurfEdge (bsp, e);
} }
} }
} }
*/ */
int edgemapping[MAX_MAP_EDGES];
typedef struct { typedef struct {
int numedges; int numedges;
@ -188,7 +185,7 @@ CountRealNumbers (void)
c = 0; c = 0;
for (i = firstmodeledge; i < bsp->numedges; i++) for (i = firstmodeledge; i < bsp->numedges; i++)
if (edgefaces[i][0]) if (edgefaces[i].f[0])
c++; // not removed c++; // not removed
qprintf ("%5i real edges\n", c); qprintf ("%5i real edges\n", c);
@ -233,8 +230,6 @@ GrowNodeRegion_r (node_t * node)
#endif #endif
r.firstedge = firstedge = bsp->numsurfedges; r.firstedge = firstedge = bsp->numsurfedges;
for (i = 0; i < f->points->numpoints; i++) { for (i = 0; i < f->points->numpoints; i++) {
if (bsp->numsurfedges == MAX_MAP_SURFEDGES)
Sys_Error ("numsurfedges == MAX_MAP_SURFEDGES");
BSP_AddSurfEdge (bsp, f->edges[i]); BSP_AddSurfEdge (bsp, f->edges[i]);
} }

View file

@ -205,7 +205,9 @@ int c_cornerverts;
hashvert_t hvertex[MAX_MAP_VERTS]; hashvert_t hvertex[MAX_MAP_VERTS];
hashvert_t *hvert_p; hashvert_t *hvert_p;
face_t *edgefaces[MAX_MAP_EDGES][2]; #define EDGEFACE_CHUNK 4096
int numedgefaces = 0;
edgeface_t *edgefaces = 0;
int firstmodeledge = 1; int firstmodeledge = 1;
int firstmodelface; int firstmodelface;
@ -360,20 +362,23 @@ GetEdge (const vec3_t p1, const vec3_t p2, face_t *f)
// but does not yet have a second face. // but does not yet have a second face.
for (i = firstmodeledge; i < bsp->numedges; i++) { for (i = firstmodeledge; i < bsp->numedges; i++) {
if (v1 == bsp->edges[i].v[1] && v2 == bsp->edges[i].v[0] if (v1 == bsp->edges[i].v[1] && v2 == bsp->edges[i].v[0]
&& !edgefaces[i][1] && !edgefaces[i].f[1]
&& edgefaces[i][0]->contents[0] == f->contents[0]) { && edgefaces[i].f[0]->contents[0] == f->contents[0]) {
edgefaces[i][1] = f; edgefaces[i].f[1] = f;
return -i; return -i;
} }
} }
// Create a new edge. // Create a new edge.
if (bsp->numedges == MAX_MAP_EDGES) while (bsp->numedges >= numedgefaces) {
Sys_Error ("numedges == MAX_MAP_EDGES"); numedgefaces += EDGEFACE_CHUNK;
edgefaces = realloc (edgefaces, numedgefaces * sizeof (edgeface_t));
}
edge.v[0] = v1; edge.v[0] = v1;
edge.v[1] = v2; edge.v[1] = v2;
BSP_AddEdge (bsp, &edge); BSP_AddEdge (bsp, &edge);
edgefaces[i][0] = f; edgefaces[i].f[0] = f;
edgefaces[i].f[1] = 0;
return i; return i;
} }

View file

@ -250,9 +250,6 @@ WriteDrawNodes (const node_t *headnode)
#endif #endif
// emit a model // emit a model
if (bsp->nummodels == MAX_MAP_MODELS)
Sys_Error ("nummodels == MAX_MAP_MODELS");
bm.headnode[0] = bsp->numnodes; bm.headnode[0] = bsp->numnodes;
for (i = 1; i < MAX_MAP_HULLS; i++) for (i = 1; i < MAX_MAP_HULLS; i++)
bm.headnode[i] = 0; bm.headnode[i] = 0;
@ -382,14 +379,14 @@ AddAnimatingTextures (void)
char name[32]; char name[32];
wadlist_t *wl; wadlist_t *wl;
base = nummiptex; base = nummiptexnames;
name[sizeof (name) - 1] = 0; name[sizeof (name) - 1] = 0;
for (i = 0; i < base; i++) { for (i = 0; i < base; i++) {
if (miptex[i][0] != '+') if (miptexnames[i][0] != '+')
continue; continue;
strncpy (name, miptex[i], sizeof (name) - 1); strncpy (name, miptexnames[i], sizeof (name) - 1);
for (j = 0; j < 20; j++) { for (j = 0; j < 20; j++) {
if (j < 10) if (j < 10)
@ -407,8 +404,8 @@ AddAnimatingTextures (void)
} }
} }
if (nummiptex - base) if (nummiptexnames - base)
printf ("added %i texture frames\n", nummiptex - base); printf ("added %i texture frames\n", nummiptexnames - base);
} }
/** Write the miptex data to the bsp file. /** Write the miptex data to the bsp file.
@ -480,14 +477,14 @@ WriteMiptex (void)
dstring_adjust (data); dstring_adjust (data);
l = (dmiptexlump_t *) data->str; l = (dmiptexlump_t *) data->str;
l->nummiptex = nummiptex; l->nummiptex = nummiptexnames;
data->size = (char *) &l->dataofs[nummiptex] - data->str; data->size = (char *) &l->dataofs[nummiptexnames] - data->str;
dstring_adjust (data); dstring_adjust (data);
for (i = 0; i < nummiptex; i++) { for (i = 0; i < nummiptexnames; i++) {
l = (dmiptexlump_t *) data->str; l = (dmiptexlump_t *) data->str;
l->dataofs[i] = data->size; l->dataofs[i] = data->size;
len = LoadLump (miptex[i], data); len = LoadLump (miptexnames[i], data);
l = (dmiptexlump_t *) data->str; l = (dmiptexlump_t *) data->str;
if (!len) if (!len)
l->dataofs[i] = -1; // didn't find the texture l->dataofs[i] = -1; // didn't find the texture