Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

gl_model.c (27106B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      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.
      8 
      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.  
     12 
     13 See the GNU General Public License for more details.
     14 
     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.
     18 
     19 */
     20 // models.c -- model loading and caching
     21 
     22 #include "gl_local.h"
     23 
     24 model_t	*loadmodel;
     25 int		modfilelen;
     26 
     27 void Mod_LoadSpriteModel (model_t *mod, void *buffer);
     28 void Mod_LoadBrushModel (model_t *mod, void *buffer);
     29 void Mod_LoadAliasModel (model_t *mod, void *buffer);
     30 model_t *Mod_LoadModel (model_t *mod, qboolean crash);
     31 
     32 byte	mod_novis[MAX_MAP_LEAFS/8];
     33 
     34 #define	MAX_MOD_KNOWN	512
     35 model_t	mod_known[MAX_MOD_KNOWN];
     36 int		mod_numknown;
     37 
     38 // the inline * models from the current map are kept seperate
     39 model_t	mod_inline[MAX_MOD_KNOWN];
     40 
     41 int		registration_sequence;
     42 
     43 /*
     44 ===============
     45 Mod_PointInLeaf
     46 ===============
     47 */
     48 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
     49 {
     50 	mnode_t		*node;
     51 	float		d;
     52 	cplane_t	*plane;
     53 	
     54 	if (!model || !model->nodes)
     55 		ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model");
     56 
     57 	node = model->nodes;
     58 	while (1)
     59 	{
     60 		if (node->contents != -1)
     61 			return (mleaf_t *)node;
     62 		plane = node->plane;
     63 		d = DotProduct (p,plane->normal) - plane->dist;
     64 		if (d > 0)
     65 			node = node->children[0];
     66 		else
     67 			node = node->children[1];
     68 	}
     69 	
     70 	return NULL;	// never reached
     71 }
     72 
     73 
     74 /*
     75 ===================
     76 Mod_DecompressVis
     77 ===================
     78 */
     79 byte *Mod_DecompressVis (byte *in, model_t *model)
     80 {
     81 	static byte	decompressed[MAX_MAP_LEAFS/8];
     82 	int		c;
     83 	byte	*out;
     84 	int		row;
     85 
     86 	row = (model->vis->numclusters+7)>>3;	
     87 	out = decompressed;
     88 
     89 	if (!in)
     90 	{	// no vis info, so make all visible
     91 		while (row)
     92 		{
     93 			*out++ = 0xff;
     94 			row--;
     95 		}
     96 		return decompressed;		
     97 	}
     98 
     99 	do
    100 	{
    101 		if (*in)
    102 		{
    103 			*out++ = *in++;
    104 			continue;
    105 		}
    106 	
    107 		c = in[1];
    108 		in += 2;
    109 		while (c)
    110 		{
    111 			*out++ = 0;
    112 			c--;
    113 		}
    114 	} while (out - decompressed < row);
    115 	
    116 	return decompressed;
    117 }
    118 
    119 /*
    120 ==============
    121 Mod_ClusterPVS
    122 ==============
    123 */
    124 byte *Mod_ClusterPVS (int cluster, model_t *model)
    125 {
    126 	if (cluster == -1 || !model->vis)
    127 		return mod_novis;
    128 	return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS],
    129 		model);
    130 }
    131 
    132 
    133 //===============================================================================
    134 
    135 /*
    136 ================
    137 Mod_Modellist_f
    138 ================
    139 */
    140 void Mod_Modellist_f (void)
    141 {
    142 	int		i;
    143 	model_t	*mod;
    144 	int		total;
    145 
    146 	total = 0;
    147 	ri.Con_Printf (PRINT_ALL,"Loaded models:\n");
    148 	for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
    149 	{
    150 		if (!mod->name[0])
    151 			continue;
    152 		ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name);
    153 		total += mod->extradatasize;
    154 	}
    155 	ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total);
    156 }
    157 
    158 /*
    159 ===============
    160 Mod_Init
    161 ===============
    162 */
    163 void Mod_Init (void)
    164 {
    165 	memset (mod_novis, 0xff, sizeof(mod_novis));
    166 }
    167 
    168 
    169 
    170 /*
    171 ==================
    172 Mod_ForName
    173 
    174 Loads in a model for the given name
    175 ==================
    176 */
    177 model_t *Mod_ForName (char *name, qboolean crash)
    178 {
    179 	model_t	*mod;
    180 	unsigned *buf;
    181 	int		i;
    182 	
    183 	if (!name[0])
    184 		ri.Sys_Error (ERR_DROP, "Mod_ForName: NULL name");
    185 		
    186 	//
    187 	// inline models are grabbed only from worldmodel
    188 	//
    189 	if (name[0] == '*')
    190 	{
    191 		i = atoi(name+1);
    192 		if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
    193 			ri.Sys_Error (ERR_DROP, "bad inline model number");
    194 		return &mod_inline[i];
    195 	}
    196 
    197 	//
    198 	// search the currently loaded models
    199 	//
    200 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
    201 	{
    202 		if (!mod->name[0])
    203 			continue;
    204 		if (!strcmp (mod->name, name) )
    205 			return mod;
    206 	}
    207 	
    208 	//
    209 	// find a free model slot spot
    210 	//
    211 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
    212 	{
    213 		if (!mod->name[0])
    214 			break;	// free spot
    215 	}
    216 	if (i == mod_numknown)
    217 	{
    218 		if (mod_numknown == MAX_MOD_KNOWN)
    219 			ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
    220 		mod_numknown++;
    221 	}
    222 	strcpy (mod->name, name);
    223 	
    224 	//
    225 	// load the file
    226 	//
    227 	modfilelen = ri.FS_LoadFile (mod->name, &buf);
    228 	if (!buf)
    229 	{
    230 		if (crash)
    231 			ri.Sys_Error (ERR_DROP, "Mod_NumForName: %s not found", mod->name);
    232 		memset (mod->name, 0, sizeof(mod->name));
    233 		return NULL;
    234 	}
    235 	
    236 	loadmodel = mod;
    237 
    238 	//
    239 	// fill it in
    240 	//
    241 
    242 
    243 	// call the apropriate loader
    244 	
    245 	switch (LittleLong(*(unsigned *)buf))
    246 	{
    247 	case IDALIASHEADER:
    248 		loadmodel->extradata = Hunk_Begin (0x200000);
    249 		Mod_LoadAliasModel (mod, buf);
    250 		break;
    251 		
    252 	case IDSPRITEHEADER:
    253 		loadmodel->extradata = Hunk_Begin (0x10000);
    254 		Mod_LoadSpriteModel (mod, buf);
    255 		break;
    256 	
    257 	case IDBSPHEADER:
    258 		loadmodel->extradata = Hunk_Begin (0x1000000);
    259 		Mod_LoadBrushModel (mod, buf);
    260 		break;
    261 
    262 	default:
    263 		ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name);
    264 		break;
    265 	}
    266 
    267 	loadmodel->extradatasize = Hunk_End ();
    268 
    269 	ri.FS_FreeFile (buf);
    270 
    271 	return mod;
    272 }
    273 
    274 /*
    275 ===============================================================================
    276 
    277 					BRUSHMODEL LOADING
    278 
    279 ===============================================================================
    280 */
    281 
    282 byte	*mod_base;
    283 
    284 
    285 /*
    286 =================
    287 Mod_LoadLighting
    288 =================
    289 */
    290 void Mod_LoadLighting (lump_t *l)
    291 {
    292 	if (!l->filelen)
    293 	{
    294 		loadmodel->lightdata = NULL;
    295 		return;
    296 	}
    297 	loadmodel->lightdata = Hunk_Alloc ( l->filelen);	
    298 	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
    299 }
    300 
    301 
    302 /*
    303 =================
    304 Mod_LoadVisibility
    305 =================
    306 */
    307 void Mod_LoadVisibility (lump_t *l)
    308 {
    309 	int		i;
    310 
    311 	if (!l->filelen)
    312 	{
    313 		loadmodel->vis = NULL;
    314 		return;
    315 	}
    316 	loadmodel->vis = Hunk_Alloc ( l->filelen);	
    317 	memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen);
    318 
    319 	loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters);
    320 	for (i=0 ; i<loadmodel->vis->numclusters ; i++)
    321 	{
    322 		loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]);
    323 		loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]);
    324 	}
    325 }
    326 
    327 
    328 /*
    329 =================
    330 Mod_LoadVertexes
    331 =================
    332 */
    333 void Mod_LoadVertexes (lump_t *l)
    334 {
    335 	dvertex_t	*in;
    336 	mvertex_t	*out;
    337 	int			i, count;
    338 
    339 	in = (void *)(mod_base + l->fileofs);
    340 	if (l->filelen % sizeof(*in))
    341 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    342 	count = l->filelen / sizeof(*in);
    343 	out = Hunk_Alloc ( count*sizeof(*out));	
    344 
    345 	loadmodel->vertexes = out;
    346 	loadmodel->numvertexes = count;
    347 
    348 	for ( i=0 ; i<count ; i++, in++, out++)
    349 	{
    350 		out->position[0] = LittleFloat (in->point[0]);
    351 		out->position[1] = LittleFloat (in->point[1]);
    352 		out->position[2] = LittleFloat (in->point[2]);
    353 	}
    354 }
    355 
    356 /*
    357 =================
    358 RadiusFromBounds
    359 =================
    360 */
    361 float RadiusFromBounds (vec3_t mins, vec3_t maxs)
    362 {
    363 	int		i;
    364 	vec3_t	corner;
    365 
    366 	for (i=0 ; i<3 ; i++)
    367 	{
    368 		corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
    369 	}
    370 
    371 	return VectorLength (corner);
    372 }
    373 
    374 
    375 /*
    376 =================
    377 Mod_LoadSubmodels
    378 =================
    379 */
    380 void Mod_LoadSubmodels (lump_t *l)
    381 {
    382 	dmodel_t	*in;
    383 	mmodel_t	*out;
    384 	int			i, j, count;
    385 
    386 	in = (void *)(mod_base + l->fileofs);
    387 	if (l->filelen % sizeof(*in))
    388 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    389 	count = l->filelen / sizeof(*in);
    390 	out = Hunk_Alloc ( count*sizeof(*out));	
    391 
    392 	loadmodel->submodels = out;
    393 	loadmodel->numsubmodels = count;
    394 
    395 	for ( i=0 ; i<count ; i++, in++, out++)
    396 	{
    397 		for (j=0 ; j<3 ; j++)
    398 		{	// spread the mins / maxs by a pixel
    399 			out->mins[j] = LittleFloat (in->mins[j]) - 1;
    400 			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
    401 			out->origin[j] = LittleFloat (in->origin[j]);
    402 		}
    403 		out->radius = RadiusFromBounds (out->mins, out->maxs);
    404 		out->headnode = LittleLong (in->headnode);
    405 		out->firstface = LittleLong (in->firstface);
    406 		out->numfaces = LittleLong (in->numfaces);
    407 	}
    408 }
    409 
    410 /*
    411 =================
    412 Mod_LoadEdges
    413 =================
    414 */
    415 void Mod_LoadEdges (lump_t *l)
    416 {
    417 	dedge_t *in;
    418 	medge_t *out;
    419 	int 	i, count;
    420 
    421 	in = (void *)(mod_base + l->fileofs);
    422 	if (l->filelen % sizeof(*in))
    423 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    424 	count = l->filelen / sizeof(*in);
    425 	out = Hunk_Alloc ( (count + 1) * sizeof(*out));	
    426 
    427 	loadmodel->edges = out;
    428 	loadmodel->numedges = count;
    429 
    430 	for ( i=0 ; i<count ; i++, in++, out++)
    431 	{
    432 		out->v[0] = (unsigned short)LittleShort(in->v[0]);
    433 		out->v[1] = (unsigned short)LittleShort(in->v[1]);
    434 	}
    435 }
    436 
    437 /*
    438 =================
    439 Mod_LoadTexinfo
    440 =================
    441 */
    442 void Mod_LoadTexinfo (lump_t *l)
    443 {
    444 	texinfo_t *in;
    445 	mtexinfo_t *out, *step;
    446 	int 	i, j, count;
    447 	char	name[MAX_QPATH];
    448 	int		next;
    449 
    450 	in = (void *)(mod_base + l->fileofs);
    451 	if (l->filelen % sizeof(*in))
    452 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    453 	count = l->filelen / sizeof(*in);
    454 	out = Hunk_Alloc ( count*sizeof(*out));	
    455 
    456 	loadmodel->texinfo = out;
    457 	loadmodel->numtexinfo = count;
    458 
    459 	for ( i=0 ; i<count ; i++, in++, out++)
    460 	{
    461 		for (j=0 ; j<8 ; j++)
    462 			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
    463 
    464 		out->flags = LittleLong (in->flags);
    465 		next = LittleLong (in->nexttexinfo);
    466 		if (next > 0)
    467 			out->next = loadmodel->texinfo + next;
    468 		else
    469 		    out->next = NULL;
    470 		Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
    471 
    472 		out->image = GL_FindImage (name, it_wall);
    473 		if (!out->image)
    474 		{
    475 			ri.Con_Printf (PRINT_ALL, "Couldn't load %s\n", name);
    476 			out->image = r_notexture;
    477 		}
    478 	}
    479 
    480 	// count animation frames
    481 	for (i=0 ; i<count ; i++)
    482 	{
    483 		out = &loadmodel->texinfo[i];
    484 		out->numframes = 1;
    485 		for (step = out->next ; step && step != out ; step=step->next)
    486 			out->numframes++;
    487 	}
    488 }
    489 
    490 /*
    491 ================
    492 CalcSurfaceExtents
    493 
    494 Fills in s->texturemins[] and s->extents[]
    495 ================
    496 */
    497 void CalcSurfaceExtents (msurface_t *s)
    498 {
    499 	float	mins[2], maxs[2], val;
    500 	int		i,j, e;
    501 	mvertex_t	*v;
    502 	mtexinfo_t	*tex;
    503 	int		bmins[2], bmaxs[2];
    504 
    505 	mins[0] = mins[1] = 999999;
    506 	maxs[0] = maxs[1] = -99999;
    507 
    508 	tex = s->texinfo;
    509 	
    510 	for (i=0 ; i<s->numedges ; i++)
    511 	{
    512 		e = loadmodel->surfedges[s->firstedge+i];
    513 		if (e >= 0)
    514 			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
    515 		else
    516 			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
    517 		
    518 		for (j=0 ; j<2 ; j++)
    519 		{
    520 			val = v->position[0] * tex->vecs[j][0] + 
    521 				v->position[1] * tex->vecs[j][1] +
    522 				v->position[2] * tex->vecs[j][2] +
    523 				tex->vecs[j][3];
    524 			if (val < mins[j])
    525 				mins[j] = val;
    526 			if (val > maxs[j])
    527 				maxs[j] = val;
    528 		}
    529 	}
    530 
    531 	for (i=0 ; i<2 ; i++)
    532 	{	
    533 		bmins[i] = floor(mins[i]/16);
    534 		bmaxs[i] = ceil(maxs[i]/16);
    535 
    536 		s->texturemins[i] = bmins[i] * 16;
    537 		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
    538 
    539 //		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
    540 //			ri.Sys_Error (ERR_DROP, "Bad surface extents");
    541 	}
    542 }
    543 
    544 
    545 void GL_BuildPolygonFromSurface(msurface_t *fa);
    546 void GL_CreateSurfaceLightmap (msurface_t *surf);
    547 void GL_EndBuildingLightmaps (void);
    548 void GL_BeginBuildingLightmaps (model_t *m);
    549 
    550 /*
    551 =================
    552 Mod_LoadFaces
    553 =================
    554 */
    555 void Mod_LoadFaces (lump_t *l)
    556 {
    557 	dface_t		*in;
    558 	msurface_t 	*out;
    559 	int			i, count, surfnum;
    560 	int			planenum, side;
    561 	int			ti;
    562 
    563 	in = (void *)(mod_base + l->fileofs);
    564 	if (l->filelen % sizeof(*in))
    565 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    566 	count = l->filelen / sizeof(*in);
    567 	out = Hunk_Alloc ( count*sizeof(*out));	
    568 
    569 	loadmodel->surfaces = out;
    570 	loadmodel->numsurfaces = count;
    571 
    572 	currentmodel = loadmodel;
    573 
    574 	GL_BeginBuildingLightmaps (loadmodel);
    575 
    576 	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
    577 	{
    578 		out->firstedge = LittleLong(in->firstedge);
    579 		out->numedges = LittleShort(in->numedges);		
    580 		out->flags = 0;
    581 		out->polys = NULL;
    582 
    583 		planenum = LittleShort(in->planenum);
    584 		side = LittleShort(in->side);
    585 		if (side)
    586 			out->flags |= SURF_PLANEBACK;			
    587 
    588 		out->plane = loadmodel->planes + planenum;
    589 
    590 		ti = LittleShort (in->texinfo);
    591 		if (ti < 0 || ti >= loadmodel->numtexinfo)
    592 			ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: bad texinfo number");
    593 		out->texinfo = loadmodel->texinfo + ti;
    594 
    595 		CalcSurfaceExtents (out);
    596 				
    597 	// lighting info
    598 
    599 		for (i=0 ; i<MAXLIGHTMAPS ; i++)
    600 			out->styles[i] = in->styles[i];
    601 		i = LittleLong(in->lightofs);
    602 		if (i == -1)
    603 			out->samples = NULL;
    604 		else
    605 			out->samples = loadmodel->lightdata + i;
    606 		
    607 	// set the drawing flags
    608 		
    609 		if (out->texinfo->flags & SURF_WARP)
    610 		{
    611 			out->flags |= SURF_DRAWTURB;
    612 			for (i=0 ; i<2 ; i++)
    613 			{
    614 				out->extents[i] = 16384;
    615 				out->texturemins[i] = -8192;
    616 			}
    617 			GL_SubdivideSurface (out);	// cut up polygon for warps
    618 		}
    619 
    620 		// create lightmaps and polygons
    621 		if ( !(out->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP) ) )
    622 			GL_CreateSurfaceLightmap (out);
    623 
    624 		if (! (out->texinfo->flags & SURF_WARP) ) 
    625 			GL_BuildPolygonFromSurface(out);
    626 
    627 	}
    628 
    629 	GL_EndBuildingLightmaps ();
    630 }
    631 
    632 
    633 /*
    634 =================
    635 Mod_SetParent
    636 =================
    637 */
    638 void Mod_SetParent (mnode_t *node, mnode_t *parent)
    639 {
    640 	node->parent = parent;
    641 	if (node->contents != -1)
    642 		return;
    643 	Mod_SetParent (node->children[0], node);
    644 	Mod_SetParent (node->children[1], node);
    645 }
    646 
    647 /*
    648 =================
    649 Mod_LoadNodes
    650 =================
    651 */
    652 void Mod_LoadNodes (lump_t *l)
    653 {
    654 	int			i, j, count, p;
    655 	dnode_t		*in;
    656 	mnode_t 	*out;
    657 
    658 	in = (void *)(mod_base + l->fileofs);
    659 	if (l->filelen % sizeof(*in))
    660 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    661 	count = l->filelen / sizeof(*in);
    662 	out = Hunk_Alloc ( count*sizeof(*out));	
    663 
    664 	loadmodel->nodes = out;
    665 	loadmodel->numnodes = count;
    666 
    667 	for ( i=0 ; i<count ; i++, in++, out++)
    668 	{
    669 		for (j=0 ; j<3 ; j++)
    670 		{
    671 			out->minmaxs[j] = LittleShort (in->mins[j]);
    672 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
    673 		}
    674 	
    675 		p = LittleLong(in->planenum);
    676 		out->plane = loadmodel->planes + p;
    677 
    678 		out->firstsurface = LittleShort (in->firstface);
    679 		out->numsurfaces = LittleShort (in->numfaces);
    680 		out->contents = -1;	// differentiate from leafs
    681 
    682 		for (j=0 ; j<2 ; j++)
    683 		{
    684 			p = LittleLong (in->children[j]);
    685 			if (p >= 0)
    686 				out->children[j] = loadmodel->nodes + p;
    687 			else
    688 				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
    689 		}
    690 	}
    691 	
    692 	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
    693 }
    694 
    695 /*
    696 =================
    697 Mod_LoadLeafs
    698 =================
    699 */
    700 void Mod_LoadLeafs (lump_t *l)
    701 {
    702 	dleaf_t 	*in;
    703 	mleaf_t 	*out;
    704 	int			i, j, count, p;
    705 //	glpoly_t	*poly;
    706 
    707 	in = (void *)(mod_base + l->fileofs);
    708 	if (l->filelen % sizeof(*in))
    709 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    710 	count = l->filelen / sizeof(*in);
    711 	out = Hunk_Alloc ( count*sizeof(*out));	
    712 
    713 	loadmodel->leafs = out;
    714 	loadmodel->numleafs = count;
    715 
    716 	for ( i=0 ; i<count ; i++, in++, out++)
    717 	{
    718 		for (j=0 ; j<3 ; j++)
    719 		{
    720 			out->minmaxs[j] = LittleShort (in->mins[j]);
    721 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
    722 		}
    723 
    724 		p = LittleLong(in->contents);
    725 		out->contents = p;
    726 
    727 		out->cluster = LittleShort(in->cluster);
    728 		out->area = LittleShort(in->area);
    729 
    730 		out->firstmarksurface = loadmodel->marksurfaces +
    731 			LittleShort(in->firstleafface);
    732 		out->nummarksurfaces = LittleShort(in->numleaffaces);
    733 		
    734 		// gl underwater warp
    735 #if 0
    736 		if (out->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA|CONTENTS_THINWATER) )
    737 		{
    738 			for (j=0 ; j<out->nummarksurfaces ; j++)
    739 			{
    740 				out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
    741 				for (poly = out->firstmarksurface[j]->polys ; poly ; poly=poly->next)
    742 					poly->flags |= SURF_UNDERWATER;
    743 			}
    744 		}
    745 #endif
    746 	}	
    747 }
    748 
    749 /*
    750 =================
    751 Mod_LoadMarksurfaces
    752 =================
    753 */
    754 void Mod_LoadMarksurfaces (lump_t *l)
    755 {	
    756 	int		i, j, count;
    757 	short		*in;
    758 	msurface_t **out;
    759 	
    760 	in = (void *)(mod_base + l->fileofs);
    761 	if (l->filelen % sizeof(*in))
    762 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    763 	count = l->filelen / sizeof(*in);
    764 	out = Hunk_Alloc ( count*sizeof(*out));	
    765 
    766 	loadmodel->marksurfaces = out;
    767 	loadmodel->nummarksurfaces = count;
    768 
    769 	for ( i=0 ; i<count ; i++)
    770 	{
    771 		j = LittleShort(in[i]);
    772 		if (j < 0 ||  j >= loadmodel->numsurfaces)
    773 			ri.Sys_Error (ERR_DROP, "Mod_ParseMarksurfaces: bad surface number");
    774 		out[i] = loadmodel->surfaces + j;
    775 	}
    776 }
    777 
    778 /*
    779 =================
    780 Mod_LoadSurfedges
    781 =================
    782 */
    783 void Mod_LoadSurfedges (lump_t *l)
    784 {	
    785 	int		i, count;
    786 	int		*in, *out;
    787 	
    788 	in = (void *)(mod_base + l->fileofs);
    789 	if (l->filelen % sizeof(*in))
    790 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    791 	count = l->filelen / sizeof(*in);
    792 	if (count < 1 || count >= MAX_MAP_SURFEDGES)
    793 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: bad surfedges count in %s: %i",
    794 		loadmodel->name, count);
    795 
    796 	out = Hunk_Alloc ( count*sizeof(*out));	
    797 
    798 	loadmodel->surfedges = out;
    799 	loadmodel->numsurfedges = count;
    800 
    801 	for ( i=0 ; i<count ; i++)
    802 		out[i] = LittleLong (in[i]);
    803 }
    804 
    805 
    806 /*
    807 =================
    808 Mod_LoadPlanes
    809 =================
    810 */
    811 void Mod_LoadPlanes (lump_t *l)
    812 {
    813 	int			i, j;
    814 	cplane_t	*out;
    815 	dplane_t 	*in;
    816 	int			count;
    817 	int			bits;
    818 	
    819 	in = (void *)(mod_base + l->fileofs);
    820 	if (l->filelen % sizeof(*in))
    821 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    822 	count = l->filelen / sizeof(*in);
    823 	out = Hunk_Alloc ( count*2*sizeof(*out));	
    824 	
    825 	loadmodel->planes = out;
    826 	loadmodel->numplanes = count;
    827 
    828 	for ( i=0 ; i<count ; i++, in++, out++)
    829 	{
    830 		bits = 0;
    831 		for (j=0 ; j<3 ; j++)
    832 		{
    833 			out->normal[j] = LittleFloat (in->normal[j]);
    834 			if (out->normal[j] < 0)
    835 				bits |= 1<<j;
    836 		}
    837 
    838 		out->dist = LittleFloat (in->dist);
    839 		out->type = LittleLong (in->type);
    840 		out->signbits = bits;
    841 	}
    842 }
    843 
    844 /*
    845 =================
    846 Mod_LoadBrushModel
    847 =================
    848 */
    849 void Mod_LoadBrushModel (model_t *mod, void *buffer)
    850 {
    851 	int			i;
    852 	dheader_t	*header;
    853 	mmodel_t 	*bm;
    854 	
    855 	loadmodel->type = mod_brush;
    856 	if (loadmodel != mod_known)
    857 		ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world");
    858 
    859 	header = (dheader_t *)buffer;
    860 
    861 	i = LittleLong (header->version);
    862 	if (i != BSPVERSION)
    863 		ri.Sys_Error (ERR_DROP, "Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
    864 
    865 // swap all the lumps
    866 	mod_base = (byte *)header;
    867 
    868 	for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
    869 		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
    870 
    871 // load into heap
    872 	
    873 	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
    874 	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
    875 	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
    876 	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
    877 	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
    878 	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
    879 	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
    880 	Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]);
    881 	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
    882 	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
    883 	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
    884 	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
    885 	mod->numframes = 2;		// regular and alternate animation
    886 	
    887 //
    888 // set up the submodels
    889 //
    890 	for (i=0 ; i<mod->numsubmodels ; i++)
    891 	{
    892 		model_t	*starmod;
    893 
    894 		bm = &mod->submodels[i];
    895 		starmod = &mod_inline[i];
    896 
    897 		*starmod = *loadmodel;
    898 		
    899 		starmod->firstmodelsurface = bm->firstface;
    900 		starmod->nummodelsurfaces = bm->numfaces;
    901 		starmod->firstnode = bm->headnode;
    902 		if (starmod->firstnode >= loadmodel->numnodes)
    903 			ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i);
    904 
    905 		VectorCopy (bm->maxs, starmod->maxs);
    906 		VectorCopy (bm->mins, starmod->mins);
    907 		starmod->radius = bm->radius;
    908 	
    909 		if (i == 0)
    910 			*loadmodel = *starmod;
    911 
    912 		starmod->numleafs = bm->visleafs;
    913 	}
    914 }
    915 
    916 /*
    917 ==============================================================================
    918 
    919 ALIAS MODELS
    920 
    921 ==============================================================================
    922 */
    923 
    924 /*
    925 =================
    926 Mod_LoadAliasModel
    927 =================
    928 */
    929 void Mod_LoadAliasModel (model_t *mod, void *buffer)
    930 {
    931 	int					i, j;
    932 	dmdl_t				*pinmodel, *pheader;
    933 	dstvert_t			*pinst, *poutst;
    934 	dtriangle_t			*pintri, *pouttri;
    935 	daliasframe_t		*pinframe, *poutframe;
    936 	int					*pincmd, *poutcmd;
    937 	int					version;
    938 
    939 	pinmodel = (dmdl_t *)buffer;
    940 
    941 	version = LittleLong (pinmodel->version);
    942 	if (version != ALIAS_VERSION)
    943 		ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
    944 				 mod->name, version, ALIAS_VERSION);
    945 
    946 	pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
    947 	
    948 	// byte swap the header fields and sanity check
    949 	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
    950 		((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);
    951 
    952 	if (pheader->skinheight > MAX_LBM_HEIGHT)
    953 		ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
    954 				   MAX_LBM_HEIGHT);
    955 
    956 	if (pheader->num_xyz <= 0)
    957 		ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name);
    958 
    959 	if (pheader->num_xyz > MAX_VERTS)
    960 		ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name);
    961 
    962 	if (pheader->num_st <= 0)
    963 		ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name);
    964 
    965 	if (pheader->num_tris <= 0)
    966 		ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name);
    967 
    968 	if (pheader->num_frames <= 0)
    969 		ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name);
    970 
    971 //
    972 // load base s and t vertices (not used in gl version)
    973 //
    974 	pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
    975 	poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);
    976 
    977 	for (i=0 ; i<pheader->num_st ; i++)
    978 	{
    979 		poutst[i].s = LittleShort (pinst[i].s);
    980 		poutst[i].t = LittleShort (pinst[i].t);
    981 	}
    982 
    983 //
    984 // load triangle lists
    985 //
    986 	pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
    987 	pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
    988 
    989 	for (i=0 ; i<pheader->num_tris ; i++)
    990 	{
    991 		for (j=0 ; j<3 ; j++)
    992 		{
    993 			pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
    994 			pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
    995 		}
    996 	}
    997 
    998 //
    999 // load the frames
   1000 //
   1001 	for (i=0 ; i<pheader->num_frames ; i++)
   1002 	{
   1003 		pinframe = (daliasframe_t *) ((byte *)pinmodel 
   1004 			+ pheader->ofs_frames + i * pheader->framesize);
   1005 		poutframe = (daliasframe_t *) ((byte *)pheader 
   1006 			+ pheader->ofs_frames + i * pheader->framesize);
   1007 
   1008 		memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
   1009 		for (j=0 ; j<3 ; j++)
   1010 		{
   1011 			poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
   1012 			poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
   1013 		}
   1014 		// verts are all 8 bit, so no swapping needed
   1015 		memcpy (poutframe->verts, pinframe->verts, 
   1016 			pheader->num_xyz*sizeof(dtrivertx_t));
   1017 
   1018 	}
   1019 
   1020 	mod->type = mod_alias;
   1021 
   1022 	//
   1023 	// load the glcmds
   1024 	//
   1025 	pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
   1026 	poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
   1027 	for (i=0 ; i<pheader->num_glcmds ; i++)
   1028 		poutcmd[i] = LittleLong (pincmd[i]);
   1029 
   1030 
   1031 	// register all skins
   1032 	memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
   1033 		pheader->num_skins*MAX_SKINNAME);
   1034 	for (i=0 ; i<pheader->num_skins ; i++)
   1035 	{
   1036 		mod->skins[i] = GL_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME
   1037 			, it_skin);
   1038 	}
   1039 
   1040 	mod->mins[0] = -32;
   1041 	mod->mins[1] = -32;
   1042 	mod->mins[2] = -32;
   1043 	mod->maxs[0] = 32;
   1044 	mod->maxs[1] = 32;
   1045 	mod->maxs[2] = 32;
   1046 }
   1047 
   1048 /*
   1049 ==============================================================================
   1050 
   1051 SPRITE MODELS
   1052 
   1053 ==============================================================================
   1054 */
   1055 
   1056 /*
   1057 =================
   1058 Mod_LoadSpriteModel
   1059 =================
   1060 */
   1061 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
   1062 {
   1063 	dsprite_t	*sprin, *sprout;
   1064 	int			i;
   1065 
   1066 	sprin = (dsprite_t *)buffer;
   1067 	sprout = Hunk_Alloc (modfilelen);
   1068 
   1069 	sprout->ident = LittleLong (sprin->ident);
   1070 	sprout->version = LittleLong (sprin->version);
   1071 	sprout->numframes = LittleLong (sprin->numframes);
   1072 
   1073 	if (sprout->version != SPRITE_VERSION)
   1074 		ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
   1075 				 mod->name, sprout->version, SPRITE_VERSION);
   1076 
   1077 	if (sprout->numframes > MAX_MD2SKINS)
   1078 		ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)",
   1079 				 mod->name, sprout->numframes, MAX_MD2SKINS);
   1080 
   1081 	// byte swap everything
   1082 	for (i=0 ; i<sprout->numframes ; i++)
   1083 	{
   1084 		sprout->frames[i].width = LittleLong (sprin->frames[i].width);
   1085 		sprout->frames[i].height = LittleLong (sprin->frames[i].height);
   1086 		sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x);
   1087 		sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y);
   1088 		memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
   1089 		mod->skins[i] = GL_FindImage (sprout->frames[i].name,
   1090 			it_sprite);
   1091 	}
   1092 
   1093 	mod->type = mod_sprite;
   1094 }
   1095 
   1096 //=============================================================================
   1097 
   1098 /*
   1099 @@@@@@@@@@@@@@@@@@@@@
   1100 R_BeginRegistration
   1101 
   1102 Specifies the model that will be used as the world
   1103 @@@@@@@@@@@@@@@@@@@@@
   1104 */
   1105 void R_BeginRegistration (char *model)
   1106 {
   1107 	char	fullname[MAX_QPATH];
   1108 	cvar_t	*flushmap;
   1109 
   1110 	registration_sequence++;
   1111 	r_oldviewcluster = -1;		// force markleafs
   1112 
   1113 	Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model);
   1114 
   1115 	// explicitly free the old map if different
   1116 	// this guarantees that mod_known[0] is the world map
   1117 	flushmap = ri.Cvar_Get ("flushmap", "0", 0);
   1118 	if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
   1119 		Mod_Free (&mod_known[0]);
   1120 	r_worldmodel = Mod_ForName(fullname, true);
   1121 
   1122 	r_viewcluster = -1;
   1123 }
   1124 
   1125 
   1126 /*
   1127 @@@@@@@@@@@@@@@@@@@@@
   1128 R_RegisterModel
   1129 
   1130 @@@@@@@@@@@@@@@@@@@@@
   1131 */
   1132 struct model_s *R_RegisterModel (char *name)
   1133 {
   1134 	model_t	*mod;
   1135 	int		i;
   1136 	dsprite_t	*sprout;
   1137 	dmdl_t		*pheader;
   1138 
   1139 	mod = Mod_ForName (name, false);
   1140 	if (mod)
   1141 	{
   1142 		mod->registration_sequence = registration_sequence;
   1143 
   1144 		// register any images used by the models
   1145 		if (mod->type == mod_sprite)
   1146 		{
   1147 			sprout = (dsprite_t *)mod->extradata;
   1148 			for (i=0 ; i<sprout->numframes ; i++)
   1149 				mod->skins[i] = GL_FindImage (sprout->frames[i].name, it_sprite);
   1150 		}
   1151 		else if (mod->type == mod_alias)
   1152 		{
   1153 			pheader = (dmdl_t *)mod->extradata;
   1154 			for (i=0 ; i<pheader->num_skins ; i++)
   1155 				mod->skins[i] = GL_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
   1156 //PGM
   1157 			mod->numframes = pheader->num_frames;
   1158 //PGM
   1159 		}
   1160 		else if (mod->type == mod_brush)
   1161 		{
   1162 			for (i=0 ; i<mod->numtexinfo ; i++)
   1163 				mod->texinfo[i].image->registration_sequence = registration_sequence;
   1164 		}
   1165 	}
   1166 	return mod;
   1167 }
   1168 
   1169 
   1170 /*
   1171 @@@@@@@@@@@@@@@@@@@@@
   1172 R_EndRegistration
   1173 
   1174 @@@@@@@@@@@@@@@@@@@@@
   1175 */
   1176 void R_EndRegistration (void)
   1177 {
   1178 	int		i;
   1179 	model_t	*mod;
   1180 
   1181 	for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
   1182 	{
   1183 		if (!mod->name[0])
   1184 			continue;
   1185 		if (mod->registration_sequence != registration_sequence)
   1186 		{	// don't need this model
   1187 			Mod_Free (mod);
   1188 		}
   1189 	}
   1190 
   1191 	GL_FreeUnusedImages ();
   1192 }
   1193 
   1194 
   1195 //=============================================================================
   1196 
   1197 
   1198 /*
   1199 ================
   1200 Mod_Free
   1201 ================
   1202 */
   1203 void Mod_Free (model_t *mod)
   1204 {
   1205 	Hunk_Free (mod->extradata);
   1206 	memset (mod, 0, sizeof(*mod));
   1207 }
   1208 
   1209 /*
   1210 ================
   1211 Mod_FreeAll
   1212 ================
   1213 */
   1214 void Mod_FreeAll (void)
   1215 {
   1216 	int		i;
   1217 
   1218 	for (i=0 ; i<mod_numknown ; i++)
   1219 	{
   1220 		if (mod_known[i].extradatasize)
   1221 			Mod_Free (&mod_known[i]);
   1222 	}
   1223 }