ref: 0f07da746048c1452a42d3a964157448967c357f
parent: 5456cc33b02aa386b4b6d5800b8b9841726daf20
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Tue Nov 14 20:45:24 EST 2023
split bsp/bsp2 loading and removing bsp-related packed structures altogether
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,9 @@
mathlib.o\
menu.o\
model.o\
+ model_brush.o\
+ model_bsp.o\
+ model_bsp2.o\
net_loop.o\
net_main.o\
pal.o\
--- a/bspfile.h
+++ b/bspfile.h
@@ -1,5 +1,8 @@
-// upper design bounds
+#define BSPVERSION 29
+#define BSP2VERSION ('B'|'S'<<8|'P'<<16|'2'<<24)
+
enum {
+ // upper design bounds
MAX_MAP_HULLS = 4,
MAX_MAP_MODELS = 256,
MAX_MAP_BRUSHES = 4096,
@@ -19,33 +22,10 @@
MAX_MAP_VISIBILITY = 0x100000,
MAX_MAP_PORTALS = 65536,
- // key / value pair sizes
- MAX_KEY = 32,
- MAX_VALUE = 1024,
-
MIPLEVELS = 4,
MAXLIGHTMAPS = 4,
-};
-//=============================================================================
-
-#define BSPVERSION 29
-#define BSP2VERSION ('B'|'S'<<8|'P'<<16|'2'<<24)
-#define TOOLVERSION 2
-
-#ifdef __plan9__
-#pragma pack on
-#else
-#pragma pack(1)
-#endif
-
-typedef struct
-{
- int fileofs, filelen;
-} lump_t;
-
-enum {
- LUMP_ENTITIES,
+ LUMP_ENTITIES = 0,
LUMP_PLANES,
LUMP_TEXTURES,
LUMP_VERTEXES,
@@ -61,44 +41,9 @@
LUMP_SURFEDGES,
LUMP_MODELS,
HEADER_LUMPS,
-};
-typedef struct
-{
- float mins[3], maxs[3];
- float origin[3];
- int headnode[MAX_MAP_HULLS];
- int visleafs; // not including the solid leaf 0
- int firstface, numfaces;
-} dmodel_t;
-
-typedef struct
-{
- int version;
- lump_t lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct
-{
- int nummiptex;
- int dataofs[4]; // [nummiptex]
-} dmiptexlump_t;
-
-typedef struct miptex_s
-{
- char name[16];
- unsigned width, height;
- unsigned offsets[MIPLEVELS]; // four mip maps stored
-} miptex_t;
-
-typedef struct
-{
- float point[3];
-} dvertex_t;
-
-enum {
// 0-2 are axial planes
- PLANE_X,
+ PLANE_X = 0,
PLANE_Y,
PLANE_Z,
// 3-5 are non-axial planes snapped to the nearest
@@ -105,16 +50,7 @@
PLANE_ANYX,
PLANE_ANYY,
PLANE_ANYZ,
-};
-typedef struct
-{
- float normal[3];
- float dist;
- int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
-} dplane_t;
-
-enum {
CONTENTS_CURRENT_DOWN = -14,
CONTENTS_CURRENT_UP,
CONTENTS_CURRENT_270,
@@ -129,124 +65,6 @@
CONTENTS_WATER,
CONTENTS_SOLID,
CONTENTS_EMPTY,
-};
-// !!! if this is changed, it must be changed in asm_i386.h too !!!
-typedef struct
-{
- int planenum;
- short children[2]; // negative numbers are -(leafs+1), not nodes
- short mins[3]; // for sphere culling
- short maxs[3];
- unsigned short firstface;
- 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 sphere culling
- float maxs[3];
- unsigned int firstface;
- unsigned int numfaces; // counting both sides
-} bsp2_dnode_t;
-
-typedef struct
-{
- int planenum;
- short children[2]; // negative numbers are contents
-} dclipnode_t;
-
-typedef struct
-{
- int planenum;
- int children[2]; // negative numbers are contents
-} bsp2_dclipnode_t;
-
-enum {
TEX_SPECIAL = 1<<0, // sky or slime, no lightmap or 256 subdivision
};
-
-typedef struct texinfo_s
-{
- float vecs[2][4]; // [s/t][xyz offset]
- int miptex;
- int flags;
-} texinfo_t;
-
-// note that edge 0 is never used, because negative edge nums are used for
-// counterclockwise use of the edge in a face
-typedef struct
-{
- unsigned short v[2]; // vertex numbers
-} dedge_t;
-
-typedef struct
-{
- unsigned int v[2];
-} bsp2_dedge_t;
-
-typedef struct
-{
- short planenum;
- short side;
-
- int firstedge; // we must support > 64k edges
- short numedges;
- short texinfo;
-
-// lighting info
- byte styles[MAXLIGHTMAPS];
- int lightofs; // start of [numstyles*surfsize] samples
-} dface_t;
-
-typedef struct
-{
- 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
-} bsp2_dface_t;
-
-// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
-// all other leafs need visibility info
-typedef struct
-{
- int contents;
- int visofs; // -1 = no visibility info
-
- short mins[3]; // for frustum culling
- short maxs[3];
-
- unsigned short firstmarksurface;
- unsigned short nummarksurfaces;
-
- byte ambient_level[Namb];
-} dleaf_t;
-
-typedef struct
-{
- int contents;
- int visofs; // -1 = no visibility info
-
- float mins[3]; // for frustum culling
- float maxs[3];
-
- unsigned int firstmarksurface;
- unsigned int nummarksurfaces;
-
- byte ambient_level[Namb];
-} bsp2_dleaf_t;
-
-#ifdef __plan9__
-#pragma pack off
-#else
-#pragma pack(0)
-#endif
--- a/mkfile
+++ b/mkfile
@@ -41,6 +41,9 @@
mathlib.$O\
menu.$O\
model.$O\
+ model_brush.$O\
+ model_bsp.$O\
+ model_bsp2.$O\
nanosec.$O\
net_dgrm.$O\
net_loop.$O\
--- a/model.c
+++ b/model.c
@@ -1,10 +1,9 @@
#include "quakedef.h"
-static model_t *loadmodel;
static char loadname[32]; // for hunk tags
void Mod_LoadSpriteModel (model_t *mod, void *buffer);
-void Mod_LoadBrushModel (model_t *mod, void *buffer);
+void Mod_LoadBrushModel (model_t *mod, void *buffer, int total);
void Mod_LoadAliasModel (model_t *mod, void *buffer);
model_t *Mod_LoadModel (model_t *mod, bool crash);
@@ -227,27 +226,19 @@
*/
model_t *Mod_LoadModel (model_t *mod, bool crash)
{
- unsigned *buf;
- byte stackbuf[1024]; // avoid dirtying the cache heap
+ byte *buf;
+ int len;
- if (mod->type == mod_alias)
- {
- if (Cache_Check (&mod->cache))
- {
+ if(mod->type == mod_alias){
+ if(Cache_Check(&mod->cache)){
mod->needload = NL_PRESENT;
return mod;
}
- }
- else
- {
- if (mod->needload == NL_PRESENT){
- return mod;
- }
- }
+ }else if(mod->needload == NL_PRESENT)
+ return mod;
// because the world is so huge, load it one piece at a time
- buf = loadstklmp(mod->name, stackbuf, sizeof stackbuf, nil);
- if(buf == nil){
+ if((buf = loadstklmp(mod->name, nil, 0, &len)) == nil){
if(crash)
Host_Error("Mod_LoadModel: %s", lerr());
return nil;
@@ -255,7 +246,6 @@
// allocate a new model
radix(mod->name, loadname);
- loadmodel = mod;
// fill it in
@@ -262,18 +252,18 @@
// call the apropriate loader
mod->needload = NL_PRESENT;
- switch (LittleLong(*(unsigned *)buf))
+ switch(LittleLong(*(unsigned *)buf))
{
case IDPOLYHEADER:
- Mod_LoadAliasModel (mod, buf);
+ Mod_LoadAliasModel(mod, buf);
break;
case IDSPRITEHEADER:
- Mod_LoadSpriteModel (mod, buf);
+ Mod_LoadSpriteModel(mod, buf);
break;
default:
- Mod_LoadBrushModel (mod, buf);
+ Mod_LoadBrushModel(mod, buf, len);
break;
}
@@ -294,894 +284,6 @@
mod = Mod_FindName (name);
return Mod_LoadModel (mod, crash);
-}
-
-
-/*
-===============================================================================
-
- BRUSHMODEL LOADING
-
-===============================================================================
-*/
-
-static byte *mod_base;
-
-/*
-=================
-Mod_LoadTextures
-=================
-*/
-void Mod_LoadTextures (lump_t *l)
-{
- int i, j, pixels, num, max, altmax;
- miptex_t *mt;
- texture_t *tx, *tx2;
- texture_t *anims[10];
- texture_t *altanims[10];
- dmiptexlump_t *m;
-
- if (!l->filelen)
- {
- loadmodel->textures = nil;
- return;
- }
- m = (dmiptexlump_t *)(mod_base + l->fileofs);
-
- m->nummiptex = LittleLong (m->nummiptex);
-
- loadmodel->numtextures = m->nummiptex;
- loadmodel->textures = Hunk_Alloc(m->nummiptex * sizeof *loadmodel->textures);
-
- for (i=0 ; i<m->nummiptex ; i++)
- {
- m->dataofs[i] = LittleLong(m->dataofs[i]);
- if (m->dataofs[i] == -1)
- continue;
- mt = (miptex_t *)((byte *)m + m->dataofs[i]);
- mt->width = LittleLong (mt->width);
- mt->height = LittleLong (mt->height);
- for (j=0 ; j<MIPLEVELS ; j++)
- mt->offsets[j] = LittleLong (mt->offsets[j]);
-
- if ( (mt->width & 15) || (mt->height & 15) )
- Con_DPrintf("Texture %s is not 16 aligned", mt->name);
- pixels = mt->width*mt->height/64*85;
- tx = Hunk_Alloc(pixels + sizeof *tx);
- loadmodel->textures[i] = tx;
-
- memcpy(tx->name, mt->name, sizeof tx->name);
- tx->width = mt->width;
- tx->height = mt->height;
- for (j=0 ; j<MIPLEVELS ; j++)
- tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
- // the pixels immediately follow the structures
- memcpy(tx+1, mt+1, pixels);
-
- if(strncmp(mt->name, "sky", 3) == 0)
- R_InitSky (tx);
- }
-
- // sequence the animations
- for (i=0 ; i<m->nummiptex ; i++)
- {
- tx = loadmodel->textures[i];
- if (!tx || tx->name[0] != '+')
- continue;
- if (tx->anim_next)
- continue; // allready sequenced
-
- // find the number of frames in the animation
- memset(anims, 0, sizeof anims);
- memset(altanims, 0, sizeof altanims);
-
- max = tx->name[1];
- altmax = 0;
- if (max >= 'a' && max <= 'z')
- max -= 'a' - 'A';
- if (max >= '0' && max <= '9')
- {
- max -= '0';
- altmax = 0;
- anims[max] = tx;
- max++;
- }
- else if (max >= 'A' && max <= 'J')
- {
- altmax = max - 'A';
- max = 0;
- altanims[altmax] = tx;
- altmax++;
- }
- else
- Host_Error("Bad animating texture %s", tx->name);
-
- for (j=i+1 ; j<m->nummiptex ; j++)
- {
- tx2 = loadmodel->textures[j];
- if (!tx2 || tx2->name[0] != '+')
- continue;
- if(strcmp(tx2->name+2, tx->name+2) != 0)
- continue;
-
- num = tx2->name[1];
- if (num >= 'a' && num <= 'z')
- num -= 'a' - 'A';
- if (num >= '0' && num <= '9')
- {
- num -= '0';
- anims[num] = tx2;
- if (num+1 > max)
- max = num + 1;
- }
- else if (num >= 'A' && num <= 'J')
- {
- num = num - 'A';
- altanims[num] = tx2;
- if (num+1 > altmax)
- altmax = num+1;
- }
- else
- Host_Error("Bad animating texture %s", tx->name);
- }
-
-#define ANIM_CYCLE 2
- // link them all together
- for (j=0 ; j<max ; j++)
- {
- tx2 = anims[j];
- if (!tx2)
- Host_Error("Missing frame %d of %s", j, tx->name);
- tx2->anim_total = max * ANIM_CYCLE;
- tx2->anim_min = j * ANIM_CYCLE;
- tx2->anim_max = (j+1) * ANIM_CYCLE;
- tx2->anim_next = anims[ (j+1)%max ];
- if (altmax)
- tx2->alternate_anims = altanims[0];
- }
- for (j=0 ; j<altmax ; j++)
- {
- tx2 = altanims[j];
- if (!tx2)
- Host_Error("Missing frame %d of %s", j, tx->name);
- tx2->anim_total = altmax * ANIM_CYCLE;
- tx2->anim_min = j * ANIM_CYCLE;
- tx2->anim_max = (j+1) * ANIM_CYCLE;
- tx2->anim_next = altanims[ (j+1)%altmax ];
- if (max)
- tx2->alternate_anims = anims[0];
- }
- }
-}
-
-/*
-=================
-Mod_LoadLighting
-=================
-*/
-void Mod_LoadLighting (lump_t *l)
-{
- if (!l->filelen)
- {
- loadmodel->lightdata = nil;
- return;
- }
- loadmodel->lightdata = Hunk_Alloc(l->filelen);
- memcpy(loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
-}
-
-
-/*
-=================
-Mod_LoadVisibility
-=================
-*/
-void Mod_LoadVisibility (lump_t *l)
-{
- if (!l->filelen)
- {
- loadmodel->visdata = nil;
- return;
- }
- loadmodel->visdata = Hunk_Alloc(l->filelen);
- memcpy(loadmodel->visdata, mod_base + l->fileofs, l->filelen);
-}
-
-
-/*
-=================
-Mod_LoadEntities
-=================
-*/
-void Mod_LoadEntities (lump_t *l)
-{
- if (!l->filelen)
- {
- loadmodel->entities = nil;
- return;
- }
- loadmodel->entities = Hunk_Alloc(l->filelen);
- memcpy(loadmodel->entities, mod_base + l->fileofs, l->filelen);
-}
-
-
-/*
-=================
-Mod_LoadVertexes
-=================
-*/
-void Mod_LoadVertexes (lump_t *l)
-{
- dvertex_t *in;
- mvertex_t *out;
- int i, count;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Host_Error("Mod_LoadVertexes: funny lump size in %s", loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc(count * sizeof *out);
-
- loadmodel->vertexes = out;
- loadmodel->numvertexes = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- out->position[0] = LittleFloat (in->point[0]);
- out->position[1] = LittleFloat (in->point[1]);
- out->position[2] = LittleFloat (in->point[2]);
- }
-}
-
-/*
-=================
-Mod_LoadSubmodels
-=================
-*/
-void Mod_LoadSubmodels (lump_t *l)
-{
- dmodel_t *in;
- dmodel_t *out;
- int i, j, count;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Host_Error("Mod_LoadSubmodels: funny lump size in %s", loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc(count * sizeof *out);
-
- loadmodel->submodels = out;
- loadmodel->numsubmodels = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- for (j=0 ; j<3 ; j++)
- { // spread the mins / maxs by a pixel
- out->mins[j] = LittleFloat (in->mins[j]) - 1;
- out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
- out->origin[j] = LittleFloat (in->origin[j]);
- }
- for (j=0 ; j<MAX_MAP_HULLS ; j++)
- out->headnode[j] = LittleLong (in->headnode[j]);
- out->visleafs = LittleLong (in->visleafs);
- out->firstface = LittleLong (in->firstface);
- out->numfaces = LittleLong (in->numfaces);
- }
-}
-
-/*
-=================
-Mod_LoadEdges
-=================
-*/
-void Mod_LoadEdges (lump_t *l, int ver)
-{
- byte *in;
- medge_t *out;
- int i, count, sz;
-
- in = (void *)(mod_base + l->fileofs);
- sz = ver == BSP2VERSION ? sizeof(bsp2_dedge_t) : sizeof(dedge_t);
- if (l->filelen % sz)
- Host_Error("Mod_LoadEdges: funny lump size in %s", loadmodel->name);
- count = l->filelen / sz;
- out = Hunk_Alloc((count+1) * sizeof *out);
-
- loadmodel->edges = out;
- loadmodel->numedges = count;
-
- for ( i=0 ; i<count ; i++, out++)
- {
- out->v[0] = ver == BSP2VERSION ? le32u(in) : le16u(in);
- out->v[1] = ver == BSP2VERSION ? le32u(in) : le16u(in);
- }
-}
-
-/*
-=================
-Mod_LoadTexinfo
-=================
-*/
-void Mod_LoadTexinfo (lump_t *l)
-{
- texinfo_t *in;
- mtexinfo_t *out;
- int i, j, count;
- int miptex;
- float len1, len2;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Host_Error("Mod_LoadTexInfo: funny lump size in %s", loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc(count * sizeof *out);
-
- loadmodel->texinfo = out;
- loadmodel->numtexinfo = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- for (j=0 ; j<4 ; j++)
- out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
- for (j=0 ; j<4 ; j++)
- out->vecs[1][j] = LittleFloat (in->vecs[1][j]);
- len1 = Length (out->vecs[0]);
- len2 = Length (out->vecs[1]);
- len1 = (len1 + len2)/2;
- if (len1 < 0.32)
- out->mipadjust = 4;
- else if (len1 < 0.49)
- out->mipadjust = 3;
- else if (len1 < 0.99)
- out->mipadjust = 2;
- else
- out->mipadjust = 1;
- /*
- if (len1 + len2 < 0.001)
- out->mipadjust = 1; // don't crash
- else
- out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
- */
-
- miptex = LittleLong (in->miptex);
- out->flags = LittleLong (in->flags);
-
- if (!loadmodel->textures)
- {
- out->texture = r_notexture_mip; // checkerboard texture
- out->flags = 0;
- }
- else
- {
- if (miptex >= loadmodel->numtextures)
- Host_Error("miptex >= loadmodel->numtextures");
- out->texture = loadmodel->textures[miptex];
- if (!out->texture)
- {
- out->texture = r_notexture_mip; // texture not found
- out->flags = 0;
- }
- }
- }
-}
-
-/*
-================
-CalcSurfaceExtents
-
-Fills in s->texturemins[] and s->extents[]
-================
-*/
-void CalcSurfaceExtents (msurface_t *s)
-{
- double mins[2], maxs[2], val;
- int i,j, e;
- mvertex_t *v;
- mtexinfo_t *tex;
- int bmins[2], bmaxs[2];
-
- mins[0] = mins[1] = Q_MAXFLOAT;
- maxs[0] = maxs[1] = -Q_MAXFLOAT;
- tex = s->texinfo;
-
- for (i=0 ; i<s->numedges ; i++)
- {
- e = loadmodel->surfedges[s->firstedge+i];
- if (e >= 0)
- v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
- else
- v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
-
- for (j=0 ; j<2 ; j++)
- {
- val = (double)v->position[0] * (double)tex->vecs[j][0] +
- (double)v->position[1] * (double)tex->vecs[j][1] +
- (double)v->position[2] * (double)tex->vecs[j][2] +
- (double)tex->vecs[j][3];
- if (val < mins[j])
- mins[j] = val;
- if (val > maxs[j])
- maxs[j] = val;
- }
- }
-
- for (i=0 ; i<2 ; i++)
- {
- bmins[i] = floor(mins[i]/16.0);
- bmaxs[i] = ceil(maxs[i]/16.0);
-
- s->texturemins[i] = bmins[i] * 16;
- s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
- if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 2000)
- Host_Error("Bad surface: texture=%s flags=%ux extents[%d]=%d",
- tex->texture->name,
- tex->flags,
- i,
- s->extents[i]
- );
- }
-}
-
-
-/*
-=================
-Mod_LoadFaces
-=================
-*/
-void Mod_LoadFaces (lump_t *l, int ver)
-{
- byte *in;
- msurface_t *out;
- int i, count, surfnum, sz;
-
- in = (void *)(mod_base + l->fileofs);
- sz = ver == BSP2VERSION ? sizeof(bsp2_dface_t) : sizeof(dface_t);
- if (l->filelen % sz)
- Host_Error("Mod_LoadFaces: funny lump size in %s", loadmodel->name);
- count = l->filelen / sz;
- out = Hunk_Alloc(count * sizeof *out);
-
- loadmodel->surfaces = out;
- loadmodel->numsurfaces = count;
-
- for ( surfnum=0 ; surfnum<count ; surfnum++, out++)
- {
- out->plane = loadmodel->planes + (ver == BSP2VERSION ? le32u(in) : le16u(in));
- out->flags = (ver == BSP2VERSION ? le32u(in) : le16u(in)) ? SURF_PLANEBACK : 0;
- out->firstedge = le32u(in);
- out->numedges = ver == BSP2VERSION ? le32u(in) : le16u(in);
- out->texinfo = loadmodel->texinfo + (ver == BSP2VERSION ? le32u(in) : le16u(in));
-
- CalcSurfaceExtents (out);
-
- // lighting info
-
- memmove(out->styles, in, MAXLIGHTMAPS);
- in += MAXLIGHTMAPS;
- out->samples = (i = le32(in)) < 0 ? nil : loadmodel->lightdata + i;
-
- // set the drawing flags flag
-
- if(strncmp(out->texinfo->texture->name, "sky", 3) == 0)
- out->flags |= SURF_DRAWSKY | SURF_DRAWTILED;
- else if(out->texinfo->texture->name[0] == '*'){ // turbulent
- out->flags |= SURF_DRAWTURB | SURF_DRAWTILED | SURF_TRANS;
- for (i=0 ; i<2 ; i++){
- out->extents[i] = 16384;
- out->texturemins[i] = -8192;
- }
- if(strstr(out->texinfo->texture->name, "lava") != nil)
- out->flags |= SURF_LAVA;
- if(strstr(out->texinfo->texture->name, "slime") != nil)
- out->flags |= SURF_SLIME;
- if(strstr(out->texinfo->texture->name, "tele") != nil){
- out->flags |= SURF_TELE;
- out->flags &= ~SURF_TRANS;
- }
- }else if(out->texinfo->texture->name[0] == '{')
- out->flags |= SURF_TRANS | SURF_FENCE;
- }
-}
-
-
-/*
-=================
-Mod_SetParent
-=================
-*/
-void Mod_SetParent (mnode_t *node, mnode_t *parent)
-{
- node->parent = parent;
- if (node->contents < 0)
- return;
- Mod_SetParent (node->children[0], node);
- Mod_SetParent (node->children[1], node);
-}
-
-/*
-=================
-Mod_LoadNodes
-=================
-*/
-void Mod_LoadNodes (lump_t *l, int ver)
-{
- int i, j, count, p, sz;
- byte *in;
- mnode_t *out;
-
- in = (void *)(mod_base + l->fileofs);
- sz = ver == BSP2VERSION ? sizeof(bsp2_dnode_t) : sizeof(dnode_t);
- if (l->filelen % sz)
- Host_Error("Mod_LoadNodes: funny lump size in %s", loadmodel->name);
- count = l->filelen / sz;
- out = Hunk_Alloc(count * sizeof *out);
-
- loadmodel->nodes = out;
- loadmodel->numnodes = count;
-
- for ( i=0 ; i<count ; i++, out++)
- {
- out->plane = loadmodel->planes + le32u(in);
-
- for (j=0 ; j<2 ; j++){
- p = ver == BSP2VERSION ? le32(in) : le16u(in);
- if(p >= 0 && p < count)
- out->children[j] = loadmodel->nodes + p;
- else{
- p = ver == BSP2VERSION ? -1-p : 0xffff-p;
- if(p >= 0 && p < loadmodel->numleafs)
- out->children[j] = (mnode_t *)(loadmodel->leafs + p);
- else{
- Con_Printf("Mod_LoadNodes: invalid node child\n");
- out->children[j] = (mnode_t *)loadmodel->leafs;
- }
- }
- }
-
- for(j=0 ; j<3 ; j++)
- out->minmaxs[0+j] = ver == BSP2VERSION ? f32(in) : le16(in);
- for(j=0 ; j<3 ; j++)
- out->minmaxs[3+j] = ver == BSP2VERSION ? f32(in) : le16(in);
-
- out->firstsurface = ver == BSP2VERSION ? le32u(in) : le16u(in);
- out->numsurfaces = ver == BSP2VERSION ? le32u(in) : le16u(in);
- }
-
- Mod_SetParent (loadmodel->nodes, nil); // sets nodes and leafs
-}
-
-/*
-=================
-Mod_LoadLeafs
-=================
-*/
-void Mod_LoadLeafs (lump_t *l, int ver)
-{
- byte *in;
- mleaf_t *out;
- int i, j, count, p, sz;
-
- in = (void *)(mod_base + l->fileofs);
- sz = ver == BSP2VERSION ? sizeof(bsp2_dleaf_t) : sizeof(dleaf_t);
- if (l->filelen % sz)
- Host_Error("Mod_LoadLeafs: funny lump size in %s", loadmodel->name);
- count = l->filelen / sz;
- out = Hunk_Alloc(count * sizeof *out);
-
- loadmodel->leafs = out;
- loadmodel->numleafs = count;
-
- for ( i=0 ; i<count ; i++, out++)
- {
- out->contents = le32(in);
- out->compressed_vis = (p = le32(in)) < 0 ? nil : loadmodel->visdata + p;
-
- for(j=0 ; j<3 ; j++)
- out->minmaxs[0+j] = ver == BSP2VERSION ? f32(in) : le16(in);
- for(j=0 ; j<3 ; j++)
- out->minmaxs[3+j] = ver == BSP2VERSION ? f32(in) : le16(in);
-
- out->firstmarksurface = loadmodel->marksurfaces + (ver == BSP2VERSION ? le32u(in) : le16u(in));
- out->nummarksurfaces = ver == BSP2VERSION ? le32u(in) : le16u(in);
-
- memmove(out->ambient_sound_level, in, 4);
- in += 4;
- }
-}
-
-/*
-=================
-Mod_LoadClipnodes
-=================
-*/
-void Mod_LoadClipnodes (lump_t *l, int ver)
-{
- byte *in;
- mclipnode_t *out;
- int i, count, sz;
- hull_t *hull;
-
- in = (void *)(mod_base + l->fileofs);
- sz = ver == BSP2VERSION ? sizeof(bsp2_dclipnode_t) : sizeof(dclipnode_t);
- if (l->filelen % sz)
- Host_Error("Mod_LoadClipnodes: funny lump size in %s", loadmodel->name);
- count = l->filelen / sz;
- out = Hunk_Alloc(count * sizeof *out);
-
- loadmodel->clipnodes = out;
- loadmodel->numclipnodes = count;
-
- hull = &loadmodel->hulls[1];
- hull->clipnodes = out;
- hull->firstclipnode = 0;
- hull->lastclipnode = count-1;
- hull->planes = loadmodel->planes;
- hull->clip_mins[0] = -16;
- hull->clip_mins[1] = -16;
- hull->clip_mins[2] = -24;
- hull->clip_maxs[0] = 16;
- hull->clip_maxs[1] = 16;
- hull->clip_maxs[2] = 32;
-
- hull = &loadmodel->hulls[2];
- hull->clipnodes = out;
- hull->firstclipnode = 0;
- hull->lastclipnode = count-1;
- hull->planes = loadmodel->planes;
- hull->clip_mins[0] = -32;
- hull->clip_mins[1] = -32;
- hull->clip_mins[2] = -24;
- hull->clip_maxs[0] = 32;
- hull->clip_maxs[1] = 32;
- hull->clip_maxs[2] = 64;
-
- for (i=0 ; i<count ; i++, out++)
- {
- out->planenum = le32u(in);
- out->children[0] = ver == BSP2VERSION ? le32u(in) : le16u(in);
- out->children[1] = ver == BSP2VERSION ? le32u(in) : le16u(in);
- if(out->children[0] >= count)
- out->children[0] -= 0x10000;
- if(out->children[1] >= count)
- out->children[1] -= 0x10000;
- }
-}
-
-/*
-=================
-Mod_MakeHull0
-
-Deplicate the drawing hull structure as a clipping hull
-=================
-*/
-void Mod_MakeHull0 (void)
-{
- mnode_t *in, *child;
- mclipnode_t *out;
- int i, j, count;
- hull_t *hull;
-
- hull = &loadmodel->hulls[0];
-
- in = loadmodel->nodes;
- count = loadmodel->numnodes;
- out = Hunk_Alloc(count * sizeof *out);
-
- hull->clipnodes = out;
- hull->firstclipnode = 0;
- hull->lastclipnode = count-1;
- hull->planes = loadmodel->planes;
-
- for (i=0 ; i<count ; i++, out++, in++)
- {
- out->planenum = in->plane - loadmodel->planes;
- for (j=0 ; j<2 ; j++)
- {
- child = in->children[j];
- if (child->contents < 0)
- out->children[j] = child->contents;
- else
- out->children[j] = child - loadmodel->nodes;
- }
- }
-}
-
-/*
-=================
-Mod_LoadMarksurfaces
-=================
-*/
-void Mod_LoadMarksurfaces (lump_t *l, int ver)
-{
- int i, j, count, sz;
- byte *in;
- msurface_t **out;
-
- in = (void *)(mod_base + l->fileofs);
- sz = ver == BSP2VERSION ? sizeof(u32int) : sizeof(u16int);
- if (l->filelen % sz)
- Host_Error("Mod_LoadMarksurfaces: funny lump size in %s", loadmodel->name);
- count = l->filelen / sz;
- out = Hunk_Alloc(count * sizeof *out);
-
- loadmodel->marksurfaces = out;
- loadmodel->nummarksurfaces = count;
-
- for ( i=0 ; i<count ; i++)
- {
- j = ver == BSP2VERSION ? le32u(in) : le16u(in);
- if(j < 0 || j >= loadmodel->numsurfaces)
- Host_Error("Mod_ParseMarksurfaces: bad surface number");
- out[i] = loadmodel->surfaces + j;
- }
-}
-
-/*
-=================
-Mod_LoadSurfedges
-=================
-*/
-void Mod_LoadSurfedges (lump_t *l)
-{
- int i, count;
- int *in, *out;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Host_Error("Mod_LoadSurfedges: funny lump size in %s", loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc(count * sizeof *out);
-
- loadmodel->surfedges = out;
- loadmodel->numsurfedges = count;
-
- for ( i=0 ; i<count ; i++)
- out[i] = LittleLong (in[i]);
-}
-
-/*
-=================
-Mod_LoadPlanes
-=================
-*/
-void Mod_LoadPlanes (lump_t *l)
-{
- int i, j;
- mplane_t *out;
- dplane_t *in;
- int count;
- int bits;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Host_Error("Mod_LoadPlanes: funny lump size in %s", loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc(count * 2 * sizeof *out);
-
- loadmodel->planes = out;
- loadmodel->numplanes = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- bits = 0;
- for (j=0 ; j<3 ; j++)
- {
- out->normal[j] = LittleFloat (in->normal[j]);
- if (out->normal[j] < 0)
- bits |= 1<<j;
- }
-
- out->dist = LittleFloat (in->dist);
- out->type = LittleLong (in->type);
- out->signbits = bits;
- }
-}
-
-/*
-=================
-RadiusFromBounds
-=================
-*/
-float RadiusFromBounds (vec3_t mins, vec3_t maxs)
-{
- int i;
- vec3_t corner;
-
- for (i=0 ; i<3 ; i++)
- {
- corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
- }
-
- return Length (corner);
-}
-
-/*
-=================
-Mod_LoadBrushModel
-=================
-*/
-void Mod_LoadBrushModel (model_t *mod, void *buffer)
-{
- int i, j, ver;
- dheader_t *header;
- dmodel_t *bm;
-
- loadmodel->type = mod_brush;
-
- header = (dheader_t *)buffer;
-
- ver = LittleLong (header->version);
- if (ver != BSPVERSION && ver != BSP2VERSION)
- Host_Error("Mod_LoadBrushModel: %s has wrong version number (%ux should be %ux or %ux)", mod->name, ver, BSPVERSION, BSP2VERSION);
-
- // swap all the lumps
- mod_base = (byte *)header;
-
- for (i=0 ; i<(int)sizeof(dheader_t)/4 ; i++)
- ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
-
- // load into heap
-
- Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
- Mod_LoadEdges (&header->lumps[LUMP_EDGES], ver);
- Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
- Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
- Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
- Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
- Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
- Mod_LoadFaces (&header->lumps[LUMP_FACES], ver);
- Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES], ver);
- Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
- Mod_LoadLeafs (&header->lumps[LUMP_LEAFS], ver);
- Mod_LoadNodes (&header->lumps[LUMP_NODES], ver);
- Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES], ver);
- Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
- Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
-
- Mod_MakeHull0 ();
-
- mod->numframes = 2; // regular and alternate animation
- mod->flags = 0;
-
- // set up the submodels (FIXME: this is confusing)
- for (i=0 ; i<mod->numsubmodels ; i++)
- {
- bm = &mod->submodels[i];
-
- mod->hulls[0].firstclipnode = bm->headnode[0];
- for (j=1 ; j<MAX_MAP_HULLS ; j++)
- {
- mod->hulls[j].firstclipnode = bm->headnode[j];
- mod->hulls[j].lastclipnode = mod->numclipnodes-1;
- }
-
- mod->firstmodelsurface = bm->firstface;
- mod->nummodelsurfaces = bm->numfaces;
- mod->blend = false;
- for(j = bm->firstface; j < bm->firstface+bm->numfaces; j++){
- if(loadmodel->surfaces[j].flags & SURF_TRANS){
- mod->blend = true;
- break;
- }
- }
-
- VectorCopy (bm->maxs, mod->maxs);
- VectorCopy (bm->mins, mod->mins);
- mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
-
- mod->numleafs = bm->visleafs;
-
- if (i < mod->numsubmodels-1)
- { // duplicate the basic information
- char name[16];
-
- snprint(name, sizeof(name), "*%d", i+1);
- loadmodel = Mod_FindName (name);
- *loadmodel = *mod;
- strcpy (loadmodel->name, name);
- mod = loadmodel;
- }
- }
}
/*
--- a/model.h
+++ b/model.h
@@ -273,17 +273,32 @@
// Whole model
//
-typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
+typedef enum {
+ mod_brush,
+ mod_sprite,
+ mod_alias,
+} modtype_t;
-#define EF_ROCKET 1 // leave a trail
-#define EF_GRENADE 2 // leave a trail
-#define EF_GIB 4 // leave a trail
-#define EF_ROTATE 8 // rotate (bonus items)
-#define EF_TRACER 16 // green split trail
-#define EF_ZOMGIB 32 // small blood trail
-#define EF_TRACER2 64 // orange split trail + rotate
-#define EF_TRACER3 128 // purple trail
+enum {
+ EF_ROCKET = 1<<0, // leave a trail
+ EF_GRENADE = 1<<1, // leave a trail
+ EF_GIB = 1<<2, // leave a trail
+ EF_ROTATE = 1<<3, // rotate (bonus items)
+ EF_TRACER = 1<<4, // green split trail
+ EF_ZOMGIB = 1<<5, // small blood trail
+ EF_TRACER2 = 1<<6, // orange split trail + rotate
+ EF_TRACER3 = 1<<7, // purple trail
+};
+typedef struct
+{
+ float mins[3], maxs[3];
+ float origin[3];
+ int headnode[MAX_MAP_HULLS];
+ int visleafs; // not including the solid leaf 0
+ int firstface, numfaces;
+} submodel_t;
+
typedef struct model_s
{
char name[Npath];
@@ -308,7 +323,7 @@
int firstmodelsurface, nummodelsurfaces;
int numsubmodels;
- dmodel_t *submodels;
+ submodel_t *submodels;
int numplanes;
mplane_t *planes;
--- /dev/null
+++ b/model_brush.c
@@ -1,0 +1,170 @@
+#include "quakedef.h"
+
+void BSP_MakeHull0(model_t *mod);
+model_t *Mod_FindName (char *name);
+
+int BSP_LoadClipnodes(model_t *mod, byte *in, int sz);
+int BSP_LoadEdges(model_t *mod, byte *in, int sz);
+int BSP_LoadEntities(model_t *mod, byte *in, int sz);
+int BSP_LoadFaces(model_t *mod, byte *in, int sz);
+int BSP_LoadLeafs(model_t *mod, byte *in, int sz);
+int BSP_LoadLighting(model_t *mod, byte *in, int sz);
+int BSP_LoadMarksurfaces(model_t *mod, byte *in, int sz);
+int BSP_LoadNodes(model_t *mod, byte *in, int sz);
+int BSP_LoadPlanes(model_t *mod, byte *in, int sz);
+int BSP_LoadSubmodels(model_t *mod, byte *in, int sz);
+int BSP_LoadSurfedges(model_t *mod, byte *in, int sz);
+int BSP_LoadTexinfo(model_t *mod, byte *in, int sz);
+int BSP_LoadTextures(model_t *mod, byte *in, int sz);
+int BSP_LoadVertexes(model_t *mod, byte *in, int sz);
+int BSP_LoadVisibility(model_t *mod, byte *in, int sz);
+
+int BSP2_LoadClipnodes(model_t *mod, byte *in, int sz);
+int BSP2_LoadEdges(model_t *mod, byte *in, int sz);
+int BSP2_LoadFaces(model_t *mod, byte *in, int sz);
+int BSP2_LoadLeafs(model_t *mod, byte *in, int sz);
+int BSP2_LoadMarksurfaces(model_t *mod, byte *in, int sz);
+int BSP2_LoadNodes(model_t *mod, byte *in, int sz);
+
+static float
+RadiusFromBounds(vec3_t mins, vec3_t maxs)
+{
+ int i;
+ vec3_t corner;
+ float fmin, fmax;
+
+ for(i=0 ; i<3 ; i++){
+ fmin = fabs(mins[i]);
+ fmax = fabs(maxs[i]);
+ corner[i] = max(fmin, fmax);
+ }
+
+ return Length(corner);
+}
+
+void
+Mod_LoadBrushModel(model_t *mod, void *buffer, int total)
+{
+ int i, j, ver, off, sz;
+ model_t *submod;
+ byte *in, *in0;
+ submodel_t *bm;
+ char name[16];
+ int (*loadf[HEADER_LUMPS])(model_t *, byte *, int) = {
+ [LUMP_VERTEXES] = BSP_LoadVertexes,
+ [LUMP_EDGES] = nil,
+ [LUMP_SURFEDGES] = BSP_LoadSurfedges,
+ [LUMP_TEXTURES] = BSP_LoadTextures,
+ [LUMP_LIGHTING] = BSP_LoadLighting,
+ [LUMP_PLANES] = BSP_LoadPlanes,
+ [LUMP_TEXINFO] = BSP_LoadTexinfo,
+ [LUMP_FACES] = nil,
+ [LUMP_MARKSURFACES] = nil,
+ [LUMP_VISIBILITY] = BSP_LoadVisibility,
+ [LUMP_LEAFS] = nil,
+ [LUMP_NODES] = nil,
+ [LUMP_CLIPNODES] = nil,
+ [LUMP_ENTITIES] = BSP_LoadEntities,
+ [LUMP_MODELS] = BSP_LoadSubmodels,
+ };
+ static const int order[HEADER_LUMPS] = {
+ LUMP_VERTEXES,
+ LUMP_EDGES,
+ LUMP_SURFEDGES,
+ LUMP_TEXTURES,
+ LUMP_LIGHTING,
+ LUMP_PLANES,
+ LUMP_TEXINFO,
+ LUMP_FACES,
+ LUMP_MARKSURFACES,
+ LUMP_VISIBILITY,
+ LUMP_LEAFS,
+ LUMP_NODES,
+ LUMP_CLIPNODES,
+ LUMP_ENTITIES,
+ LUMP_MODELS,
+ };
+
+ in0 = in = buffer;
+ ver = le32(in);
+ if(ver == BSPVERSION){
+ loadf[LUMP_EDGES] = BSP_LoadEdges;
+ loadf[LUMP_FACES] = BSP_LoadFaces;
+ loadf[LUMP_MARKSURFACES] = BSP_LoadMarksurfaces;
+ loadf[LUMP_LEAFS] = BSP_LoadLeafs;
+ loadf[LUMP_NODES] = BSP_LoadNodes;
+ loadf[LUMP_CLIPNODES] = BSP_LoadClipnodes;
+ }else if(ver == BSP2VERSION){
+ loadf[LUMP_EDGES] = BSP2_LoadEdges;
+ loadf[LUMP_FACES] = BSP2_LoadFaces;
+ loadf[LUMP_MARKSURFACES] = BSP2_LoadMarksurfaces;
+ loadf[LUMP_LEAFS] = BSP2_LoadLeafs;
+ loadf[LUMP_NODES] = BSP2_LoadNodes;
+ loadf[LUMP_CLIPNODES] = BSP2_LoadClipnodes;
+ }else{
+ werrstr("unsupported version: %ux", ver);
+ goto err;
+ }
+
+ if(total < 4+nelem(loadf)*2*4){
+ werrstr("truncated: total=%d", total);
+ goto err;
+ }
+
+ mod->type = mod_brush;
+
+ for(i = 0; i < nelem(loadf); i++){
+ in = in0+4+2*4*order[i];
+ off = le32(in);
+ sz = le32(in);
+ if(off < 0 || sz < 0 || off+sz > total){
+ werrstr("invalid lump off=%d sz=%d total=%d", off, sz, total);
+ goto err;
+ }
+ if(loadf[order[i]](mod, in0+off, sz) != 0)
+ goto err;
+ }
+
+ BSP_MakeHull0(mod);
+
+ mod->numframes = 2; // regular and alternate animation
+ mod->flags = 0;
+
+ // set up the submodels (FIXME: this is confusing)
+ for(i = 0; i < mod->numsubmodels; i++){
+ bm = &mod->submodels[i];
+
+ mod->hulls[0].firstclipnode = bm->headnode[0];
+ for(j = 1; j < MAX_MAP_HULLS; j++){
+ mod->hulls[j].firstclipnode = bm->headnode[j];
+ mod->hulls[j].lastclipnode = mod->numclipnodes-1;
+ }
+
+ mod->firstmodelsurface = bm->firstface;
+ mod->nummodelsurfaces = bm->numfaces;
+ mod->blend = false;
+ for(j = bm->firstface; j < bm->firstface+bm->numfaces; j++){
+ if(mod->surfaces[j].flags & SURF_TRANS){
+ mod->blend = true;
+ break;
+ }
+ }
+
+ VectorCopy(bm->maxs, mod->maxs);
+ VectorCopy(bm->mins, mod->mins);
+ mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
+ mod->numleafs = bm->visleafs;
+
+ if(i < mod->numsubmodels-1){
+ snprint(name, sizeof(name), "*%d", i+1);
+ submod = Mod_FindName(name);
+ *submod = *mod;
+ strcpy(submod->name, name);
+ mod = submod;
+ }
+ }
+
+ return;
+err:
+ Host_Error("Mod_LoadBrushModel: %s: %s", mod->name, lerr());
+}
--- /dev/null
+++ b/model_bsp.c
@@ -1,0 +1,641 @@
+#include "quakedef.h"
+
+void
+BSP_SetParent(mnode_t *node, mnode_t *parent)
+{
+ node->parent = parent;
+ if(node->contents < 0)
+ return;
+ BSP_SetParent(node->children[0], node);
+ BSP_SetParent(node->children[1], node);
+}
+
+int
+BSP_CalcSurfaceExtents(model_t *mod, msurface_t *s)
+{
+ float mins[2], maxs[2], val;
+ int i,j, e;
+ mvertex_t *v;
+ mtexinfo_t *tex;
+ int bmins[2], bmaxs[2];
+
+ mins[0] = mins[1] = Q_MAXFLOAT;
+ maxs[0] = maxs[1] = -Q_MAXFLOAT;
+ tex = s->texinfo;
+
+ for(i = 0; i < s->numedges; i++){
+ e = mod->surfedges[s->firstedge+i];
+ if(e >= 0)
+ v = &mod->vertexes[mod->edges[e].v[0]];
+ else
+ v = &mod->vertexes[mod->edges[-e].v[1]];
+
+ for(j = 0; j < 2; j++){
+ val = (double)v->position[0] * (double)tex->vecs[j][0] +
+ (double)v->position[1] * (double)tex->vecs[j][1] +
+ (double)v->position[2] * (double)tex->vecs[j][2] +
+ (double)tex->vecs[j][3];
+ if(val < mins[j])
+ mins[j] = val;
+ if(val > maxs[j])
+ maxs[j] = val;
+ }
+ }
+
+ for(i = 0; i < 2; i++){
+ bmins[i] = floor(mins[i]/16.0);
+ bmaxs[i] = ceil(maxs[i]/16.0);
+
+ s->texturemins[i] = bmins[i] * 16;
+ s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
+ if((tex->flags & TEX_SPECIAL) == 0 && s->extents[i] > 2000){
+ werrstr("BSP_CalcSurfaceExtents: bad surface: texture=%s flags=%ux extents[%d]=%d",
+ tex->texture->name,
+ tex->flags,
+ i,
+ s->extents[i]
+ );
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int
+BSP_LoadTextures(model_t *mod, byte *in, int sz)
+{
+ int off, i, j, pixels, num, max, altmax, w, h;
+ byte *p, *in0;
+ texture_t *tx, *tx2;
+ texture_t *anims[10];
+ texture_t *altanims[10];
+ static const int elsz = 16+2*4+4*4;
+
+ if(sz < 1){
+ mod->textures = nil;
+ return 0;
+ }
+ if(sz < 4 || (sz % 4) != 0){
+ werrstr("funny lump size");
+ goto err;
+ }
+
+ in0 = in;
+ mod->numtextures = le32(in);
+ if(mod->numtextures*4 > sz-4){
+ werrstr("overflow? %d > %d", mod->numtextures*4, sz-4);
+ goto err;
+ }
+ mod->textures = Hunk_Alloc(mod->numtextures * sizeof(*mod->textures));
+
+ for(i = 0; i < mod->numtextures; i++){
+ off = le32(in);
+ if(off == -1)
+ continue;
+ if(off < 0 || off > sz-elsz){
+ werrstr("bad offset %d (sz %d)", off, sz);
+ goto err;
+ }
+ p = in0+off+16;
+ w = le32(p);
+ h = le32(p);
+ pixels = w*h/64*85;
+ tx = Hunk_Alloc(sizeof(*tx) + pixels);
+ strncpy(tx->name, (char*)in0+off, sizeof(tx->name)-1);
+ tx->name[sizeof(tx->name)-1] = 0;
+ for(j = 0; j < MIPLEVELS; j++)
+ tx->offsets[j] = le32(p) + sizeof(texture_t) - (16+2*4+4*4);
+ mod->textures[i] = tx;
+ tx->width = w;
+ tx->height = h;
+ // the pixels immediately follow the structures
+ memcpy(tx+1, p, pixels);
+ if(strncmp(tx->name, "sky", 3) == 0)
+ R_InitSky(tx);
+ }
+
+ // sequence the animations
+ for(i = 0; i < mod->numtextures; i++){
+ tx = mod->textures[i];
+ if(!tx || tx->name[0] != '+')
+ continue;
+ if(tx->anim_next)
+ continue; // already sequenced
+
+ // find the number of frames in the animation
+ memset(anims, 0, sizeof(anims));
+ memset(altanims, 0, sizeof(altanims));
+
+ max = tx->name[1];
+ if(max >= 'a' && max <= 'z')
+ max -= 'a' - 'A';
+ if(max >= '0' && max <= '9'){
+ max -= '0';
+ altmax = 0;
+ anims[max++] = tx;
+ }else if(max >= 'A' && max <= 'J'){
+ altmax = max - 'A';
+ max = 0;
+ altanims[altmax++] = tx;
+ }else{
+badanim:
+ werrstr("bad animating texture: %s", tx->name);
+ goto err;
+ }
+
+ for(j = i+1; j < mod->numtextures; j++){
+ tx2 = mod->textures[j];
+ if(!tx2 || tx2->name[0] != '+')
+ continue;
+ if(strcmp(tx2->name+2, tx->name+2) != 0)
+ continue;
+
+ num = tx2->name[1];
+ if(num >= 'a' && num <= 'z')
+ num -= 'a' - 'A';
+ if(num >= '0' && num <= '9'){
+ num -= '0';
+ anims[num] = tx2;
+ if(num+1 > max)
+ max = num + 1;
+ }else if(num >= 'A' && num <= 'J'){
+ num = num - 'A';
+ altanims[num] = tx2;
+ if(num+1 > altmax)
+ altmax = num+1;
+ }else{
+ goto badanim;
+ }
+ }
+
+#define ANIM_CYCLE 2
+ // link them all together
+ for(j = 0; j < max; j++){
+ tx2 = anims[j];
+ if(!tx2){
+badframe:
+ werrstr("missing frame %d of %s", j, tx->name);
+ goto err;
+ }
+ tx2->anim_total = max * ANIM_CYCLE;
+ tx2->anim_min = j * ANIM_CYCLE;
+ tx2->anim_max = (j+1) * ANIM_CYCLE;
+ tx2->anim_next = anims[(j+1) % max];
+ if(altmax)
+ tx2->alternate_anims = altanims[0];
+ }
+ for(j = 0; j < altmax; j++){
+ tx2 = altanims[j];
+ if(!tx2)
+ goto badframe;
+ tx2->anim_total = altmax * ANIM_CYCLE;
+ tx2->anim_min = j * ANIM_CYCLE;
+ tx2->anim_max = (j+1) * ANIM_CYCLE;
+ tx2->anim_next = altanims[(j+1) % altmax];
+ if(max)
+ tx2->alternate_anims = anims[0];
+ }
+ }
+
+ return 0;
+err:
+ werrstr("BSP_LoadTextures: %s", lerr());
+ return -1;
+}
+
+int
+BSP_LoadLighting(model_t *mod, byte *in, int sz)
+{
+ if(sz == 0)
+ mod->lightdata = nil;
+ else
+ memcpy(mod->lightdata = Hunk_Alloc(sz), in, sz);
+ return 0;
+}
+
+int
+BSP_LoadVisibility(model_t *mod, byte *in, int sz)
+{
+ if(sz == 0)
+ mod->visdata = nil;
+ else
+ memcpy(mod->visdata = Hunk_Alloc(sz), in, sz);
+ return 0;
+}
+
+int
+BSP_LoadEntities(model_t *mod, byte *in, int sz)
+{
+ if(sz == 0)
+ mod->entities = nil;
+ else
+ memcpy(mod->entities = Hunk_Alloc(sz), in, sz);
+ return 0;
+}
+
+int
+BSP_LoadVertexes(model_t *mod, byte *in, int sz)
+{
+ mvertex_t *out;
+ int i;
+ static const int elsz = 3*4;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadVertexes: funny lump size");
+ return -1;
+ }
+ mod->numvertexes = sz / elsz;
+ mod->vertexes = out = Hunk_Alloc(mod->numvertexes * sizeof(*out));
+ for(i = 0; i < mod->numvertexes; i++, out++){
+ out->position[0] = f32(in);
+ out->position[1] = f32(in);
+ out->position[2] = f32(in);
+ }
+ return 0;
+}
+
+int
+BSP_LoadSubmodels(model_t *mod, byte *in, int sz)
+{
+ submodel_t *out;
+ int i, j;
+ static const int elsz = 3*4+3*4+3*4+MAX_MAP_HULLS*4+4+4+4;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadSubmodels: funny lump size");
+ return -1;
+ }
+ mod->numsubmodels = sz / elsz;
+ mod->submodels = out = Hunk_Alloc(mod->numsubmodels * sizeof(*out));
+
+ for(i = 0 ; i < mod->numsubmodels; i++, out++){
+ for(j = 0; j < 3; j++)
+ out->mins[j] = f32(in) - 1.0;
+ for(j = 0; j < 3; j++)
+ out->maxs[j] = f32(in) + 1.0;
+ for(j = 0; j < 3; j++)
+ out->origin[j] = f32(in);
+ for(j = 0; j < MAX_MAP_HULLS; j++)
+ out->headnode[j] = le32(in);
+ out->visleafs = le32(in);
+ out->firstface = le32(in);
+ out->numfaces = le32(in);
+ }
+ return 0;
+}
+
+int
+BSP_LoadEdges(model_t *mod, byte *in, int sz)
+{
+ medge_t *out;
+ int i;
+ static const int elsz = 2*2;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadEdges: funny lump size");
+ return -1;
+ }
+ mod->numedges = sz / elsz;
+ // FIXME(sigrid): why +1?
+ mod->edges = out = Hunk_Alloc((mod->numedges+1) * sizeof(*out));
+
+ for(i = 0; i < mod->numedges; i++, out++){
+ out->v[0] = le16u(in);
+ out->v[1] = le16u(in);
+ }
+ return 0;
+}
+
+int
+BSP_LoadTexinfo(model_t *mod, byte *in, int sz)
+{
+ mtexinfo_t *out;
+ int i, j, k, miptex;
+ float len1, len2;
+ static const int elsz = 2*4*4+4+4;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadTexinfo: funny lump size");
+ return -1;
+ }
+ mod->numtexinfo = sz / elsz;
+ mod->texinfo = out = Hunk_Alloc(mod->numtexinfo * sizeof(*out));
+
+ for(i = 0; i < mod->numtexinfo; i++, out++){
+ for(j = 0; j < 2; j++){
+ for(k = 0; k < 4; k++)
+ out->vecs[j][k] = f32(in);
+ }
+ len1 = Length(out->vecs[0]);
+ len2 = Length(out->vecs[1]);
+ len1 = (len1 + len2)/2;
+ if (len1 < 0.32)
+ out->mipadjust = 4;
+ else if (len1 < 0.49)
+ out->mipadjust = 3;
+ else if (len1 < 0.99)
+ out->mipadjust = 2;
+ else
+ out->mipadjust = 1;
+
+ miptex = le32(in);
+ out->flags = le32(in);
+ out->texture = nil;
+ if(mod->textures != nil){
+ if(miptex >= mod->numtextures){
+ werrstr("BSP_LoadTexinfo: miptex >= mod->numtextures");
+ return -1;
+ }
+ out->texture = mod->textures[miptex];
+ }
+ if(out->texture == nil){
+ out->texture = r_notexture_mip; // texture not found
+ out->flags = 0;
+ }
+ }
+ return 0;
+}
+
+int
+BSP_LoadFaces(model_t *mod, byte *in, int sz)
+{
+ msurface_t *out;
+ int i, surfnum;
+ static const int elsz = 2+2+4+2+2+MAXLIGHTMAPS+4;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadFaces: funny lump size");
+ return -1;
+ }
+ mod->numsurfaces = sz / elsz;
+ mod->surfaces = out = Hunk_Alloc(mod->numsurfaces * sizeof(*out));
+
+ for(surfnum = 0; surfnum < mod->numsurfaces; surfnum++, out++){
+ out->plane = mod->planes + le16u(in);
+ out->flags = le16u(in) ? SURF_PLANEBACK : 0;
+ out->firstedge = le32u(in);
+ out->numedges = le16u(in);
+ out->texinfo = mod->texinfo + le16u(in);
+
+ if(BSP_CalcSurfaceExtents(mod, out) != 0)
+ return -1;
+
+ // lighting info
+
+ memmove(out->styles, in, MAXLIGHTMAPS);
+ in += MAXLIGHTMAPS;
+ out->samples = (i = le32(in)) < 0 ? nil : mod->lightdata + i;
+
+ // set the drawing flags flag
+
+ if(strncmp(out->texinfo->texture->name, "sky", 3) == 0)
+ out->flags |= SURF_DRAWSKY | SURF_DRAWTILED;
+ else if(out->texinfo->texture->name[0] == '*'){ // turbulent
+ out->flags |= SURF_DRAWTURB | SURF_DRAWTILED | SURF_TRANS;
+ for(i = 0; i < 2; i++){
+ out->extents[i] = 16384;
+ out->texturemins[i] = -8192;
+ }
+ if(strstr(out->texinfo->texture->name, "lava") != nil)
+ out->flags |= SURF_LAVA;
+ if(strstr(out->texinfo->texture->name, "slime") != nil)
+ out->flags |= SURF_SLIME;
+ if(strstr(out->texinfo->texture->name, "tele") != nil){
+ out->flags |= SURF_TELE;
+ out->flags &= ~SURF_TRANS;
+ }
+ }else if(out->texinfo->texture->name[0] == '{')
+ out->flags |= SURF_TRANS | SURF_FENCE;
+ }
+ return 0;
+}
+
+int
+BSP_LoadNodes(model_t *mod, byte *in, int sz)
+{
+ int i, j, p;
+ mnode_t *out;
+ static const int elsz = 4+2*2+3*2+3*2+2+2;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadNodes: funny lump size");
+ return -1;
+ }
+ mod->numnodes = sz / elsz;
+ mod->nodes = out = Hunk_Alloc(mod->numnodes * sizeof(*out));
+
+ for(i = 0; i < mod->numnodes; i++, out++){
+ out->plane = mod->planes + le32u(in);
+
+ for(j = 0; j < 2; j++){
+ p = le16u(in);
+ if(p >= 0 && p < mod->numnodes)
+ out->children[j] = mod->nodes + p;
+ else{
+ p = 0xffff-p;
+ assert(mod->leafs != nil);
+ if(p >= 0 && p < mod->numleafs)
+ out->children[j] = (mnode_t*)(mod->leafs + p);
+ else{
+ Con_DPrintf("BSP_LoadNodes: invalid node child\n");
+ out->children[j] = (mnode_t*)mod->leafs;
+ }
+ }
+ }
+
+ for(j = 0; j < 6; j++)
+ out->minmaxs[j] = le16(in);
+
+ out->firstsurface = le16u(in);
+ out->numsurfaces = le16u(in);
+ }
+
+ BSP_SetParent(mod->nodes, nil); // sets nodes and leafs
+ return 0;
+}
+
+int
+BSP_LoadLeafs(model_t *mod, byte *in, int sz)
+{
+ mleaf_t *out;
+ int i, j, p;
+ static const int elsz = 4+4+3*2+3*2+2+2+Namb;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadLeafs: funny lump size");
+ return -1;
+ }
+ mod->numleafs = sz / elsz;
+ mod->leafs = out = Hunk_Alloc(mod->numleafs * sizeof(*out));
+
+ for(i = 0; i < mod->numleafs; i++, out++){
+ out->contents = le32(in);
+ out->compressed_vis = (p = le32(in)) < 0 ? nil : mod->visdata + p;
+
+ for(j = 0; j < 3; j++)
+ out->minmaxs[0+j] = le16(in);
+ for(j = 0; j < 3; j++)
+ out->minmaxs[3+j] = le16(in);
+
+ out->firstmarksurface = mod->marksurfaces + le16u(in);
+ out->nummarksurfaces = le16u(in);
+
+ memmove(out->ambient_sound_level, in, Namb);
+ in += Namb;
+ }
+ return 0;
+}
+
+int
+BSP_LoadClipnodes(model_t *mod, byte *in, int sz)
+{
+ mclipnode_t *out;
+ int i;
+ hull_t *hull;
+ static const int elsz = 4+2*2;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadClipnodes: funny lump size");
+ return -1;
+ }
+ mod->numclipnodes = sz / elsz;
+ mod->clipnodes = out = Hunk_Alloc(mod->numclipnodes * sizeof(*out));
+
+ hull = &mod->hulls[1];
+ hull->clipnodes = out;
+ hull->firstclipnode = 0;
+ hull->lastclipnode = mod->numclipnodes-1;
+ hull->planes = mod->planes;
+ hull->clip_mins[0] = -16;
+ hull->clip_mins[1] = -16;
+ hull->clip_mins[2] = -24;
+ hull->clip_maxs[0] = 16;
+ hull->clip_maxs[1] = 16;
+ hull->clip_maxs[2] = 32;
+
+ hull = &mod->hulls[2];
+ hull->clipnodes = out;
+ hull->firstclipnode = 0;
+ hull->lastclipnode = mod->numclipnodes-1;
+ hull->planes = mod->planes;
+ hull->clip_mins[0] = -32;
+ hull->clip_mins[1] = -32;
+ hull->clip_mins[2] = -24;
+ hull->clip_maxs[0] = 32;
+ hull->clip_maxs[1] = 32;
+ hull->clip_maxs[2] = 64;
+
+ for(i = 0; i < mod->numclipnodes; i++, out++){
+ out->planenum = le32u(in);
+ out->children[0] = le16u(in);
+ out->children[1] = le16u(in);
+ if(out->children[0] >= mod->numclipnodes)
+ out->children[0] -= 0x10000;
+ if(out->children[1] >= mod->numclipnodes)
+ out->children[1] -= 0x10000;
+ }
+ return 0;
+}
+
+void
+BSP_MakeHull0(model_t *mod)
+{
+ mnode_t *in, *child;
+ mclipnode_t *out;
+ int i, j;
+ hull_t *hull;
+
+ hull = &mod->hulls[0];
+
+ in = mod->nodes;
+ out = Hunk_Alloc(mod->numnodes * sizeof(*out));
+
+ hull->clipnodes = out;
+ hull->firstclipnode = 0;
+ hull->lastclipnode = mod->numnodes-1;
+ hull->planes = mod->planes;
+
+ for(i = 0; i < mod->numnodes; i++, out++, in++){
+ out->planenum = in->plane - mod->planes;
+ for(j = 0; j < 2; j++){
+ child = in->children[j];
+ if(child->contents < 0)
+ out->children[j] = child->contents;
+ else
+ out->children[j] = child - mod->nodes;
+ }
+ }
+}
+
+int
+BSP_LoadMarksurfaces(model_t *mod, byte *in, int sz)
+{
+ int i, j;
+ msurface_t **out;
+ static const int elsz = 2;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadMarksurfaces: funny lump size");
+ return -1;
+ }
+ mod->nummarksurfaces = sz / elsz;
+ mod->marksurfaces = out = Hunk_Alloc(mod->nummarksurfaces * sizeof(*out));
+
+ for(i = 0; i < mod->nummarksurfaces; i++){
+ j = le16u(in);
+ if(j < 0 || j >= mod->numsurfaces){
+ werrstr("BSP_LoadMarksurfaces: bad surface number: %d", j);
+ return -1;
+ }
+ out[i] = mod->surfaces + j;
+ }
+ return 0;
+}
+
+int
+BSP_LoadSurfedges(model_t *mod, byte *in, int sz)
+{
+ int i, *out;
+ static const int elsz = 4;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadSurfedges: funny lump size");
+ return -1;
+ }
+ mod->numsurfedges = sz / elsz;
+ mod->surfedges = out = Hunk_Alloc(mod->numsurfedges * sizeof(*out));
+
+ for(i = 0; i < mod->numsurfedges; i++)
+ out[i] = le32(in);
+ return 0;
+}
+
+int
+BSP_LoadPlanes(model_t *mod, byte *in, int sz)
+{
+ int i, j, bits;
+ mplane_t *out;
+ static const int elsz = 3*4+4+4;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadPlanes: funny lump size");
+ return -1;
+ }
+ mod->numplanes = sz / elsz;
+ // FIXME(sigrid): why " * 2"???
+ mod->planes = out = Hunk_Alloc(mod->numplanes * 2 * sizeof(*out));
+
+ for(i = 0; i < mod->numplanes; i++, out++){
+ bits = 0;
+ for(j = 0; j < 3; j++){
+ if((out->normal[j] = f32(in)) < 0)
+ bits |= 1<<j;
+ }
+
+ out->dist = f32(in);
+ out->type = le32(in);
+ out->signbits = bits;
+ }
+ return 0;
+}
--- /dev/null
+++ b/model_bsp2.c
@@ -1,0 +1,231 @@
+#include "quakedef.h"
+
+void BSP_SetParent(mnode_t *node, mnode_t *parent);
+void BSP_MakeHull0(model_t *mod);
+int BSP_CalcSurfaceExtents(model_t *mod, msurface_t *s);
+
+int
+BSP2_LoadEdges(model_t *mod, byte *in, int sz)
+{
+ medge_t *out;
+ int i;
+ static const int elsz = 2*4;
+
+ if(sz % elsz){
+ werrstr("BSP2_LoadEdges: funny lump size");
+ return -1;
+ }
+ mod->numedges = sz / elsz;
+ // FIXME(sigrid): why +1?
+ mod->edges = out = Hunk_Alloc((mod->numedges+1) * sizeof(*out));
+
+ for(i = 0; i < mod->numedges; i++, out++){
+ out->v[0] = le32u(in);
+ out->v[1] = le32u(in);
+ }
+ return 0;
+}
+
+int
+BSP2_LoadLeafs(model_t *mod, byte *in, int sz)
+{
+ mleaf_t *out;
+ int i, j, p;
+ static const int elsz = 4+4+3*4+3*4+4+4+Namb;
+
+ if(sz % elsz){
+ werrstr("BSP2_LoadLeafs: funny lump size");
+ return -1;
+ }
+ mod->numleafs = sz / elsz;
+ mod->leafs = out = Hunk_Alloc(mod->numleafs * sizeof(*out));
+
+ for(i = 0; i < mod->numleafs; i++, out++){
+ out->contents = le32(in);
+ out->compressed_vis = (p = le32(in)) < 0 ? nil : mod->visdata + p;
+
+ for(j = 0; j < 3; j++)
+ out->minmaxs[0+j] = f32(in);
+ for(j = 0; j < 3; j++)
+ out->minmaxs[3+j] = f32(in);
+
+ out->firstmarksurface = mod->marksurfaces + le32u(in);
+ out->nummarksurfaces = le32u(in);
+
+ memmove(out->ambient_sound_level, in, Namb);
+ in += Namb;
+ }
+ return 0;
+}
+
+int
+BSP2_LoadFaces(model_t *mod, byte *in, int sz)
+{
+ msurface_t *out;
+ int i, surfnum;
+ static const int elsz = 4+4+4+4+4+MAXLIGHTMAPS+4;
+
+ if(sz % elsz){
+ werrstr("BSP2_LoadFaces: funny lump size");
+ return -1;
+ }
+ mod->numsurfaces = sz / elsz;
+ mod->surfaces = out = Hunk_Alloc(mod->numsurfaces * sizeof(*out));
+
+ for(surfnum = 0; surfnum < mod->numsurfaces; surfnum++, out++){
+ out->plane = mod->planes + le32u(in);
+ out->flags = le32u(in) ? SURF_PLANEBACK : 0;
+ out->firstedge = le32u(in);
+ out->numedges = le32u(in);
+ out->texinfo = mod->texinfo + le32u(in);
+
+ if(BSP_CalcSurfaceExtents(mod, out) != 0)
+ return -1;
+
+ // lighting info
+
+ memmove(out->styles, in, MAXLIGHTMAPS);
+ in += MAXLIGHTMAPS;
+ out->samples = (i = le32(in)) < 0 ? nil : mod->lightdata + i;
+
+ // set the drawing flags flag
+
+ if(strncmp(out->texinfo->texture->name, "sky", 3) == 0)
+ out->flags |= SURF_DRAWSKY | SURF_DRAWTILED;
+ else if(out->texinfo->texture->name[0] == '*'){ // turbulent
+ out->flags |= SURF_DRAWTURB | SURF_DRAWTILED | SURF_TRANS;
+ for(i = 0; i < 2; i++){
+ out->extents[i] = 16384;
+ out->texturemins[i] = -8192;
+ }
+ if(strstr(out->texinfo->texture->name, "lava") != nil)
+ out->flags |= SURF_LAVA;
+ if(strstr(out->texinfo->texture->name, "slime") != nil)
+ out->flags |= SURF_SLIME;
+ if(strstr(out->texinfo->texture->name, "tele") != nil){
+ out->flags |= SURF_TELE;
+ out->flags &= ~SURF_TRANS;
+ }
+ }else if(out->texinfo->texture->name[0] == '{')
+ out->flags |= SURF_TRANS | SURF_FENCE;
+ }
+ return 0;
+}
+
+int
+BSP2_LoadNodes(model_t *mod, byte *in, int sz)
+{
+ int i, j, p;
+ mnode_t *out;
+ static const int elsz = 4+2*4+3*4+3*4+4+4;
+
+ if(sz % elsz){
+ werrstr("BSP_LoadNodes: funny lump size");
+ return -1;
+ }
+ mod->numnodes = sz / elsz;
+ mod->nodes = out = Hunk_Alloc(mod->numnodes * sizeof(*out));
+
+ for(i = 0; i < mod->numnodes; i++, out++){
+ out->plane = mod->planes + le32u(in);
+
+ for(j = 0; j < 2; j++){
+ p = le32(in);
+ if(p >= 0 && p < mod->numnodes)
+ out->children[j] = mod->nodes + p;
+ else{
+ p = -1-p;
+ if(p >= 0 && p < mod->numleafs)
+ out->children[j] = (mnode_t*)(mod->leafs + p);
+ else{
+ Con_DPrintf("BSP2_LoadNodes: invalid node child\n");
+ out->children[j] = (mnode_t*)mod->leafs;
+ }
+ }
+ }
+
+ for(j = 0; j < 6; j++)
+ out->minmaxs[j] = f32(in);
+
+ out->firstsurface = le32u(in);
+ out->numsurfaces = le32u(in);
+ }
+
+ BSP_SetParent(mod->nodes, nil); // sets nodes and leafs
+ return 0;
+}
+
+int
+BSP2_LoadClipnodes(model_t *mod, byte *in, int sz)
+{
+ mclipnode_t *out;
+ int i;
+ hull_t *hull;
+ static const int elsz = 4+2*4;
+
+ if(sz % elsz){
+ werrstr("BSP2_LoadClipnodes: funny lump size");
+ return -1;
+ }
+ mod->numclipnodes = sz / elsz;
+ mod->clipnodes = out = Hunk_Alloc(mod->numclipnodes * sizeof(*out));
+
+ hull = &mod->hulls[1];
+ hull->clipnodes = out;
+ hull->firstclipnode = 0;
+ hull->lastclipnode = mod->numclipnodes-1;
+ hull->planes = mod->planes;
+ hull->clip_mins[0] = -16;
+ hull->clip_mins[1] = -16;
+ hull->clip_mins[2] = -24;
+ hull->clip_maxs[0] = 16;
+ hull->clip_maxs[1] = 16;
+ hull->clip_maxs[2] = 32;
+
+ hull = &mod->hulls[2];
+ hull->clipnodes = out;
+ hull->firstclipnode = 0;
+ hull->lastclipnode = mod->numclipnodes-1;
+ hull->planes = mod->planes;
+ hull->clip_mins[0] = -32;
+ hull->clip_mins[1] = -32;
+ hull->clip_mins[2] = -24;
+ hull->clip_maxs[0] = 32;
+ hull->clip_maxs[1] = 32;
+ hull->clip_maxs[2] = 64;
+
+ for(i = 0; i < mod->numclipnodes; i++, out++){
+ out->planenum = le32u(in);
+ out->children[0] = le32u(in);
+ out->children[1] = le32u(in);
+ if(out->children[0] >= mod->numclipnodes)
+ out->children[0] -= 0x10000;
+ if(out->children[1] >= mod->numclipnodes)
+ out->children[1] -= 0x10000;
+ }
+ return 0;
+}
+
+int
+BSP2_LoadMarksurfaces(model_t *mod, byte *in, int sz)
+{
+ int i, j;
+ msurface_t **out;
+
+ if(sz % 4){
+ werrstr("BSP2_LoadMarksurfaces: funny lump size");
+ return -1;
+ }
+ mod->nummarksurfaces = sz / 4;
+ mod->marksurfaces = out = Hunk_Alloc(mod->nummarksurfaces * sizeof(*out));
+
+ for(i = 0; i < mod->nummarksurfaces; i++){
+ j = le32u(in);
+ if(j < 0 || j >= mod->numsurfaces){
+ werrstr("BSP2_LoadMarksurfaces: bad surface number: %d", j);
+ return -1;
+ }
+ out[i] = mod->surfaces + j;
+ }
+ return 0;
+}
--- a/unix/u.h
+++ b/unix/u.h
@@ -38,7 +38,7 @@
#define setmalloctag(p, t) do{USED(p); USED(t);}while(0)
extern char lasterr[256];
-#define werrstr(fmt, ...) do{snprint(lasterr, sizeof(lasterr), fmt, __VA_ARGS__); }while(0)
+#define werrstr(fmt...) do{snprint(lasterr, sizeof(lasterr), fmt); }while(0)
char *seprint(char *, char *, char *, ...);
int nrand(int);