]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
added back support for textures smaller than 4 pixels wide (Nehahra uses one)
[xonotic/darkplaces.git] / model_brush.c
index e62b5272bfd0491aa021b5ef6edf59f8ab600660..8604c43b716e9a283c1d9ee1d0c3a95c2882a7d1 100644 (file)
@@ -45,6 +45,26 @@ Mod_PointInLeaf
 ===============
 */
 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
+{
+       mnode_t         *node;
+       
+//     if (!model || !model->nodes)
+//             Sys_Error ("Mod_PointInLeaf: bad model");
+
+       node = model->nodes;
+       if (node->contents < 0)
+               return (mleaf_t *)node;
+       while (1)
+       {
+               node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist];
+               if (node->contents < 0)
+                       return (mleaf_t *)node;
+       }
+       
+       return NULL;    // never reached
+}
+/*
+mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
 {
        mnode_t         *node;
        float           d;
@@ -68,7 +88,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
        
        return NULL;    // never reached
 }
-
+*/
 
 /*
 ===================
@@ -122,7 +142,7 @@ byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
        return Mod_DecompressVis (leaf->compressed_vis, model);
 }
 
-byte   *mod_base;
+extern byte    *mod_base;
 
 extern cvar_t r_fullbrights;
 
@@ -133,13 +153,14 @@ Mod_LoadTextures
 */
 void Mod_LoadTextures (lump_t *l)
 {
-       int             i, j, num, max, altmax, bytesperpixel, freeimage, transparent, fullbrights;
+       int             i, j, num, max, altmax;
        miptex_t        *mt;
        texture_t       *tx, *tx2;
        texture_t       *anims[10];
        texture_t       *altanims[10];
        dmiptexlump_t *m;
-       byte *data;
+       byte    *data;
+       int             *dofs;
 
        if (!l->filelen)
        {
@@ -152,14 +173,16 @@ void Mod_LoadTextures (lump_t *l)
        m->nummiptex = LittleLong (m->nummiptex);
        
        loadmodel->numtextures = m->nummiptex;
-       loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
+       loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures), va("%s texture headers", loadname));
 
+       // just to work around bounds checking when debugging with it (array index out of bounds error thing)
+       dofs = m->dataofs;
        for (i=0 ; i<m->nummiptex ; i++)
        {
-               m->dataofs[i] = LittleLong(m->dataofs[i]);
-               if (m->dataofs[i] == -1)
+               dofs[i] = LittleLong(dofs[i]);
+               if (dofs[i] == -1)
                        continue;
-               mt = (miptex_t *)((byte *)m + m->dataofs[i]);
+               mt = (miptex_t *)((byte *)m + dofs[i]);
                mt->width = LittleLong (mt->width);
                mt->height = LittleLong (mt->height);
                for (j=0 ; j<MIPLEVELS ; j++)
@@ -168,99 +191,149 @@ void Mod_LoadTextures (lump_t *l)
                if ( (mt->width & 15) || (mt->height & 15) )
                        Host_Error ("Texture %s is not 16 aligned", mt->name);
                // LordHavoc: rewriting the map texture loader for GLQuake
-               tx = Hunk_AllocName (sizeof(texture_t), loadname );
+               tx = Hunk_AllocName (sizeof(texture_t), va("%s textures", loadname));
                loadmodel->textures[i] = tx;
 
-               memcpy (tx->name, mt->name, sizeof(tx->name));
-               tx->width = mt->width;
-               tx->height = mt->height;
+               // LordHavoc: force all names to lowercase and make sure they are terminated while copying
+               for (j = 0;mt->name[j] && j < 15;j++)
+               {
+                       if (mt->name[j] >= 'A' && mt->name[j] <= 'Z')
+                               tx->name[j] = mt->name[j] + ('a' - 'A');
+                       else
+                               tx->name[j] = mt->name[j];
+               }
+               for (;j < 16;j++)
+                       tx->name[j] = 0;
+
                for (j=0 ; j<MIPLEVELS ; j++)
                        tx->offsets[j] = 0;
-               freeimage = TRUE;
-               bytesperpixel = 4;
-               fullbrights = FALSE;
-               transparent = TRUE;
-               data = loadimagepixels(mt->name, FALSE, 0, 0); //tx->width, tx->height);
-               if (!data) // no external texture found
+               tx->transparent = false;
+               data = loadimagepixels(tx->name, false, 0, 0);
+               if (data)
                {
-                       freeimage = FALSE;
-                       transparent = FALSE;
-                       bytesperpixel = 1;
-                       if (!hlbsp && mt->offsets[0]) // texture included
+                       if (!hlbsp && !strncmp(tx->name,"sky",3) && image_width == 256 && image_height == 128) // LordHavoc: HL sky textures are entirely unrelated
                        {
-                               data = (byte *)((int) mt + mt->offsets[0]);
-                               if (r_fullbrights.value && mt->name[0] != '*')
-                               {
-                                       for (j = 0;j < tx->width*tx->height;j++)
-                                               if (data[j] >= 224) // fullbright
-                                               {
-                                                       fullbrights = TRUE;
-                                                       break;
-                                               }
-                               }
+                               tx->width = image_width;
+                               tx->height = image_height;
+                               tx->transparent = false;
+                               tx->texture = NULL;
+                               tx->glowtexture = NULL;
+                               R_InitSky (data, 4);
                        }
-                       else // no texture, and no external replacement texture was found
+                       else
                        {
-                               tx->width = tx->height = 16;
-                               data = (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]);
+                               tx->width = mt->width;
+                               tx->height = mt->height;
+                               tx->transparent = Image_CheckAlpha(data, image_width * image_height, true);
+                               tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE);
+                               tx->glowtexture = NULL;
                        }
+                       qfree(data);
                }
                else
                {
-                       tx->width = image_width;
-                       tx->height = image_height;
-               }
-               if (!hlbsp && !strncmp(mt->name,"sky",3) && tx->width == 256 && tx->height == 128) // LordHavoc: HL sky textures are entirely unrelated
-               {
-                       tx->transparent = FALSE;
-                       R_InitSky (data, bytesperpixel);
-               }
-               else
-               {
-                       tx->transparent = transparent;
-                       if (fullbrights)
+                       if (!hlbsp && !strncmp(tx->name,"sky",3) && mt->width == 256 && mt->height == 128) // LordHavoc: HL sky textures are entirely unrelated
                        {
-                               char name[64];
-                               byte *data2;
-                               data2 = malloc(tx->width*tx->height);
-                               for (j = 0;j < tx->width*tx->height;j++)
-                                       data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights
-                               tx->gl_texturenum = GL_LoadTexture (tx->name, tx->width, tx->height, data2, true, transparent, 1);
-                               strcpy(name, tx->name);
-                               strcat(name, "_glow");
-                               for (j = 0;j < tx->width*tx->height;j++)
-                                       data2[j] = data[j] >= 224 ? data[j] : 0; // only fullbrights
-                               tx->gl_glowtexturenum = GL_LoadTexture (name, tx->width, tx->height, data2, true, transparent, 1);
-                               free(data2);
+                               tx->width = mt->width;
+                               tx->height = mt->height;
+                               tx->transparent = false;
+                               tx->texture = NULL;
+                               tx->glowtexture = NULL;
+                               R_InitSky ((byte *)((int) mt + mt->offsets[0]), 1);
                        }
                        else
                        {
-                               tx->gl_texturenum = GL_LoadTexture (tx->name, tx->width, tx->height, data, true, transparent, bytesperpixel);
-                               tx->gl_glowtexturenum = 0;
+                               if (hlbsp)
+                               {
+                                       if (mt->offsets[0]) // texture included
+                                       {
+                                               data = W_ConvertWAD3Texture(mt);
+                                               if (data)
+                                               {
+                                                       tx->width = mt->width;
+                                                       tx->height = mt->height;
+                                                       tx->transparent = Image_CheckAlpha(data, mt->width * mt->height, true);
+                                                       tx->texture = R_LoadTexture (tx->name, mt->width, mt->height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE);
+                                                       tx->glowtexture = NULL;
+                                                       qfree(data);
+                                               }
+                                       }
+                                       if (!data)
+                                       {
+                                               data = W_GetTexture(mt->name);
+                                               // get the size from the wad texture
+                                               if (data)
+                                               {
+                                                       tx->width = image_width;
+                                                       tx->height = image_height;
+                                                       tx->transparent = Image_CheckAlpha(data, image_width * image_height, true);
+                                                       tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE);
+                                                       tx->glowtexture = NULL;
+                                                       qfree(data);
+                                               }
+                                       }
+                                       if (!data)
+                                       {
+                                               tx->width = r_notexture_mip->width;
+                                               tx->height = r_notexture_mip->height;
+                                               tx->transparent = false;
+                                               tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE);
+                                               tx->glowtexture = NULL;
+                                       }
+                               }
+                               else
+                               {
+                                       if (mt->offsets[0]) // texture included
+                                       {
+                                               int fullbrights;
+                                               data = (byte *)((int) mt + mt->offsets[0]);
+                                               tx->width = mt->width;
+                                               tx->height = mt->height;
+                                               tx->transparent = false;
+                                               fullbrights = false;
+                                               if (r_fullbrights.value && tx->name[0] != '*')
+                                               {
+                                                       for (j = 0;j < tx->width*tx->height;j++)
+                                                       {
+                                                               if (data[j] >= 224) // fullbright
+                                                               {
+                                                                       fullbrights = true;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                               if (fullbrights)
+                                               {
+                                                       char name[64];
+                                                       byte *data2;
+                                                       data2 = qmalloc(tx->width*tx->height);
+                                                       for (j = 0;j < tx->width*tx->height;j++)
+                                                               data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights
+                                                       tx->texture = R_LoadTexture (tx->name, tx->width, tx->height, data2, TEXF_MIPMAP | TEXF_PRECACHE);
+                                                       strcpy(name, tx->name);
+                                                       strcat(name, "_glow");
+                                                       for (j = 0;j < tx->width*tx->height;j++)
+                                                               data2[j] = data[j] >= 224 ? data[j] : 0; // only fullbrights
+                                                       tx->glowtexture = R_LoadTexture (name, tx->width, tx->height, data2, TEXF_MIPMAP | TEXF_PRECACHE);
+                                                       qfree(data2);
+                                               }
+                                               else
+                                               {
+                                                       tx->texture = R_LoadTexture (tx->name, tx->width, tx->height, data, TEXF_MIPMAP | TEXF_PRECACHE);
+                                                       tx->glowtexture = NULL;
+                                               }
+                                       }
+                                       else // no texture, and no external replacement texture was found
+                                       {
+                                               tx->width = r_notexture_mip->width;
+                                               tx->height = r_notexture_mip->height;
+                                               tx->transparent = false;
+                                               tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE);
+                                               tx->glowtexture = NULL;
+                                       }
+                               }
                        }
                }
-               if (freeimage)
-                       free(data);
-
-               /*
-               pixels = mt->width*mt->height/64*85;
-               tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
-               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)) 
-                       R_InitSky (tx);
-               else
-                       tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false, 1);
-               */
        }
 
 //
@@ -272,7 +345,7 @@ void Mod_LoadTextures (lump_t *l)
                if (!tx || tx->name[0] != '+')
                        continue;
                if (tx->anim_next)
-                       continue;       // allready sequenced
+                       continue;       // already sequenced
 
        // find the number of frames in the animation
                memset (anims, 0, sizeof(anims));
@@ -369,11 +442,9 @@ void Mod_LoadLighting (lump_t *l)
        byte d;
        char litfilename[1024];
        loadmodel->lightdata = NULL;
-       if (!l->filelen)
-               return;
        if (hlbsp) // LordHavoc: load the colored lighting data straight
        {
-               loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
+               loadmodel->lightdata = Hunk_AllocName ( l->filelen, va("%s lightmaps", loadname));
                memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
        }
        else // LordHavoc: bsp version 29 (normal white lighting)
@@ -390,6 +461,7 @@ void Mod_LoadLighting (lump_t *l)
                                i = LittleLong(((int *)data)[1]);
                                if (i == 1)
                                {
+                                       Con_DPrintf("%s loaded", litfilename);
                                        loadmodel->lightdata = data + 8;
                                        return;
                                }
@@ -400,7 +472,9 @@ void Mod_LoadLighting (lump_t *l)
                                Con_Printf("Corrupt .lit file (old version?), ignoring\n");
                }
                // LordHavoc: oh well, expand the white lighting data
-               loadmodel->lightdata = Hunk_AllocName ( l->filelen*3, litfilename);
+               if (!l->filelen)
+                       return;
+               loadmodel->lightdata = Hunk_AllocName ( l->filelen*3, va("%s lightmaps", loadname));
                in = loadmodel->lightdata + l->filelen*2; // place the file at the end, so it will not be overwritten until the very last write
                out = loadmodel->lightdata;
                memcpy (in, mod_base + l->fileofs, l->filelen);
@@ -427,7 +501,7 @@ void Mod_LoadVisibility (lump_t *l)
                loadmodel->visdata = NULL;
                return;
        }
-       loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);    
+       loadmodel->visdata = Hunk_AllocName ( l->filelen, va("%s visdata", loadname));
        memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
 }
 
@@ -447,7 +521,7 @@ void Mod_LoadEntities (lump_t *l)
                loadmodel->entities = NULL;
                return;
        }
-       loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);   
+       loadmodel->entities = Hunk_AllocName ( l->filelen, va("%s entities", loadname));
        memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
 
        if (isworldmodel)
@@ -470,7 +544,7 @@ void Mod_LoadVertexes (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s vertices", loadname));
 
        loadmodel->vertexes = out;
        loadmodel->numvertexes = count;
@@ -498,7 +572,7 @@ void Mod_LoadSubmodels (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s submodels", loadname));
 
        loadmodel->submodels = out;
        loadmodel->numsubmodels = count;
@@ -534,7 +608,7 @@ void Mod_LoadEdges (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);   
+       out = Hunk_AllocName ( (count + 1) * sizeof(*out), va("%s edges", loadname));
 
        loadmodel->edges = out;
        loadmodel->numedges = count;
@@ -555,7 +629,7 @@ void Mod_LoadTexinfo (lump_t *l)
 {
        texinfo_t *in;
        mtexinfo_t *out;
-       int     i, j, count;
+       int     i, j, k, count;
        int             miptex;
        float   len1, len2;
 
@@ -563,15 +637,16 @@ void Mod_LoadTexinfo (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s texinfo", loadname));
 
        loadmodel->texinfo = out;
        loadmodel->numtexinfo = count;
 
        for ( i=0 ; i<count ; i++, in++, out++)
        {
-               for (j=0 ; j<8 ; j++)
-                       out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
+               for (k=0 ; k<2 ; k++)
+                       for (j=0 ; j<4 ; j++)
+                               out->vecs[k][j] = LittleFloat (in->vecs[k][j]);
                len1 = Length (out->vecs[0]);
                len2 = Length (out->vecs[1]);
                len1 = (len1 + len2)/2;
@@ -597,6 +672,7 @@ void Mod_LoadTexinfo (lump_t *l)
                {
                        out->texture = r_notexture_mip; // checkerboard texture
                        out->flags = 0;
+                       out->texture->transparent = false;
                }
                else
                {
@@ -607,9 +683,8 @@ void Mod_LoadTexinfo (lump_t *l)
                        {
                                out->texture = r_notexture_mip; // texture not found
                                out->flags = 0;
+                               out->texture->transparent = false;
                        }
-                       else
-                               out->texture->transparent = FALSE;
                }
        }
 }
@@ -662,7 +737,8 @@ void CalcSurfaceExtents (msurface_t *s)
 
                s->texturemins[i] = bmins[i] * 16;
                s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
-               if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
+//             if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512)
+               if ((tex->flags & TEX_SPECIAL) == 0 && (s->extents[i]+1) > (256*16))
                        Host_Error ("Bad surface extents");
        }
 }
@@ -687,7 +763,7 @@ void Mod_LoadFaces (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s faces", loadname));
 
        loadmodel->surfaces = out;
        loadmodel->numsurfaces = count;
@@ -738,7 +814,7 @@ void Mod_LoadFaces (lump_t *l)
 //             if (!strncmp(out->texinfo->texture->name,"*",1))                // turbulent
                if (out->texinfo->texture->name[0] == '*') // LordHavoc: faster check
                {
-                       out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
+                       out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED | SURF_LIGHTBOTHSIDES);
                        // LordHavoc: some turbulent textures should be fullbright and solid
                        if (!strncmp(out->texinfo->texture->name,"*lava",5)
                         || !strncmp(out->texinfo->texture->name,"*teleport",9)
@@ -786,7 +862,7 @@ void Mod_LoadNodes (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s nodes", loadname));
 
        loadmodel->nodes = out;
        loadmodel->numnodes = count;
@@ -833,7 +909,7 @@ void Mod_LoadLeafs (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s leafs", loadname));
 
        loadmodel->leafs = out;
        loadmodel->numleafs = count;
@@ -890,40 +966,83 @@ void Mod_LoadClipnodes (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s clipnodes", loadname));
 
        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;
+       if (hlbsp)
+       {
+               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] = -36;
+               hull->clip_maxs[0] = 16;
+               hull->clip_maxs[1] = 16;
+               hull->clip_maxs[2] = 36;
+
+               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] = -32;
+               hull->clip_maxs[0] = 32;
+               hull->clip_maxs[1] = 32;
+               hull->clip_maxs[2] = 32;
+
+               hull = &loadmodel->hulls[3];
+               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] = -18;
+               hull->clip_maxs[0] = 16;
+               hull->clip_maxs[1] = 16;
+               hull->clip_maxs[2] = 18;
+       }
+       else
+       {
+               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++, in++)
        {
                out->planenum = LittleLong(in->planenum);
                out->children[0] = LittleShort(in->children[0]);
                out->children[1] = LittleShort(in->children[1]);
+               if (out->children[0] >= count || out->children[1] >= count)
+                       Host_Error("Corrupt clipping hull (out of range child)\n");
        }
 }
 
@@ -945,7 +1064,7 @@ void Mod_MakeHull0 (void)
        
        in = loadmodel->nodes;
        count = loadmodel->numnodes;
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s hull0", loadname));
 
        hull->clipnodes = out;
        hull->firstclipnode = 0;
@@ -981,7 +1100,7 @@ void Mod_LoadMarksurfaces (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s marksurfaces", loadname));
 
        loadmodel->marksurfaces = out;
        loadmodel->nummarksurfaces = count;
@@ -1009,7 +1128,7 @@ void Mod_LoadSurfedges (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*sizeof(*out), loadname);   
+       out = Hunk_AllocName ( count*sizeof(*out), va("%s surfedges", loadname));
 
        loadmodel->surfedges = out;
        loadmodel->numsurfedges = count;
@@ -1036,7 +1155,7 @@ void Mod_LoadPlanes (lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       out = Hunk_AllocName ( count*2*sizeof(*out), loadname); 
+       out = Hunk_AllocName ( count*2*sizeof(*out), va("%s planes", loadname));
 
        loadmodel->planes = out;
        loadmodel->numplanes = count;
@@ -1074,7 +1193,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
        header = (dheader_t *)buffer;
 
        i = LittleLong (header->version);
-       if (i != BSPVERSION & i != 30)
+       if (i != BSPVERSION && i != 30)
                Host_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i or 30 (HalfLife))", mod->name, i, BSPVERSION);
        hlbsp = i == 30;
        halflifebsp.value = hlbsp;