Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

r_model.c (27632B)


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