Home | History | Annotate | Download | only in WinQuake
      1 /*
      2 Copyright (C) 1996-1997 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 "quakedef.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	512
     38 model_t	mod_known[MAX_MOD_KNOWN];
     39 int		mod_numknown;
     40 
     41 cvar_t gl_subdivide_size = CVAR3("gl_subdivide_size", "128", true);
     42 
     43 /*
     44 ===============
     45 Mod_Init
     46 ===============
     47 */
     48 void Mod_Init (void)
     49 {
     50 	Cvar_RegisterVariable (&gl_subdivide_size);
     51 	memset (mod_novis, 0xff, sizeof(mod_novis));
     52 }
     53 
     54 /*
     55 ===============
     56 Mod_Init
     57 
     58 Caches the data if needed
     59 ===============
     60 */
     61 void *Mod_Extradata (model_t *mod)
     62 {
     63 	void	*r;
     64 
     65 	r = Cache_Check (&mod->cache);
     66 	if (r)
     67 		return r;
     68 
     69 	Mod_LoadModel (mod, true);
     70 
     71 	if (!mod->cache.data)
     72 		Sys_Error ("Mod_Extradata: caching failed");
     73 	return mod->cache.data;
     74 }
     75 
     76 /*
     77 ===============
     78 Mod_PointInLeaf
     79 ===============
     80 */
     81 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
     82 {
     83 	mnode_t		*node;
     84 	float		d;
     85 	mplane_t	*plane;
     86 
     87 	if (!model || !model->nodes)
     88 		Sys_Error ("Mod_PointInLeaf: bad model");
     89 
     90 	node = model->nodes;
     91 	while (1)
     92 	{
     93 		if (node->contents < 0)
     94 			return (mleaf_t *)node;
     95 		plane = node->plane;
     96 		d = DotProduct (p,plane->normal) - plane->dist;
     97 		if (d > 0)
     98 			node = node->children[0];
     99 		else
    100 			node = node->children[1];
    101 	}
    102 
    103 	return NULL;	// never reached
    104 }
    105 
    106 
    107 /*
    108 ===================
    109 Mod_DecompressVis
    110 ===================
    111 */
    112 byte *Mod_DecompressVis (byte *in, model_t *model)
    113 {
    114 	static byte	decompressed[MAX_MAP_LEAFS/8];
    115 	int		c;
    116 	byte	*out;
    117 	int		row;
    118 
    119 	row = (model->numleafs+7)>>3;
    120 	out = decompressed;
    121 
    122 #if 0
    123 	memcpy (out, in, row);
    124 #else
    125 	if (!in)
    126 	{	// no vis info, so make all visible
    127 		while (row)
    128 		{
    129 			*out++ = 0xff;
    130 			row--;
    131 		}
    132 		return decompressed;
    133 	}
    134 
    135 	do
    136 	{
    137 		if (*in)
    138 		{
    139 			*out++ = *in++;
    140 			continue;
    141 		}
    142 
    143 		c = in[1];
    144 		in += 2;
    145 		while (c)
    146 		{
    147 			*out++ = 0;
    148 			c--;
    149 		}
    150 	} while (out - decompressed < row);
    151 #endif
    152 
    153 	return decompressed;
    154 }
    155 
    156 byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
    157 {
    158 	if (leaf == model->leafs)
    159 		return mod_novis;
    160 	return Mod_DecompressVis (leaf->compressed_vis, model);
    161 }
    162 
    163 /*
    164 ===================
    165 Mod_ClearAll
    166 ===================
    167 */
    168 void Mod_ClearAll (void)
    169 {
    170 	int		i;
    171 	model_t	*mod;
    172 
    173 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
    174 		if (mod->type != mod_alias)
    175 			mod->needload = true;
    176 }
    177 
    178 /*
    179 ==================
    180 Mod_FindName
    181 
    182 ==================
    183 */
    184 model_t *Mod_FindName (const char *name)
    185 {
    186 	int		i;
    187 	model_t	*mod;
    188 
    189 	if (!name[0])
    190 		Sys_Error ("Mod_ForName: NULL name");
    191 
    192 //
    193 // search the currently loaded models
    194 //
    195 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
    196 		if (!strcmp (mod->name, name) )
    197 			break;
    198 
    199 	if (i == mod_numknown)
    200 	{
    201 		if (mod_numknown == MAX_MOD_KNOWN)
    202 			Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
    203 		strcpy (mod->name, name);
    204 		mod->needload = true;
    205 		mod_numknown++;
    206 	}
    207 
    208 	return mod;
    209 }
    210 
    211 /*
    212 ==================
    213 Mod_TouchModel
    214 
    215 ==================
    216 */
    217 void Mod_TouchModel (const char *name)
    218 {
    219 	model_t	*mod;
    220 
    221 	mod = Mod_FindName (name);
    222 
    223 	if (!mod->needload)
    224 	{
    225 		if (mod->type == mod_alias)
    226 			Cache_Check (&mod->cache);
    227 	}
    228 }
    229 
    230 /*
    231 ==================
    232 Mod_LoadModel
    233 
    234 Loads a model into the cache
    235 ==================
    236 */
    237 model_t *Mod_LoadModel (model_t *mod, qboolean crash)
    238 {
    239 	void	*d;
    240 	unsigned *buf;
    241 	byte	stackbuf[1024];		// avoid dirtying the cache heap
    242 
    243 	if (!mod->needload)
    244 	{
    245 		if (mod->type == mod_alias)
    246 		{
    247 			d = Cache_Check (&mod->cache);
    248 			if (d)
    249 				return mod;
    250 		}
    251 		else
    252 			return mod;		// not cached at all
    253 	}
    254 
    255 //
    256 // because the world is so huge, load it one piece at a time
    257 //
    258 	if (!crash)
    259 	{
    260 
    261 	}
    262 
    263 //
    264 // load the file
    265 //
    266 	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
    267 	if (!buf)
    268 	{
    269 		if (crash)
    270 			Sys_Error ("Mod_NumForName: %s not found", mod->name);
    271 		return NULL;
    272 	}
    273 
    274 //
    275 // allocate a new model
    276 //
    277 	COM_FileBase (mod->name, loadname, sizeof(loadname));
    278 
    279 	loadmodel = mod;
    280 
    281 //
    282 // fill it in
    283 //
    284 
    285 // call the apropriate loader
    286 	mod->needload = false;
    287 
    288 	switch (LittleLong(*(unsigned *)buf))
    289 	{
    290 	case IDPOLYHEADER:
    291 		Mod_LoadAliasModel (mod, buf);
    292 		break;
    293 
    294 	case IDSPRITEHEADER:
    295 		Mod_LoadSpriteModel (mod, buf);
    296 		break;
    297 
    298 	default:
    299 		Mod_LoadBrushModel (mod, buf);
    300 		break;
    301 	}
    302 
    303 	return mod;
    304 }
    305 
    306 /*
    307 ==================
    308 Mod_ForName
    309 
    310 Loads in a model for the given name
    311 ==================
    312 */
    313 model_t *Mod_ForName (const char *name, qboolean crash)
    314 {
    315 	model_t	*mod;
    316 
    317 	mod = Mod_FindName (name);
    318 
    319 	return Mod_LoadModel (mod, crash);
    320 }
    321 
    322 
    323 /*
    324 ===============================================================================
    325 
    326 					BRUSHMODEL LOADING
    327 
    328 ===============================================================================
    329 */
    330 
    331 byte	*mod_base;
    332 
    333 
    334 /*
    335 =================
    336 Mod_LoadTextures
    337 =================
    338 */
    339 void Mod_LoadTextures (lump_t *l)
    340 {
    341 	int		i, j, pixels, num, max, altmax;
    342 	miptex_t	*mt;
    343 	texture_t	*tx, *tx2;
    344 	texture_t	*anims[10];
    345 	texture_t	*altanims[10];
    346 	dmiptexlump_t *m;
    347 
    348 	if (!l->filelen)
    349 	{
    350 		loadmodel->textures = NULL;
    351 		return;
    352 	}
    353 	m = (dmiptexlump_t *)(mod_base + l->fileofs);
    354 
    355 	m->nummiptex = LittleLong (m->nummiptex);
    356 
    357 	loadmodel->numtextures = m->nummiptex;
    358 	loadmodel->textures = (texture_t**) Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
    359 
    360 	for (i=0 ; i<m->nummiptex ; i++)
    361 	{
    362 		m->dataofs[i] = LittleLong(m->dataofs[i]);
    363 		if (m->dataofs[i] == -1)
    364 			continue;
    365 		mt = (miptex_t *)((byte *)m + m->dataofs[i]);
    366 		mt->width = LittleLong (mt->width);
    367 		mt->height = LittleLong (mt->height);
    368 		for (j=0 ; j<MIPLEVELS ; j++)
    369 			mt->offsets[j] = LittleLong (mt->offsets[j]);
    370 
    371 		if ( (mt->width & 15) || (mt->height & 15) )
    372 			Sys_Error ("Texture %s is not 16 aligned", mt->name);
    373 		pixels = mt->width*mt->height/64*85;
    374 		tx = (texture_t*) Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
    375 		loadmodel->textures[i] = tx;
    376 
    377 		memcpy (tx->name, mt->name, sizeof(tx->name));
    378 		tx->width = mt->width;
    379 		tx->height = mt->height;
    380 		for (j=0 ; j<MIPLEVELS ; j++)
    381 			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
    382 		// the pixels immediately follow the structures
    383 		memcpy ( tx+1, mt+1, pixels);
    384 
    385 
    386 		if (!Q_strncmp(mt->name,"sky",3))
    387 			R_InitSky (tx);
    388 		else
    389 		{
    390 			texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR;
    391 			tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false);
    392 			texture_mode = GL_LINEAR;
    393 		}
    394 	}
    395 
    396 //
    397 // sequence the animations
    398 //
    399 	for (i=0 ; i<m->nummiptex ; i++)
    400 	{
    401 		tx = loadmodel->textures[i];
    402 		if (!tx || tx->name[0] != '+')
    403 			continue;
    404 		if (tx->anim_next)
    405 			continue;	// allready sequenced
    406 
    407 	// find the number of frames in the animation
    408 		memset (anims, 0, sizeof(anims));
    409 		memset (altanims, 0, sizeof(altanims));
    410 
    411 		max = tx->name[1];
    412 		altmax = 0;
    413 		if (max >= 'a' && max <= 'z')
    414 			max -= 'a' - 'A';
    415 		if (max >= '0' && max <= '9')
    416 		{
    417 			max -= '0';
    418 			altmax = 0;
    419 			anims[max] = tx;
    420 			max++;
    421 		}
    422 		else if (max >= 'A' && max <= 'J')
    423 		{
    424 			altmax = max - 'A';
    425 			max = 0;
    426 			altanims[altmax] = tx;
    427 			altmax++;
    428 		}
    429 		else
    430 			Sys_Error ("Bad animating texture %s", tx->name);
    431 
    432 		for (j=i+1 ; j<m->nummiptex ; j++)
    433 		{
    434 			tx2 = loadmodel->textures[j];
    435 			if (!tx2 || tx2->name[0] != '+')
    436 				continue;
    437 			if (strcmp (tx2->name+2, tx->name+2))
    438 				continue;
    439 
    440 			num = tx2->name[1];
    441 			if (num >= 'a' && num <= 'z')
    442 				num -= 'a' - 'A';
    443 			if (num >= '0' && num <= '9')
    444 			{
    445 				num -= '0';
    446 				anims[num] = tx2;
    447 				if (num+1 > max)
    448 					max = num + 1;
    449 			}
    450 			else if (num >= 'A' && num <= 'J')
    451 			{
    452 				num = num - 'A';
    453 				altanims[num] = tx2;
    454 				if (num+1 > altmax)
    455 					altmax = num+1;
    456 			}
    457 			else
    458 				Sys_Error ("Bad animating texture %s", tx->name);
    459 		}
    460 
    461 #define	ANIM_CYCLE	2
    462 	// link them all together
    463 		for (j=0 ; j<max ; j++)
    464 		{
    465 			tx2 = anims[j];
    466 			if (!tx2)
    467 				Sys_Error ("Missing frame %i of %s",j, tx->name);
    468 			tx2->anim_total = max * ANIM_CYCLE;
    469 			tx2->anim_min = j * ANIM_CYCLE;
    470 			tx2->anim_max = (j+1) * ANIM_CYCLE;
    471 			tx2->anim_next = anims[ (j+1)%max ];
    472 			if (altmax)
    473 				tx2->alternate_anims = altanims[0];
    474 		}
    475 		for (j=0 ; j<altmax ; j++)
    476 		{
    477 			tx2 = altanims[j];
    478 			if (!tx2)
    479 				Sys_Error ("Missing frame %i of %s",j, tx->name);
    480 			tx2->anim_total = altmax * ANIM_CYCLE;
    481 			tx2->anim_min = j * ANIM_CYCLE;
    482 			tx2->anim_max = (j+1) * ANIM_CYCLE;
    483 			tx2->anim_next = altanims[ (j+1)%altmax ];
    484 			if (max)
    485 				tx2->alternate_anims = anims[0];
    486 		}
    487 	}
    488 }
    489 
    490 /*
    491 =================
    492 Mod_LoadLighting
    493 =================
    494 */
    495 void Mod_LoadLighting (lump_t *l)
    496 {
    497 	if (!l->filelen)
    498 	{
    499 		loadmodel->lightdata = NULL;
    500 		return;
    501 	}
    502 	loadmodel->lightdata = (byte*) Hunk_AllocName ( l->filelen, loadname);
    503 	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
    504 }
    505 
    506 
    507 /*
    508 =================
    509 Mod_LoadVisibility
    510 =================
    511 */
    512 void Mod_LoadVisibility (lump_t *l)
    513 {
    514 	if (!l->filelen)
    515 	{
    516 		loadmodel->visdata = NULL;
    517 		return;
    518 	}
    519 	loadmodel->visdata = (byte*) Hunk_AllocName ( l->filelen, loadname);
    520 	memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
    521 }
    522 
    523 
    524 /*
    525 =================
    526 Mod_LoadEntities
    527 =================
    528 */
    529 void Mod_LoadEntities (lump_t *l)
    530 {
    531 	if (!l->filelen)
    532 	{
    533 		loadmodel->entities = NULL;
    534 		return;
    535 	}
    536 	loadmodel->entities = (char*) Hunk_AllocName ( l->filelen, loadname);
    537 	memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
    538 }
    539 
    540 
    541 /*
    542 =================
    543 Mod_LoadVertexes
    544 =================
    545 */
    546 void Mod_LoadVertexes (lump_t *l)
    547 {
    548 	dvertex_t	*in;
    549 	mvertex_t	*out;
    550 	int			i, count;
    551 
    552 	in = (dvertex_t*) (void *)(mod_base + l->fileofs);
    553 	if (l->filelen % sizeof(*in))
    554 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    555 	count = l->filelen / sizeof(*in);
    556 	out = (mvertex_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
    557 
    558 	loadmodel->vertexes = out;
    559 	loadmodel->numvertexes = count;
    560 
    561 	for ( i=0 ; i<count ; i++, in++, out++)
    562 	{
    563 		out->position[0] = LittleFloat (in->point[0]);
    564 		out->position[1] = LittleFloat (in->point[1]);
    565 		out->position[2] = LittleFloat (in->point[2]);
    566 	}
    567 }
    568 
    569 /*
    570 =================
    571 Mod_LoadSubmodels
    572 =================
    573 */
    574 void Mod_LoadSubmodels (lump_t *l)
    575 {
    576 	dmodel_t	*in;
    577 	dmodel_t	*out;
    578 	int			i, j, count;
    579 
    580 	in = (dmodel_t*) (void *)(mod_base + l->fileofs);
    581 	if (l->filelen % sizeof(*in))
    582 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    583 	count = l->filelen / sizeof(*in);
    584 	out =(dmodel_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
    585 
    586 	loadmodel->submodels = out;
    587 	loadmodel->numsubmodels = count;
    588 
    589 	for ( i=0 ; i<count ; i++, in++, out++)
    590 	{
    591 		for (j=0 ; j<3 ; j++)
    592 		{	// spread the mins / maxs by a pixel
    593 			out->mins[j] = LittleFloat (in->mins[j]) - 1;
    594 			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
    595 			out->origin[j] = LittleFloat (in->origin[j]);
    596 		}
    597 		for (j=0 ; j<MAX_MAP_HULLS ; j++)
    598 			out->headnode[j] = LittleLong (in->headnode[j]);
    599 		out->visleafs = LittleLong (in->visleafs);
    600 		out->firstface = LittleLong (in->firstface);
    601 		out->numfaces = LittleLong (in->numfaces);
    602 	}
    603 }
    604 
    605 /*
    606 =================
    607 Mod_LoadEdges
    608 =================
    609 */
    610 void Mod_LoadEdges (lump_t *l)
    611 {
    612 	dedge_t *in;
    613 	medge_t *out;
    614 	int 	i, count;
    615 
    616 	in = (dedge_t *) (mod_base + l->fileofs);
    617 	if (l->filelen % sizeof(*in))
    618 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    619 	count = l->filelen / sizeof(*in);
    620 	out = (medge_t*) Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
    621 
    622 	loadmodel->edges = out;
    623 	loadmodel->numedges = count;
    624 
    625 	for ( i=0 ; i<count ; i++, in++, out++)
    626 	{
    627 		out->v[0] = (unsigned short)LittleShort(in->v[0]);
    628 		out->v[1] = (unsigned short)LittleShort(in->v[1]);
    629 	}
    630 }
    631 
    632 /*
    633 =================
    634 Mod_LoadTexinfo
    635 =================
    636 */
    637 void Mod_LoadTexinfo (lump_t *l)
    638 {
    639 	texinfo_t *in;
    640 	mtexinfo_t *out;
    641 	int 	i, j, count;
    642 	int		miptex;
    643 	float	len1, len2;
    644 
    645 	in = (texinfo_t *)(mod_base + l->fileofs);
    646 	if (l->filelen % sizeof(*in))
    647 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    648 	count = l->filelen / sizeof(*in);
    649 	out = (mtexinfo_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
    650 
    651 	loadmodel->texinfo = out;
    652 	loadmodel->numtexinfo = count;
    653 
    654 	for ( i=0 ; i<count ; i++, in++, out++)
    655 	{
    656 		for (j=0 ; j<8 ; j++)
    657 			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
    658 		len1 = Length (out->vecs[0]);
    659 		len2 = Length (out->vecs[1]);
    660 		len1 = (len1 + len2)/2;
    661 		if (len1 < 0.32)
    662 			out->mipadjust = 4;
    663 		else if (len1 < 0.49)
    664 			out->mipadjust = 3;
    665 		else if (len1 < 0.99)
    666 			out->mipadjust = 2;
    667 		else
    668 			out->mipadjust = 1;
    669 #if 0
    670 		if (len1 + len2 < 0.001)
    671 			out->mipadjust = 1;		// don't crash
    672 		else
    673 			out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
    674 #endif
    675 
    676 		miptex = LittleLong (in->miptex);
    677 		out->flags = LittleLong (in->flags);
    678 
    679 		if (!loadmodel->textures)
    680 		{
    681 			out->texture = r_notexture_mip;	// checkerboard texture
    682 			out->flags = 0;
    683 		}
    684 		else
    685 		{
    686 			if (miptex >= loadmodel->numtextures)
    687 				Sys_Error ("miptex >= loadmodel->numtextures");
    688 			out->texture = loadmodel->textures[miptex];
    689 			if (!out->texture)
    690 			{
    691 				out->texture = r_notexture_mip; // texture not found
    692 				out->flags = 0;
    693 			}
    694 		}
    695 	}
    696 }
    697 
    698 /*
    699 ================
    700 CalcSurfaceExtents
    701 
    702 Fills in s->texturemins[] and s->extents[]
    703 ================
    704 */
    705 void CalcSurfaceExtents (msurface_t *s)
    706 {
    707 	float	mins[2], maxs[2], val;
    708 	int		i,j, e;
    709 	mvertex_t	*v;
    710 	mtexinfo_t	*tex;
    711 	int		bmins[2], bmaxs[2];
    712 
    713 	mins[0] = mins[1] = 999999;
    714 	maxs[0] = maxs[1] = -99999;
    715 
    716 	tex = s->texinfo;
    717 
    718 	for (i=0 ; i<s->numedges ; i++)
    719 	{
    720 		e = loadmodel->surfedges[s->firstedge+i];
    721 		if (e >= 0)
    722 			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
    723 		else
    724 			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
    725 
    726 		for (j=0 ; j<2 ; j++)
    727 		{
    728 			val = v->position[0] * tex->vecs[j][0] +
    729 				v->position[1] * tex->vecs[j][1] +
    730 				v->position[2] * tex->vecs[j][2] +
    731 				tex->vecs[j][3];
    732 			if (val < mins[j])
    733 				mins[j] = val;
    734 			if (val > maxs[j])
    735 				maxs[j] = val;
    736 		}
    737 	}
    738 
    739 	for (i=0 ; i<2 ; i++)
    740 	{
    741 		bmins[i] = (int) floorf(mins[i]/16);
    742 		bmaxs[i] = (int) ceilf(maxs[i]/16);
    743 
    744 		s->texturemins[i] = bmins[i] * 16;
    745 		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
    746 		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
    747 			Sys_Error ("Bad surface extents");
    748 	}
    749 }
    750 
    751 
    752 /*
    753 =================
    754 Mod_LoadFaces
    755 =================
    756 */
    757 void Mod_LoadFaces (lump_t *l)
    758 {
    759 	dface_t		*in;
    760 	msurface_t 	*out;
    761 	int			i, count, surfnum;
    762 	int			planenum, side;
    763 
    764 	in = (dface_t *)(mod_base + l->fileofs);
    765 	if (l->filelen % sizeof(*in))
    766 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    767 	count = l->filelen / sizeof(*in);
    768 	out = (msurface_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
    769 
    770 	loadmodel->surfaces = out;
    771 	loadmodel->numsurfaces = count;
    772 
    773 	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
    774 	{
    775 		out->firstedge = LittleLong(in->firstedge);
    776 		out->numedges = LittleShort(in->numedges);
    777 		out->flags = 0;
    778 
    779 		planenum = LittleShort(in->planenum);
    780 		side = LittleShort(in->side);
    781 		if (side)
    782 			out->flags |= SURF_PLANEBACK;
    783 
    784 		out->plane = loadmodel->planes + planenum;
    785 
    786 		out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
    787 
    788 		CalcSurfaceExtents (out);
    789 
    790 	// lighting info
    791 
    792 		for (i=0 ; i<MAXLIGHTMAPS ; i++)
    793 			out->styles[i] = in->styles[i];
    794 		i = LittleLong(in->lightofs);
    795 		if (i == -1)
    796 			out->samples = NULL;
    797 		else
    798 			out->samples = loadmodel->lightdata + i;
    799 
    800 	// set the drawing flags flag
    801 
    802 		if (!Q_strncmp(out->texinfo->texture->name,"sky",3))	// sky
    803 		{
    804 			out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
    805 #ifndef QUAKE2
    806 			GL_SubdivideSurface (out);	// cut up polygon for warps
    807 #endif
    808 			continue;
    809 		}
    810 
    811 		if (!Q_strncmp(out->texinfo->texture->name,"*",1))		// turbulent
    812 		{
    813 			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
    814 			for (i=0 ; i<2 ; i++)
    815 			{
    816 				out->extents[i] = 16384;
    817 				out->texturemins[i] = -8192;
    818 			}
    819 			GL_SubdivideSurface (out);	// cut up polygon for warps
    820 			continue;
    821 		}
    822 
    823 	}
    824 }
    825 
    826 
    827 /*
    828 =================
    829 Mod_SetParent
    830 =================
    831 */
    832 void Mod_SetParent (mnode_t *node, mnode_t *parent)
    833 {
    834 	node->parent = parent;
    835 	if (node->contents < 0)
    836 		return;
    837 	Mod_SetParent (node->children[0], node);
    838 	Mod_SetParent (node->children[1], node);
    839 }
    840 
    841 /*
    842 =================
    843 Mod_LoadNodes
    844 =================
    845 */
    846 void Mod_LoadNodes (lump_t *l)
    847 {
    848 	int			i, j, count, p;
    849 	dnode_t		*in;
    850 	mnode_t 	*out;
    851 
    852 	in = (dnode_t *)(mod_base + l->fileofs);
    853 	if (l->filelen % sizeof(*in))
    854 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    855 	count = l->filelen / sizeof(*in);
    856 	out = (mnode_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
    857 
    858 	loadmodel->nodes = out;
    859 	loadmodel->numnodes = count;
    860 
    861 	for ( i=0 ; i<count ; i++, in++, out++)
    862 	{
    863 		for (j=0 ; j<3 ; j++)
    864 		{
    865 			out->minmaxs[j] = LittleShort (in->mins[j]);
    866 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
    867 		}
    868 
    869 		p = LittleLong(in->planenum);
    870 		out->plane = loadmodel->planes + p;
    871 
    872 		out->firstsurface = LittleShort (in->firstface);
    873 		out->numsurfaces = LittleShort (in->numfaces);
    874 
    875 		for (j=0 ; j<2 ; j++)
    876 		{
    877 			p = LittleShort (in->children[j]);
    878 			if (p >= 0)
    879 				out->children[j] = loadmodel->nodes + p;
    880 			else
    881 				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
    882 		}
    883 	}
    884 
    885 	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
    886 }
    887 
    888 /*
    889 =================
    890 Mod_LoadLeafs
    891 =================
    892 */
    893 void Mod_LoadLeafs (lump_t *l)
    894 {
    895 	dleaf_t 	*in;
    896 	mleaf_t 	*out;
    897 	int			i, j, count, p;
    898 
    899 	in = (dleaf_t *)(mod_base + l->fileofs);
    900 	if (l->filelen % sizeof(*in))
    901 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    902 	count = l->filelen / sizeof(*in);
    903 	out = (mleaf_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
    904 
    905 	loadmodel->leafs = out;
    906 	loadmodel->numleafs = count;
    907 
    908 	for ( i=0 ; i<count ; i++, in++, out++)
    909 	{
    910 		for (j=0 ; j<3 ; j++)
    911 		{
    912 			out->minmaxs[j] = LittleShort (in->mins[j]);
    913 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
    914 		}
    915 
    916 		p = LittleLong(in->contents);
    917 		out->contents = p;
    918 
    919 		out->firstmarksurface = loadmodel->marksurfaces +
    920 			LittleShort(in->firstmarksurface);
    921 		out->nummarksurfaces = LittleShort(in->nummarksurfaces);
    922 
    923 		p = LittleLong(in->visofs);
    924 		if (p == -1)
    925 			out->compressed_vis = NULL;
    926 		else
    927 			out->compressed_vis = loadmodel->visdata + p;
    928 		out->efrags = NULL;
    929 
    930 		for (j=0 ; j<4 ; j++)
    931 			out->ambient_sound_level[j] = in->ambient_level[j];
    932 
    933 		// gl underwater warp
    934 		if (out->contents != CONTENTS_EMPTY)
    935 		{
    936 			for (j=0 ; j<out->nummarksurfaces ; j++)
    937 				out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
    938 		}
    939 	}
    940 }
    941 
    942 /*
    943 =================
    944 Mod_LoadClipnodes
    945 =================
    946 */
    947 void Mod_LoadClipnodes (lump_t *l)
    948 {
    949 	dclipnode_t *in, *out;
    950 	int			i, count;
    951 	hull_t		*hull;
    952 
    953 	in = (dclipnode_t *)(mod_base + l->fileofs);
    954 	if (l->filelen % sizeof(*in))
    955 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    956 	count = l->filelen / sizeof(*in);
    957 	out = (dclipnode_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
    958 
    959 	loadmodel->clipnodes = out;
    960 	loadmodel->numclipnodes = count;
    961 
    962 	hull = &loadmodel->hulls[1];
    963 	hull->clipnodes = out;
    964 	hull->firstclipnode = 0;
    965 	hull->lastclipnode = count-1;
    966 	hull->planes = loadmodel->planes;
    967 	hull->clip_mins[0] = -16;
    968 	hull->clip_mins[1] = -16;
    969 	hull->clip_mins[2] = -24;
    970 	hull->clip_maxs[0] = 16;
    971 	hull->clip_maxs[1] = 16;
    972 	hull->clip_maxs[2] = 32;
    973 
    974 	hull = &loadmodel->hulls[2];
    975 	hull->clipnodes = out;
    976 	hull->firstclipnode = 0;
    977 	hull->lastclipnode = count-1;
    978 	hull->planes = loadmodel->planes;
    979 	hull->clip_mins[0] = -32;
    980 	hull->clip_mins[1] = -32;
    981 	hull->clip_mins[2] = -24;
    982 	hull->clip_maxs[0] = 32;
    983 	hull->clip_maxs[1] = 32;
    984 	hull->clip_maxs[2] = 64;
    985 
    986 	for (i=0 ; i<count ; i++, out++, in++)
    987 	{
    988 		out->planenum = LittleLong(in->planenum);
    989 		out->children[0] = LittleShort(in->children[0]);
    990 		out->children[1] = LittleShort(in->children[1]);
    991 	}
    992 }
    993 
    994 /*
    995 =================
    996 Mod_MakeHull0
    997 
    998 Deplicate the drawing hull structure as a clipping hull
    999 =================
   1000 */
   1001 void Mod_MakeHull0 (void)
   1002 {
   1003 	mnode_t		*in, *child;
   1004 	dclipnode_t *out;
   1005 	int			i, j, count;
   1006 	hull_t		*hull;
   1007 
   1008 	hull = &loadmodel->hulls[0];
   1009 
   1010 	in = loadmodel->nodes;
   1011 	count = loadmodel->numnodes;
   1012 	out = (dclipnode_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
   1013 
   1014 	hull->clipnodes = out;
   1015 	hull->firstclipnode = 0;
   1016 	hull->lastclipnode = count-1;
   1017 	hull->planes = loadmodel->planes;
   1018 
   1019 	for (i=0 ; i<count ; i++, out++, in++)
   1020 	{
   1021 		out->planenum = in->plane - loadmodel->planes;
   1022 		for (j=0 ; j<2 ; j++)
   1023 		{
   1024 			child = in->children[j];
   1025 			if (child->contents < 0)
   1026 				out->children[j] = child->contents;
   1027 			else
   1028 				out->children[j] = child - loadmodel->nodes;
   1029 		}
   1030 	}
   1031 }
   1032 
   1033 /*
   1034 =================
   1035 Mod_LoadMarksurfaces
   1036 =================
   1037 */
   1038 void Mod_LoadMarksurfaces (lump_t *l)
   1039 {
   1040 	int		i, j, count;
   1041 	short		*in;
   1042 	msurface_t **out;
   1043 
   1044 	in = (short *)(mod_base + l->fileofs);
   1045 	if (l->filelen % sizeof(*in))
   1046 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
   1047 	count = l->filelen / sizeof(*in);
   1048 	out = (msurface_t **) Hunk_AllocName ( count*sizeof(*out), loadname);
   1049 
   1050 	loadmodel->marksurfaces = out;
   1051 	loadmodel->nummarksurfaces = count;
   1052 
   1053 	for ( i=0 ; i<count ; i++)
   1054 	{
   1055 		j = LittleShort(in[i]);
   1056 		if (j >= loadmodel->numsurfaces)
   1057 			Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
   1058 		out[i] = loadmodel->surfaces + j;
   1059 	}
   1060 }
   1061 
   1062 /*
   1063 =================
   1064 Mod_LoadSurfedges
   1065 =================
   1066 */
   1067 void Mod_LoadSurfedges (lump_t *l)
   1068 {
   1069 	int		i, count;
   1070 	int		*in, *out;
   1071 
   1072 	in = (int *)(mod_base + l->fileofs);
   1073 	if (l->filelen % sizeof(*in))
   1074 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
   1075 	count = l->filelen / sizeof(*in);
   1076 	out = (int*) Hunk_AllocName ( count*sizeof(*out), loadname);
   1077 
   1078 	loadmodel->surfedges = out;
   1079 	loadmodel->numsurfedges = count;
   1080 
   1081 	for ( i=0 ; i<count ; i++)
   1082 		out[i] = LittleLong (in[i]);
   1083 }
   1084 
   1085 
   1086 /*
   1087 =================
   1088 Mod_LoadPlanes
   1089 =================
   1090 */
   1091 void Mod_LoadPlanes (lump_t *l)
   1092 {
   1093 	int			i, j;
   1094 	mplane_t	*out;
   1095 	dplane_t 	*in;
   1096 	int			count;
   1097 	int			bits;
   1098 
   1099 	in = (dplane_t *)(mod_base + l->fileofs);
   1100 	if (l->filelen % sizeof(*in))
   1101 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
   1102 	count = l->filelen / sizeof(*in);
   1103 	out = (mplane_t*) Hunk_AllocName ( count*2*sizeof(*out), loadname);
   1104 
   1105 	loadmodel->planes = out;
   1106 	loadmodel->numplanes = count;
   1107 
   1108 	for ( i=0 ; i<count ; i++, in++, out++)
   1109 	{
   1110 		bits = 0;
   1111 		for (j=0 ; j<3 ; j++)
   1112 		{
   1113 			out->normal[j] = LittleFloat (in->normal[j]);
   1114 			if (out->normal[j] < 0)
   1115 				bits |= 1<<j;
   1116 		}
   1117 
   1118 		out->dist = LittleFloat (in->dist);
   1119 		out->type = LittleLong (in->type);
   1120 		out->signbits = bits;
   1121 	}
   1122 }
   1123 
   1124 /*
   1125 =================
   1126 RadiusFromBounds
   1127 =================
   1128 */
   1129 float RadiusFromBounds (vec3_t mins, vec3_t maxs)
   1130 {
   1131 	int		i;
   1132 	vec3_t	corner;
   1133 
   1134 	for (i=0 ; i<3 ; i++)
   1135 	{
   1136 		corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
   1137 	}
   1138 
   1139 	return Length (corner);
   1140 }
   1141 
   1142 /*
   1143 =================
   1144 Mod_LoadBrushModel
   1145 =================
   1146 */
   1147 void Mod_LoadBrushModel (model_t *mod, void *buffer)
   1148 {
   1149 	int			i, j;
   1150 	dheader_t	*header;
   1151 	dmodel_t 	*bm;
   1152 
   1153 	loadmodel->type = mod_brush;
   1154 
   1155 	header = (dheader_t *)buffer;
   1156 
   1157 	i = LittleLong (header->version);
   1158 	if (i != BSPVERSION)
   1159 		Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
   1160 
   1161 // swap all the lumps
   1162 	mod_base = (byte *)header;
   1163 
   1164 	for (i=0 ; i< (int) (sizeof(dheader_t)/4) ; i++)
   1165 		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
   1166 
   1167 // load into heap
   1168 
   1169 	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
   1170 	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
   1171 	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
   1172 	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
   1173 	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
   1174 	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
   1175 	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
   1176 	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
   1177 	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
   1178 	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
   1179 	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
   1180 	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
   1181 	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
   1182 	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
   1183 	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
   1184 
   1185 	Mod_MakeHull0 ();
   1186 
   1187 	mod->numframes = 2;		// regular and alternate animation
   1188 
   1189 //
   1190 // set up the submodels (FIXME: this is confusing)
   1191 //
   1192 	for (i=0 ; i<mod->numsubmodels ; i++)
   1193 	{
   1194 		bm = &mod->submodels[i];
   1195 
   1196 		mod->hulls[0].firstclipnode = bm->headnode[0];
   1197 		for (j=1 ; j<MAX_MAP_HULLS ; j++)
   1198 		{
   1199 			mod->hulls[j].firstclipnode = bm->headnode[j];
   1200 			mod->hulls[j].lastclipnode = mod->numclipnodes-1;
   1201 		}
   1202 
   1203 		mod->firstmodelsurface = bm->firstface;
   1204 		mod->nummodelsurfaces = bm->numfaces;
   1205 
   1206 		VectorCopy (bm->maxs, mod->maxs);
   1207 		VectorCopy (bm->mins, mod->mins);
   1208 
   1209 		mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
   1210 
   1211 		mod->numleafs = bm->visleafs;
   1212 
   1213 		if (i < mod->numsubmodels-1)
   1214 		{	// duplicate the basic information
   1215 			char	name[10];
   1216 
   1217 			sprintf (name, "*%i", i+1);
   1218 			loadmodel = Mod_FindName (name);
   1219 			*loadmodel = *mod;
   1220 			strcpy (loadmodel->name, name);
   1221 			mod = loadmodel;
   1222 		}
   1223 	}
   1224 }
   1225 
   1226 /*
   1227 ==============================================================================
   1228 
   1229 ALIAS MODELS
   1230 
   1231 ==============================================================================
   1232 */
   1233 
   1234 aliashdr_t	*pheader;
   1235 
   1236 stvert_t	stverts[MAXALIASVERTS];
   1237 mtriangle_t	triangles[MAXALIASTRIS];
   1238 
   1239 // a pose is a single set of vertexes.  a frame may be
   1240 // an animating sequence of poses
   1241 trivertx_t	*poseverts[MAXALIASFRAMES];
   1242 int			posenum;
   1243 
   1244 byte		**player_8bit_texels_tbl;
   1245 byte		*player_8bit_texels;
   1246 
   1247 /*
   1248 =================
   1249 Mod_LoadAliasFrame
   1250 =================
   1251 */
   1252 void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
   1253 {
   1254 	trivertx_t		*pframe, *pinframe;
   1255 	int				i, j;
   1256 	daliasframe_t	*pdaliasframe;
   1257 
   1258 	pdaliasframe = (daliasframe_t *)pin;
   1259 
   1260 	strcpy (frame->name, pdaliasframe->name);
   1261 	frame->firstpose = posenum;
   1262 	frame->numposes = 1;
   1263 
   1264 	for (i=0 ; i<3 ; i++)
   1265 	{
   1266 	// these are byte values, so we don't have to worry about
   1267 	// endianness
   1268 		frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
   1269 		frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
   1270 	}
   1271 
   1272 	pinframe = (trivertx_t *)(pdaliasframe + 1);
   1273 
   1274 	poseverts[posenum] = pinframe;
   1275 	posenum++;
   1276 
   1277 	pinframe += pheader->numverts;
   1278 
   1279 	return (void *)pinframe;
   1280 }
   1281 
   1282 
   1283 /*
   1284 =================
   1285 Mod_LoadAliasGroup
   1286 =================
   1287 */
   1288 void *Mod_LoadAliasGroup (void * pin,  maliasframedesc_t *frame)
   1289 {
   1290 	daliasgroup_t		*pingroup;
   1291 	int					i, numframes;
   1292 	daliasinterval_t	*pin_intervals;
   1293 	void				*ptemp;
   1294 
   1295 	pingroup = (daliasgroup_t *)pin;
   1296 
   1297 	numframes = LittleLong (pingroup->numframes);
   1298 
   1299 	frame->firstpose = posenum;
   1300 	frame->numposes = numframes;
   1301 
   1302 	for (i=0 ; i<3 ; i++)
   1303 	{
   1304 	// these are byte values, so we don't have to worry about endianness
   1305 		frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
   1306 		frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
   1307 	}
   1308 
   1309 	pin_intervals = (daliasinterval_t *)(pingroup + 1);
   1310 
   1311 	frame->interval = LittleFloat (pin_intervals->interval);
   1312 
   1313 	pin_intervals += numframes;
   1314 
   1315 	ptemp = (void *)pin_intervals;
   1316 
   1317 	for (i=0 ; i<numframes ; i++)
   1318 	{
   1319 		poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
   1320 		posenum++;
   1321 
   1322 		ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
   1323 	}
   1324 
   1325 	return ptemp;
   1326 }
   1327 
   1328 //=========================================================
   1329 
   1330 /*
   1331 =================
   1332 Mod_FloodFillSkin
   1333 
   1334 Fill background pixels so mipmapping doesn't have haloes - Ed
   1335 =================
   1336 */
   1337 
   1338 typedef struct
   1339 {
   1340 	short		x, y;
   1341 } floodfill_t;
   1342 
   1343 extern unsigned d_8to24table[];
   1344 
   1345 // must be a power of 2
   1346 #define FLOODFILL_FIFO_SIZE 0x1000
   1347 #define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
   1348 
   1349 #define FLOODFILL_STEP( off, dx, dy ) \
   1350 { \
   1351 	if (pos[off] == fillcolor) \
   1352 	{ \
   1353 		pos[off] = 255; \
   1354 		fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
   1355 		inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
   1356 	} \
   1357 	else if (pos[off] != 255) fdc = pos[off]; \
   1358 }
   1359 
   1360 void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
   1361 {
   1362 	byte				fillcolor = *skin; // assume this is the pixel to fill
   1363 	floodfill_t			fifo[FLOODFILL_FIFO_SIZE];
   1364 	int					inpt = 0, outpt = 0;
   1365 	int					filledcolor = -1;
   1366 	int					i;
   1367 
   1368 	if (filledcolor == -1)
   1369 	{
   1370 		filledcolor = 0;
   1371 		// attempt to find opaque black
   1372 		for (i = 0; i < 256; ++i)
   1373 			if (d_8to24table[i] == (255 << 0)) // alpha 1.0
   1374 			{
   1375 				filledcolor = i;
   1376 				break;
   1377 			}
   1378 	}
   1379 
   1380 	// can't fill to filled color or to transparent color (used as visited marker)
   1381 	if ((fillcolor == filledcolor) || (fillcolor == 255))
   1382 	{
   1383 		//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
   1384 		return;
   1385 	}
   1386 
   1387 	fifo[inpt].x = 0, fifo[inpt].y = 0;
   1388 	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
   1389 
   1390 	while (outpt != inpt)
   1391 	{
   1392 		int			x = fifo[outpt].x, y = fifo[outpt].y;
   1393 		int			fdc = filledcolor;
   1394 		byte		*pos = &skin[x + skinwidth * y];
   1395 
   1396 		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
   1397 
   1398 		if (x > 0)				FLOODFILL_STEP( -1, -1, 0 );
   1399 		if (x < skinwidth - 1)	FLOODFILL_STEP( 1, 1, 0 );
   1400 		if (y > 0)				FLOODFILL_STEP( -skinwidth, 0, -1 );
   1401 		if (y < skinheight - 1)	FLOODFILL_STEP( skinwidth, 0, 1 );
   1402 		skin[x + skinwidth * y] = fdc;
   1403 	}
   1404 }
   1405 
   1406 /*
   1407 ===============
   1408 Mod_LoadAllSkins
   1409 ===============
   1410 */
   1411 void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
   1412 {
   1413 	int		i, j, k;
   1414 	char	name[32];
   1415 	int		s;
   1416 	byte	*copy;
   1417 	byte	*skin;
   1418 	byte	*texels;
   1419 	daliasskingroup_t		*pinskingroup;
   1420 	int		groupskins;
   1421 	daliasskininterval_t	*pinskinintervals;
   1422 
   1423 	skin = (byte *)(pskintype + 1);
   1424 
   1425 	if (numskins < 1 || numskins > MAX_SKINS)
   1426 		Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
   1427 
   1428 	s = pheader->skinwidth * pheader->skinheight;
   1429 
   1430 	for (i=0 ; i<numskins ; i++)
   1431 	{
   1432 		if (pskintype->type == ALIAS_SKIN_SINGLE) {
   1433 			Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
   1434 
   1435 			// save 8 bit texels for the player model to remap
   1436 	//		if (!strcmp(loadmodel->name,"progs/player.mdl")) {
   1437 				texels = (byte*) Hunk_AllocName(s, loadname);
   1438 				pheader->texels[i] = texels - (byte *)pheader;
   1439 				memcpy (texels, (byte *)(pskintype + 1), s);
   1440 	//		}
   1441 			sprintf (name, "%s_%i", loadmodel->name, i);
   1442 			pheader->gl_texturenum[i][0] =
   1443 			pheader->gl_texturenum[i][1] =
   1444 			pheader->gl_texturenum[i][2] =
   1445 			pheader->gl_texturenum[i][3] =
   1446 				GL_LoadTexture (name, pheader->skinwidth,
   1447 				pheader->skinheight, (byte *)(pskintype + 1), true, false);
   1448 			pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
   1449 		} else {
   1450 			// animating skin group.  yuck.
   1451 			pskintype++;
   1452 			pinskingroup = (daliasskingroup_t *)pskintype;
   1453 			groupskins = LittleLong (pinskingroup->numskins);
   1454 			pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
   1455 
   1456 			pskintype = (daliasskintype_t *)(pinskinintervals + groupskins);
   1457 
   1458 			for (j=0 ; j<groupskins ; j++)
   1459 			{
   1460 					Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
   1461 					if (j == 0) {
   1462 						texels = (byte*) Hunk_AllocName(s, loadname);
   1463 						pheader->texels[i] = texels - (byte *)pheader;
   1464 						memcpy (texels, (byte *)(pskintype), s);
   1465 					}
   1466 					sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
   1467 					pheader->gl_texturenum[i][j&3] =
   1468 						GL_LoadTexture (name, pheader->skinwidth,
   1469 						pheader->skinheight, (byte *)(pskintype), true, false);
   1470 					pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
   1471 			}
   1472 			k = j;
   1473 			for (/* */; j < 4; j++)
   1474 				pheader->gl_texturenum[i][j&3] =
   1475 				pheader->gl_texturenum[i][j - k];
   1476 		}
   1477 	}
   1478 
   1479 	return (void *)pskintype;
   1480 }
   1481 
   1482 //=========================================================================
   1483 
   1484 /*
   1485 =================
   1486 Mod_LoadAliasModel
   1487 =================
   1488 */
   1489 void Mod_LoadAliasModel (model_t *mod, void *buffer)
   1490 {
   1491 	int					i, j;
   1492 	mdl_t				*pinmodel;
   1493 	stvert_t			*pinstverts;
   1494 	dtriangle_t			*pintriangles;
   1495 	int					version, numframes, numskins;
   1496 	int					size;
   1497 	daliasframetype_t	*pframetype;
   1498 	daliasskintype_t	*pskintype;
   1499 	int					start, end, total;
   1500 
   1501 	start = Hunk_LowMark ();
   1502 
   1503 	pinmodel = (mdl_t *)buffer;
   1504 
   1505 	version = LittleLong (pinmodel->version);
   1506 	if (version != ALIAS_VERSION)
   1507 		Sys_Error ("%s has wrong version number (%i should be %i)",
   1508 				 mod->name, version, ALIAS_VERSION);
   1509 
   1510 //
   1511 // allocate space for a working header, plus all the data except the frames,
   1512 // skin and group info
   1513 //
   1514 	size = 	sizeof (aliashdr_t)
   1515 			+ (LittleLong (pinmodel->numframes) - 1) *
   1516 			sizeof (pheader->frames[0]);
   1517 	pheader = (aliashdr_t*) Hunk_AllocName (size, loadname);
   1518 
   1519 	mod->flags = LittleLong (pinmodel->flags);
   1520 
   1521 //
   1522 // endian-adjust and copy the data, starting with the alias model header
   1523 //
   1524 	pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
   1525 	pheader->numskins = LittleLong (pinmodel->numskins);
   1526 	pheader->skinwidth = LittleLong (pinmodel->skinwidth);
   1527 	pheader->skinheight = LittleLong (pinmodel->skinheight);
   1528 
   1529 	if (pheader->skinheight > MAX_LBM_HEIGHT)
   1530 		Sys_Error ("model %s has a skin taller than %d", mod->name,
   1531 				   MAX_LBM_HEIGHT);
   1532 
   1533 	pheader->numverts = LittleLong (pinmodel->numverts);
   1534 
   1535 	if (pheader->numverts <= 0)
   1536 		Sys_Error ("model %s has no vertices", mod->name);
   1537 
   1538 	if (pheader->numverts > MAXALIASVERTS)
   1539 		Sys_Error ("model %s has too many vertices", mod->name);
   1540 
   1541 	pheader->numtris = LittleLong (pinmodel->numtris);
   1542 
   1543 	if (pheader->numtris <= 0)
   1544 		Sys_Error ("model %s has no triangles", mod->name);
   1545 
   1546 	pheader->numframes = LittleLong (pinmodel->numframes);
   1547 	numframes = pheader->numframes;
   1548 	if (numframes < 1)
   1549 		Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
   1550 
   1551 	pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
   1552 	mod->synctype = (synctype_t) LittleLong (pinmodel->synctype);
   1553 	mod->numframes = pheader->numframes;
   1554 
   1555 	for (i=0 ; i<3 ; i++)
   1556 	{
   1557 		pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
   1558 		pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
   1559 		pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
   1560 	}
   1561 
   1562 
   1563 //
   1564 // load the skins
   1565 //
   1566 	pskintype = (daliasskintype_t *)&pinmodel[1];
   1567 	pskintype = (daliasskintype_t*) Mod_LoadAllSkins (pheader->numskins, pskintype);
   1568 
   1569 //
   1570 // load base s and t vertices
   1571 //
   1572 	pinstverts = (stvert_t *)pskintype;
   1573 
   1574 	for (i=0 ; i<pheader->numverts ; i++)
   1575 	{
   1576 		stverts[i].onseam = LittleLong (pinstverts[i].onseam);
   1577 		stverts[i].s = LittleLong (pinstverts[i].s);
   1578 		stverts[i].t = LittleLong (pinstverts[i].t);
   1579 	}
   1580 
   1581 //
   1582 // load triangle lists
   1583 //
   1584 	pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
   1585 
   1586 	for (i=0 ; i<pheader->numtris ; i++)
   1587 	{
   1588 		triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
   1589 
   1590 		for (j=0 ; j<3 ; j++)
   1591 		{
   1592 			triangles[i].vertindex[j] =
   1593 					LittleLong (pintriangles[i].vertindex[j]);
   1594 		}
   1595 	}
   1596 
   1597 //
   1598 // load the frames
   1599 //
   1600 	posenum = 0;
   1601 	pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
   1602 
   1603 	for (i=0 ; i<numframes ; i++)
   1604 	{
   1605 		aliasframetype_t	frametype;
   1606 
   1607 		frametype = (aliasframetype_t) LittleLong (pframetype->type);
   1608 
   1609 		if (frametype == ALIAS_SINGLE)
   1610 		{
   1611 			pframetype = (daliasframetype_t *)
   1612 					Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
   1613 		}
   1614 		else
   1615 		{
   1616 			pframetype = (daliasframetype_t *)
   1617 					Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
   1618 		}
   1619 	}
   1620 
   1621 	pheader->numposes = posenum;
   1622 
   1623 	mod->type = mod_alias;
   1624 
   1625 // FIXME: do this right
   1626 	mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
   1627 	mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
   1628 
   1629 	//
   1630 	// build the draw lists
   1631 	//
   1632 	GL_MakeAliasModelDisplayLists (mod, pheader);
   1633 
   1634 //
   1635 // move the complete, relocatable alias model to the cache
   1636 //
   1637 	end = Hunk_LowMark ();
   1638 	total = end - start;
   1639 
   1640 	Cache_Alloc (&mod->cache, total, loadname);
   1641 	if (!mod->cache.data)
   1642 		return;
   1643 	memcpy (mod->cache.data, pheader, total);
   1644 
   1645 	Hunk_FreeToLowMark (start);
   1646 }
   1647 
   1648 //=============================================================================
   1649 
   1650 /*
   1651 =================
   1652 Mod_LoadSpriteFrame
   1653 =================
   1654 */
   1655 void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
   1656 {
   1657 	dspriteframe_t		*pinframe;
   1658 	mspriteframe_t		*pspriteframe;
   1659 	int					i, width, height, size, origin[2];
   1660 	unsigned short		*ppixout;
   1661 	byte				*ppixin;
   1662 	char				name[64];
   1663 
   1664 	pinframe = (dspriteframe_t *)pin;
   1665 
   1666 	width = LittleLong (pinframe->width);
   1667 	height = LittleLong (pinframe->height);
   1668 	size = width * height;
   1669 
   1670 	pspriteframe = (mspriteframe_t*) Hunk_AllocName (sizeof (mspriteframe_t),loadname);
   1671 
   1672 	Q_memset (pspriteframe, 0, sizeof (mspriteframe_t));
   1673 
   1674 	*ppframe = pspriteframe;
   1675 
   1676 	pspriteframe->width = width;
   1677 	pspriteframe->height = height;
   1678 	origin[0] = LittleLong (pinframe->origin[0]);
   1679 	origin[1] = LittleLong (pinframe->origin[1]);
   1680 
   1681 	pspriteframe->up = origin[1];
   1682 	pspriteframe->down = origin[1] - height;
   1683 	pspriteframe->left = origin[0];
   1684 	pspriteframe->right = width + origin[0];
   1685 
   1686 	sprintf (name, "%s_%i", loadmodel->name, framenum);
   1687 	pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true);
   1688 
   1689 	return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
   1690 }
   1691 
   1692 
   1693 /*
   1694 =================
   1695 Mod_LoadSpriteGroup
   1696 =================
   1697 */
   1698 void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum)
   1699 {
   1700 	dspritegroup_t		*pingroup;
   1701 	mspritegroup_t		*pspritegroup;
   1702 	int					i, numframes;
   1703 	dspriteinterval_t	*pin_intervals;
   1704 	float				*poutintervals;
   1705 	void				*ptemp;
   1706 
   1707 	pingroup = (dspritegroup_t *)pin;
   1708 
   1709 	numframes = LittleLong (pingroup->numframes);
   1710 
   1711 	pspritegroup = (mspritegroup_t*) Hunk_AllocName (sizeof (mspritegroup_t) +
   1712 				(numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
   1713 
   1714 	pspritegroup->numframes = numframes;
   1715 
   1716 	*ppframe = (mspriteframe_t *)pspritegroup;
   1717 
   1718 	pin_intervals = (dspriteinterval_t *)(pingroup + 1);
   1719 
   1720 	poutintervals = (float*) Hunk_AllocName (numframes * sizeof (float), loadname);
   1721 
   1722 	pspritegroup->intervals = poutintervals;
   1723 
   1724 	for (i=0 ; i<numframes ; i++)
   1725 	{
   1726 		*poutintervals = LittleFloat (pin_intervals->interval);
   1727 		if (*poutintervals <= 0.0)
   1728 			Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
   1729 
   1730 		poutintervals++;
   1731 		pin_intervals++;
   1732 	}
   1733 
   1734 	ptemp = (void *)pin_intervals;
   1735 
   1736 	for (i=0 ; i<numframes ; i++)
   1737 	{
   1738 		ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i);
   1739 	}
   1740 
   1741 	return ptemp;
   1742 }
   1743 
   1744 
   1745 /*
   1746 =================
   1747 Mod_LoadSpriteModel
   1748 =================
   1749 */
   1750 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
   1751 {
   1752 	int					i;
   1753 	int					version;
   1754 	dsprite_t			*pin;
   1755 	msprite_t			*psprite;
   1756 	int					numframes;
   1757 	int					size;
   1758 	dspriteframetype_t	*pframetype;
   1759 
   1760 	pin = (dsprite_t *)buffer;
   1761 
   1762 	version = LittleLong (pin->version);
   1763 	if (version != SPRITE_VERSION)
   1764 		Sys_Error ("%s has wrong version number "
   1765 				 "(%i should be %i)", mod->name, version, SPRITE_VERSION);
   1766 
   1767 	numframes = LittleLong (pin->numframes);
   1768 
   1769 	size = sizeof (msprite_t) +	(numframes - 1) * sizeof (psprite->frames);
   1770 
   1771 	psprite = (msprite_t*) Hunk_AllocName (size, loadname);
   1772 
   1773 	mod->cache.data = psprite;
   1774 
   1775 	psprite->type = LittleLong (pin->type);
   1776 	psprite->maxwidth = LittleLong (pin->width);
   1777 	psprite->maxheight = LittleLong (pin->height);
   1778 	psprite->beamlength = LittleFloat (pin->beamlength);
   1779 	mod->synctype = (synctype_t) LittleLong (pin->synctype);
   1780 	psprite->numframes = numframes;
   1781 
   1782 	mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
   1783 	mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
   1784 	mod->mins[2] = -psprite->maxheight/2;
   1785 	mod->maxs[2] = psprite->maxheight/2;
   1786 
   1787 //
   1788 // load the frames
   1789 //
   1790 	if (numframes < 1)
   1791 		Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
   1792 
   1793 	mod->numframes = numframes;
   1794 
   1795 	pframetype = (dspriteframetype_t *)(pin + 1);
   1796 
   1797 	for (i=0 ; i<numframes ; i++)
   1798 	{
   1799 		spriteframetype_t	frametype;
   1800 
   1801 		frametype = (spriteframetype_t) LittleLong (pframetype->type);
   1802 		psprite->frames[i].type = frametype;
   1803 
   1804 		if (frametype == SPR_SINGLE)
   1805 		{
   1806 			pframetype = (dspriteframetype_t *)
   1807 					Mod_LoadSpriteFrame (pframetype + 1,
   1808 										 &psprite->frames[i].frameptr, i);
   1809 		}
   1810 		else
   1811 		{
   1812 			pframetype = (dspriteframetype_t *)
   1813 					Mod_LoadSpriteGroup (pframetype + 1,
   1814 										 &psprite->frames[i].frameptr, i);
   1815 		}
   1816 	}
   1817 
   1818 	mod->type = mod_sprite;
   1819 }
   1820 
   1821 //=============================================================================
   1822 
   1823 /*
   1824 ================
   1825 Mod_Print
   1826 ================
   1827 */
   1828 void Mod_Print (void)
   1829 {
   1830 	int		i;
   1831 	model_t	*mod;
   1832 
   1833 	Con_Printf ("Cached models:\n");
   1834 	for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
   1835 	{
   1836 		Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
   1837 	}
   1838 }
   1839 
   1840 
   1841