2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 byte mod_novis[MAX_MAP_LEAFS/8];
25 qboolean hlbsp; // LordHavoc: true if it is a HalfLife BSP file (version 30)
27 cvar_t gl_subdivide_size = {"gl_subdivide_size", "128", true};
28 cvar_t halflifebsp = {"halflifebsp", "0"};
35 void Mod_BrushInit (void)
37 Cvar_RegisterVariable (&gl_subdivide_size);
38 Cvar_RegisterVariable (&halflifebsp);
39 memset (mod_novis, 0xff, sizeof(mod_novis));
47 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
51 // if (!model || !model->nodes)
52 // Sys_Error ("Mod_PointInLeaf: bad model");
55 if (node->contents < 0)
56 return (mleaf_t *)node;
59 node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist];
60 if (node->contents < 0)
61 return (mleaf_t *)node;
64 return NULL; // never reached
67 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
73 if (!model || !model->nodes)
74 Sys_Error ("Mod_PointInLeaf: bad model");
79 if (node->contents < 0)
80 return (mleaf_t *)node;
82 d = DotProduct (p,plane->normal) - plane->dist;
84 node = node->children[0];
86 node = node->children[1];
89 return NULL; // never reached
98 byte *Mod_DecompressVis (byte *in, model_t *model)
100 static byte decompressed[MAX_MAP_LEAFS/8];
105 row = (model->numleafs+7)>>3;
109 { // no vis info, so make all visible
133 } while (out - decompressed < row);
138 byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
140 if (leaf == model->leafs)
142 return Mod_DecompressVis (leaf->compressed_vis, model);
145 extern byte *mod_base;
147 extern cvar_t r_fullbrights;
154 void Mod_LoadTextures (lump_t *l)
156 int i, j, num, max, altmax;
159 texture_t *anims[10];
160 texture_t *altanims[10];
167 loadmodel->textures = NULL;
171 m = (dmiptexlump_t *)(mod_base + l->fileofs);
173 m->nummiptex = LittleLong (m->nummiptex);
175 loadmodel->numtextures = m->nummiptex;
176 loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures), va("%s texture headers", loadname));
178 // just to work around bounds checking when debugging with it (array index out of bounds error thing)
180 for (i=0 ; i<m->nummiptex ; i++)
182 dofs[i] = LittleLong(dofs[i]);
185 mt = (miptex_t *)((byte *)m + dofs[i]);
186 mt->width = LittleLong (mt->width);
187 mt->height = LittleLong (mt->height);
188 for (j=0 ; j<MIPLEVELS ; j++)
189 mt->offsets[j] = LittleLong (mt->offsets[j]);
191 if ( (mt->width & 15) || (mt->height & 15) )
192 Host_Error ("Texture %s is not 16 aligned", mt->name);
193 // LordHavoc: rewriting the map texture loader for GLQuake
194 tx = Hunk_AllocName (sizeof(texture_t), va("%s textures", loadname));
195 loadmodel->textures[i] = tx;
197 // LordHavoc: force all names to lowercase and make sure they are terminated while copying
198 for (j = 0;mt->name[j] && j < 15;j++)
200 if (mt->name[j] >= 'A' && mt->name[j] <= 'Z')
201 tx->name[j] = mt->name[j] + ('a' - 'A');
203 tx->name[j] = mt->name[j];
208 for (j=0 ; j<MIPLEVELS ; j++)
210 tx->transparent = false;
211 data = loadimagepixels(tx->name, false, 0, 0);
214 if (!hlbsp && !strncmp(tx->name,"sky",3) && image_width == 256 && image_height == 128) // LordHavoc: HL sky textures are entirely unrelated
216 tx->width = image_width;
217 tx->height = image_height;
218 tx->transparent = false;
220 tx->glowtexture = NULL;
225 tx->width = mt->width;
226 tx->height = mt->height;
227 tx->transparent = Image_CheckAlpha(data, image_width * image_height, true);
228 tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE);
229 tx->glowtexture = NULL;
235 if (!hlbsp && !strncmp(tx->name,"sky",3) && mt->width == 256 && mt->height == 128) // LordHavoc: HL sky textures are entirely unrelated
237 tx->width = mt->width;
238 tx->height = mt->height;
239 tx->transparent = false;
241 tx->glowtexture = NULL;
242 R_InitSky ((byte *)((int) mt + mt->offsets[0]), 1);
248 if (mt->offsets[0]) // texture included
250 data = W_ConvertWAD3Texture(mt);
253 tx->width = mt->width;
254 tx->height = mt->height;
255 tx->transparent = Image_CheckAlpha(data, mt->width * mt->height, true);
256 tx->texture = R_LoadTexture (tx->name, mt->width, mt->height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE);
257 tx->glowtexture = NULL;
263 data = W_GetTexture(mt->name);
264 // get the size from the wad texture
267 tx->width = image_width;
268 tx->height = image_height;
269 tx->transparent = Image_CheckAlpha(data, image_width * image_height, true);
270 tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE);
271 tx->glowtexture = NULL;
277 tx->width = r_notexture_mip->width;
278 tx->height = r_notexture_mip->height;
279 tx->transparent = false;
280 tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE);
281 tx->glowtexture = NULL;
286 if (mt->offsets[0]) // texture included
289 data = (byte *)((int) mt + mt->offsets[0]);
290 tx->width = mt->width;
291 tx->height = mt->height;
292 tx->transparent = false;
294 if (r_fullbrights.value && tx->name[0] != '*')
296 for (j = 0;j < tx->width*tx->height;j++)
298 if (data[j] >= 224) // fullbright
309 data2 = qmalloc(tx->width*tx->height);
310 for (j = 0;j < tx->width*tx->height;j++)
311 data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights
312 tx->texture = R_LoadTexture (tx->name, tx->width, tx->height, data2, TEXF_MIPMAP | TEXF_PRECACHE);
313 strcpy(name, tx->name);
314 strcat(name, "_glow");
315 for (j = 0;j < tx->width*tx->height;j++)
316 data2[j] = data[j] >= 224 ? data[j] : 0; // only fullbrights
317 tx->glowtexture = R_LoadTexture (name, tx->width, tx->height, data2, TEXF_MIPMAP | TEXF_PRECACHE);
322 tx->texture = R_LoadTexture (tx->name, tx->width, tx->height, data, TEXF_MIPMAP | TEXF_PRECACHE);
323 tx->glowtexture = NULL;
326 else // no texture, and no external replacement texture was found
328 tx->width = r_notexture_mip->width;
329 tx->height = r_notexture_mip->height;
330 tx->transparent = false;
331 tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE);
332 tx->glowtexture = NULL;
340 // sequence the animations
342 for (i=0 ; i<m->nummiptex ; i++)
344 tx = loadmodel->textures[i];
345 if (!tx || tx->name[0] != '+')
348 continue; // already sequenced
350 // find the number of frames in the animation
351 memset (anims, 0, sizeof(anims));
352 memset (altanims, 0, sizeof(altanims));
356 if (max >= 'a' && max <= 'z')
358 if (max >= '0' && max <= '9')
365 else if (max >= 'A' && max <= 'J')
369 altanims[altmax] = tx;
373 Host_Error ("Bad animating texture %s", tx->name);
375 for (j=i+1 ; j<m->nummiptex ; j++)
377 tx2 = loadmodel->textures[j];
378 if (!tx2 || tx2->name[0] != '+')
380 if (strcmp (tx2->name+2, tx->name+2))
384 if (num >= 'a' && num <= 'z')
386 if (num >= '0' && num <= '9')
393 else if (num >= 'A' && num <= 'J')
401 Host_Error ("Bad animating texture %s", tx->name);
405 // link them all together
406 for (j=0 ; j<max ; j++)
410 Host_Error ("Missing frame %i of %s",j, tx->name);
411 tx2->anim_total = max * ANIM_CYCLE;
412 tx2->anim_min = j * ANIM_CYCLE;
413 tx2->anim_max = (j+1) * ANIM_CYCLE;
414 tx2->anim_next = anims[ (j+1)%max ];
416 tx2->alternate_anims = altanims[0];
418 for (j=0 ; j<altmax ; j++)
422 Host_Error ("Missing frame %i of %s",j, tx->name);
423 tx2->anim_total = altmax * ANIM_CYCLE;
424 tx2->anim_min = j * ANIM_CYCLE;
425 tx2->anim_max = (j+1) * ANIM_CYCLE;
426 tx2->anim_next = altanims[ (j+1)%altmax ];
428 tx2->alternate_anims = anims[0];
438 void Mod_LoadLighting (lump_t *l)
441 byte *in, *out, *data;
443 char litfilename[1024];
444 loadmodel->lightdata = NULL;
445 if (hlbsp) // LordHavoc: load the colored lighting data straight
447 loadmodel->lightdata = Hunk_AllocName ( l->filelen, va("%s lightmaps", loadname));
448 memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
450 else // LordHavoc: bsp version 29 (normal white lighting)
452 // LordHavoc: hope is not lost yet, check for a .lit file to load
453 strcpy(litfilename, loadmodel->name);
454 COM_StripExtension(litfilename, litfilename);
455 strcat(litfilename, ".lit");
456 data = (byte*) COM_LoadHunkFile (litfilename, false);
459 if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' && data[3] == 'T')
461 i = LittleLong(((int *)data)[1]);
464 Con_DPrintf("%s loaded", litfilename);
465 loadmodel->lightdata = data + 8;
469 Con_Printf("Unknown .lit file version (%d)\n", i);
472 Con_Printf("Corrupt .lit file (old version?), ignoring\n");
474 // LordHavoc: oh well, expand the white lighting data
477 loadmodel->lightdata = Hunk_AllocName ( l->filelen*3, va("%s lightmaps", loadname));
478 in = loadmodel->lightdata + l->filelen*2; // place the file at the end, so it will not be overwritten until the very last write
479 out = loadmodel->lightdata;
480 memcpy (in, mod_base + l->fileofs, l->filelen);
481 for (i = 0;i < l->filelen;i++)
497 void Mod_LoadVisibility (lump_t *l)
501 loadmodel->visdata = NULL;
504 loadmodel->visdata = Hunk_AllocName ( l->filelen, va("%s visdata", loadname));
505 memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
508 void CL_ParseEntityLump(char *entdata);
510 extern qboolean isworldmodel;
517 void Mod_LoadEntities (lump_t *l)
521 loadmodel->entities = NULL;
524 loadmodel->entities = Hunk_AllocName ( l->filelen, va("%s entities", loadname));
525 memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
528 CL_ParseEntityLump(loadmodel->entities);
537 void Mod_LoadVertexes (lump_t *l)
543 in = (void *)(mod_base + l->fileofs);
544 if (l->filelen % sizeof(*in))
545 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
546 count = l->filelen / sizeof(*in);
547 out = Hunk_AllocName ( count*sizeof(*out), va("%s vertices", loadname));
549 loadmodel->vertexes = out;
550 loadmodel->numvertexes = count;
552 for ( i=0 ; i<count ; i++, in++, out++)
554 out->position[0] = LittleFloat (in->point[0]);
555 out->position[1] = LittleFloat (in->point[1]);
556 out->position[2] = LittleFloat (in->point[2]);
565 void Mod_LoadSubmodels (lump_t *l)
571 in = (void *)(mod_base + l->fileofs);
572 if (l->filelen % sizeof(*in))
573 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
574 count = l->filelen / sizeof(*in);
575 out = Hunk_AllocName ( count*sizeof(*out), va("%s submodels", loadname));
577 loadmodel->submodels = out;
578 loadmodel->numsubmodels = count;
580 for ( i=0 ; i<count ; i++, in++, out++)
582 for (j=0 ; j<3 ; j++)
583 { // spread the mins / maxs by a pixel
584 out->mins[j] = LittleFloat (in->mins[j]) - 1;
585 out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
586 out->origin[j] = LittleFloat (in->origin[j]);
588 for (j=0 ; j<MAX_MAP_HULLS ; j++)
589 out->headnode[j] = LittleLong (in->headnode[j]);
590 out->visleafs = LittleLong (in->visleafs);
591 out->firstface = LittleLong (in->firstface);
592 out->numfaces = LittleLong (in->numfaces);
601 void Mod_LoadEdges (lump_t *l)
607 in = (void *)(mod_base + l->fileofs);
608 if (l->filelen % sizeof(*in))
609 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
610 count = l->filelen / sizeof(*in);
611 out = Hunk_AllocName ( (count + 1) * sizeof(*out), va("%s edges", loadname));
613 loadmodel->edges = out;
614 loadmodel->numedges = count;
616 for ( i=0 ; i<count ; i++, in++, out++)
618 out->v[0] = (unsigned short)LittleShort(in->v[0]);
619 out->v[1] = (unsigned short)LittleShort(in->v[1]);
628 void Mod_LoadTexinfo (lump_t *l)
636 in = (void *)(mod_base + l->fileofs);
637 if (l->filelen % sizeof(*in))
638 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
639 count = l->filelen / sizeof(*in);
640 out = Hunk_AllocName ( count*sizeof(*out), va("%s texinfo", loadname));
642 loadmodel->texinfo = out;
643 loadmodel->numtexinfo = count;
645 for ( i=0 ; i<count ; i++, in++, out++)
647 for (k=0 ; k<2 ; k++)
648 for (j=0 ; j<4 ; j++)
649 out->vecs[k][j] = LittleFloat (in->vecs[k][j]);
650 len1 = Length (out->vecs[0]);
651 len2 = Length (out->vecs[1]);
652 len1 = (len1 + len2)/2;
655 else if (len1 < 0.49)
657 else if (len1 < 0.99)
662 if (len1 + len2 < 0.001)
663 out->mipadjust = 1; // don't crash
665 out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
668 miptex = LittleLong (in->miptex);
669 out->flags = LittleLong (in->flags);
671 if (!loadmodel->textures)
673 out->texture = r_notexture_mip; // checkerboard texture
675 out->texture->transparent = false;
679 if (miptex >= loadmodel->numtextures)
680 Host_Error ("miptex >= loadmodel->numtextures");
681 out->texture = loadmodel->textures[miptex];
684 out->texture = r_notexture_mip; // texture not found
686 out->texture->transparent = false;
696 Fills in s->texturemins[] and s->extents[]
699 void CalcSurfaceExtents (msurface_t *s)
701 float mins[2], maxs[2], val;
705 int bmins[2], bmaxs[2];
707 mins[0] = mins[1] = 999999;
708 maxs[0] = maxs[1] = -99999;
712 for (i=0 ; i<s->numedges ; i++)
714 e = loadmodel->surfedges[s->firstedge+i];
716 v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
718 v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
720 for (j=0 ; j<2 ; j++)
722 val = v->position[0] * tex->vecs[j][0] +
723 v->position[1] * tex->vecs[j][1] +
724 v->position[2] * tex->vecs[j][2] +
733 for (i=0 ; i<2 ; i++)
735 bmins[i] = floor(mins[i]/16);
736 bmaxs[i] = ceil(maxs[i]/16);
738 s->texturemins[i] = bmins[i] * 16;
739 s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
740 // if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512)
741 if ((tex->flags & TEX_SPECIAL) == 0 && (s->extents[i]+1) > (256*16))
742 Host_Error ("Bad surface extents");
746 void GL_SubdivideSurface (msurface_t *fa);
748 extern char skyname[];
755 void Mod_LoadFaces (lump_t *l)
759 int i, count, surfnum;
762 in = (void *)(mod_base + l->fileofs);
763 if (l->filelen % sizeof(*in))
764 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
765 count = l->filelen / sizeof(*in);
766 out = Hunk_AllocName ( count*sizeof(*out), va("%s faces", loadname));
768 loadmodel->surfaces = out;
769 loadmodel->numsurfaces = count;
771 for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
773 out->firstedge = LittleLong(in->firstedge);
774 out->numedges = LittleShort(in->numedges);
777 planenum = LittleShort(in->planenum);
778 side = LittleShort(in->side);
780 out->flags |= SURF_PLANEBACK;
782 out->plane = loadmodel->planes + planenum;
784 out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
786 CalcSurfaceExtents (out);
790 for (i=0 ; i<MAXLIGHTMAPS ; i++)
791 out->styles[i] = in->styles[i];
792 i = LittleLong(in->lightofs);
795 else if (hlbsp) // LordHavoc: HalfLife map (bsp version 30)
796 out->samples = loadmodel->lightdata + i;
797 else // LordHavoc: white lighting (bsp version 29)
798 out->samples = loadmodel->lightdata + (i * 3);
800 // set the drawing flags flag
802 // if (!strncmp(out->texinfo->texture->name,"sky",3)) // sky
803 // LordHavoc: faster check
804 if ((out->texinfo->texture->name[0] == 's' || out->texinfo->texture->name[0] == 'S')
805 && (out->texinfo->texture->name[1] == 'k' || out->texinfo->texture->name[1] == 'K')
806 && (out->texinfo->texture->name[2] == 'y' || out->texinfo->texture->name[2] == 'Y'))
808 // LordHavoc: for consistency reasons, mark sky as fullbright and solid as well
809 out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA);
810 GL_SubdivideSurface (out); // cut up polygon for warps
814 // if (!strncmp(out->texinfo->texture->name,"*",1)) // turbulent
815 if (out->texinfo->texture->name[0] == '*') // LordHavoc: faster check
817 out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED | SURF_LIGHTBOTHSIDES);
818 // LordHavoc: some turbulent textures should be fullbright and solid
819 if (!strncmp(out->texinfo->texture->name,"*lava",5)
820 || !strncmp(out->texinfo->texture->name,"*teleport",9)
821 || !strncmp(out->texinfo->texture->name,"*rift",5)) // Scourge of Armagon texture
822 out->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA);
823 for (i=0 ; i<2 ; i++)
825 out->extents[i] = 16384;
826 out->texturemins[i] = -8192;
828 GL_SubdivideSurface (out); // cut up polygon for warps
841 void Mod_SetParent (mnode_t *node, mnode_t *parent)
843 node->parent = parent;
844 if (node->contents < 0)
846 Mod_SetParent (node->children[0], node);
847 Mod_SetParent (node->children[1], node);
855 void Mod_LoadNodes (lump_t *l)
861 in = (void *)(mod_base + l->fileofs);
862 if (l->filelen % sizeof(*in))
863 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
864 count = l->filelen / sizeof(*in);
865 out = Hunk_AllocName ( count*sizeof(*out), va("%s nodes", loadname));
867 loadmodel->nodes = out;
868 loadmodel->numnodes = count;
870 for ( i=0 ; i<count ; i++, in++, out++)
872 for (j=0 ; j<3 ; j++)
874 out->minmaxs[j] = LittleShort (in->mins[j]);
875 out->minmaxs[3+j] = LittleShort (in->maxs[j]);
878 p = LittleLong(in->planenum);
879 out->plane = loadmodel->planes + p;
881 out->firstsurface = LittleShort (in->firstface);
882 out->numsurfaces = LittleShort (in->numfaces);
884 for (j=0 ; j<2 ; j++)
886 p = LittleShort (in->children[j]);
888 out->children[j] = loadmodel->nodes + p;
890 out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
894 Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
902 void Mod_LoadLeafs (lump_t *l)
908 in = (void *)(mod_base + l->fileofs);
909 if (l->filelen % sizeof(*in))
910 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
911 count = l->filelen / sizeof(*in);
912 out = Hunk_AllocName ( count*sizeof(*out), va("%s leafs", loadname));
914 loadmodel->leafs = out;
915 loadmodel->numleafs = count;
917 for ( i=0 ; i<count ; i++, in++, out++)
919 for (j=0 ; j<3 ; j++)
921 out->minmaxs[j] = LittleShort (in->mins[j]);
922 out->minmaxs[3+j] = LittleShort (in->maxs[j]);
925 p = LittleLong(in->contents);
928 out->firstmarksurface = loadmodel->marksurfaces +
929 LittleShort(in->firstmarksurface);
930 out->nummarksurfaces = LittleShort(in->nummarksurfaces);
932 p = LittleLong(in->visofs);
934 out->compressed_vis = NULL;
936 out->compressed_vis = loadmodel->visdata + p;
939 for (j=0 ; j<4 ; j++)
940 out->ambient_sound_level[j] = in->ambient_level[j];
942 // gl underwater warp
943 // LordHavoc: disabled underwater warping
945 if (out->contents != CONTENTS_EMPTY)
947 for (j=0 ; j<out->nummarksurfaces ; j++)
948 out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
959 void Mod_LoadClipnodes (lump_t *l)
961 dclipnode_t *in, *out;
965 in = (void *)(mod_base + l->fileofs);
966 if (l->filelen % sizeof(*in))
967 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
968 count = l->filelen / sizeof(*in);
969 out = Hunk_AllocName ( count*sizeof(*out), va("%s clipnodes", loadname));
971 loadmodel->clipnodes = out;
972 loadmodel->numclipnodes = count;
976 hull = &loadmodel->hulls[1];
977 hull->clipnodes = out;
978 hull->firstclipnode = 0;
979 hull->lastclipnode = count-1;
980 hull->planes = loadmodel->planes;
981 hull->clip_mins[0] = -16;
982 hull->clip_mins[1] = -16;
983 hull->clip_mins[2] = -36;
984 hull->clip_maxs[0] = 16;
985 hull->clip_maxs[1] = 16;
986 hull->clip_maxs[2] = 36;
988 hull = &loadmodel->hulls[2];
989 hull->clipnodes = out;
990 hull->firstclipnode = 0;
991 hull->lastclipnode = count-1;
992 hull->planes = loadmodel->planes;
993 hull->clip_mins[0] = -32;
994 hull->clip_mins[1] = -32;
995 hull->clip_mins[2] = -32;
996 hull->clip_maxs[0] = 32;
997 hull->clip_maxs[1] = 32;
998 hull->clip_maxs[2] = 32;
1000 hull = &loadmodel->hulls[3];
1001 hull->clipnodes = out;
1002 hull->firstclipnode = 0;
1003 hull->lastclipnode = count-1;
1004 hull->planes = loadmodel->planes;
1005 hull->clip_mins[0] = -16;
1006 hull->clip_mins[1] = -16;
1007 hull->clip_mins[2] = -18;
1008 hull->clip_maxs[0] = 16;
1009 hull->clip_maxs[1] = 16;
1010 hull->clip_maxs[2] = 18;
1014 hull = &loadmodel->hulls[1];
1015 hull->clipnodes = out;
1016 hull->firstclipnode = 0;
1017 hull->lastclipnode = count-1;
1018 hull->planes = loadmodel->planes;
1019 hull->clip_mins[0] = -16;
1020 hull->clip_mins[1] = -16;
1021 hull->clip_mins[2] = -24;
1022 hull->clip_maxs[0] = 16;
1023 hull->clip_maxs[1] = 16;
1024 hull->clip_maxs[2] = 32;
1026 hull = &loadmodel->hulls[2];
1027 hull->clipnodes = out;
1028 hull->firstclipnode = 0;
1029 hull->lastclipnode = count-1;
1030 hull->planes = loadmodel->planes;
1031 hull->clip_mins[0] = -32;
1032 hull->clip_mins[1] = -32;
1033 hull->clip_mins[2] = -24;
1034 hull->clip_maxs[0] = 32;
1035 hull->clip_maxs[1] = 32;
1036 hull->clip_maxs[2] = 64;
1039 for (i=0 ; i<count ; i++, out++, in++)
1041 out->planenum = LittleLong(in->planenum);
1042 out->children[0] = LittleShort(in->children[0]);
1043 out->children[1] = LittleShort(in->children[1]);
1044 if (out->children[0] >= count || out->children[1] >= count)
1045 Host_Error("Corrupt clipping hull (out of range child)\n");
1053 Duplicate the drawing hull structure as a clipping hull
1056 void Mod_MakeHull0 (void)
1058 mnode_t *in, *child;
1063 hull = &loadmodel->hulls[0];
1065 in = loadmodel->nodes;
1066 count = loadmodel->numnodes;
1067 out = Hunk_AllocName ( count*sizeof(*out), va("%s hull0", loadname));
1069 hull->clipnodes = out;
1070 hull->firstclipnode = 0;
1071 hull->lastclipnode = count-1;
1072 hull->planes = loadmodel->planes;
1074 for (i=0 ; i<count ; i++, out++, in++)
1076 out->planenum = in->plane - loadmodel->planes;
1077 for (j=0 ; j<2 ; j++)
1079 child = in->children[j];
1080 if (child->contents < 0)
1081 out->children[j] = child->contents;
1083 out->children[j] = child - loadmodel->nodes;
1090 Mod_LoadMarksurfaces
1093 void Mod_LoadMarksurfaces (lump_t *l)
1099 in = (void *)(mod_base + l->fileofs);
1100 if (l->filelen % sizeof(*in))
1101 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1102 count = l->filelen / sizeof(*in);
1103 out = Hunk_AllocName ( count*sizeof(*out), va("%s marksurfaces", loadname));
1105 loadmodel->marksurfaces = out;
1106 loadmodel->nummarksurfaces = count;
1108 for ( i=0 ; i<count ; i++)
1110 j = LittleShort(in[i]);
1111 if (j >= loadmodel->numsurfaces)
1112 Host_Error ("Mod_ParseMarksurfaces: bad surface number");
1113 out[i] = loadmodel->surfaces + j;
1122 void Mod_LoadSurfedges (lump_t *l)
1127 in = (void *)(mod_base + l->fileofs);
1128 if (l->filelen % sizeof(*in))
1129 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1130 count = l->filelen / sizeof(*in);
1131 out = Hunk_AllocName ( count*sizeof(*out), va("%s surfedges", loadname));
1133 loadmodel->surfedges = out;
1134 loadmodel->numsurfedges = count;
1136 for ( i=0 ; i<count ; i++)
1137 out[i] = LittleLong (in[i]);
1146 void Mod_LoadPlanes (lump_t *l)
1154 in = (void *)(mod_base + l->fileofs);
1155 if (l->filelen % sizeof(*in))
1156 Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1157 count = l->filelen / sizeof(*in);
1158 out = Hunk_AllocName ( count*2*sizeof(*out), va("%s planes", loadname));
1160 loadmodel->planes = out;
1161 loadmodel->numplanes = count;
1163 for ( i=0 ; i<count ; i++, in++, out++)
1166 for (j=0 ; j<3 ; j++)
1168 out->normal[j] = LittleFloat (in->normal[j]);
1169 // if (out->normal[j] < 0)
1173 out->dist = LittleFloat (in->dist);
1174 out->type = LittleLong (in->type);
1175 // out->signbits = bits;
1176 BoxOnPlaneSideClassify(out);
1185 void Mod_LoadBrushModel (model_t *mod, void *buffer)
1191 loadmodel->type = mod_brush;
1193 header = (dheader_t *)buffer;
1195 i = LittleLong (header->version);
1196 if (i != BSPVERSION && i != 30)
1197 Host_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i or 30 (HalfLife))", mod->name, i, BSPVERSION);
1199 halflifebsp.value = hlbsp;
1201 // swap all the lumps
1202 mod_base = (byte *)header;
1204 for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
1205 ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
1209 // LordHavoc: had to move entity loading above everything to allow parsing various settings from worldspawn
1210 Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
1212 Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
1213 Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
1214 Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
1215 Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
1216 Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
1217 Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
1218 Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
1219 Mod_LoadFaces (&header->lumps[LUMP_FACES]);
1220 Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
1221 Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
1222 Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
1223 Mod_LoadNodes (&header->lumps[LUMP_NODES]);
1224 Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
1225 // Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
1226 Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
1230 mod->numframes = 2; // regular and alternate animation
1233 // set up the submodels (FIXME: this is confusing)
1235 for (i=0 ; i<mod->numsubmodels ; i++)
1237 bm = &mod->submodels[i];
1239 mod->hulls[0].firstclipnode = bm->headnode[0];
1240 for (j=1 ; j<MAX_MAP_HULLS ; j++)
1242 mod->hulls[j].firstclipnode = bm->headnode[j];
1243 mod->hulls[j].lastclipnode = mod->numclipnodes-1;
1246 mod->firstmodelsurface = bm->firstface;
1247 mod->nummodelsurfaces = bm->numfaces;
1249 VectorCopy (bm->maxs, mod->maxs);
1250 VectorCopy (bm->mins, mod->mins);
1252 mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
1254 mod->numleafs = bm->visleafs;
1256 if (isworldmodel && i < (mod->numsubmodels-1)) // LordHavoc: only register submodels if it is the world (prevents bsp models from replacing world submodels)
1257 { // duplicate the basic information
1260 sprintf (name, "*%i", i+1);
1261 loadmodel = Mod_FindName (name);
1263 strcpy (loadmodel->name, name);