Home | History | Annotate | Download | only in server
      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 "qwsvdef.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 texture_t	r_notexture_mip;
     42 
     43 unsigned *model_checksum;
     44 
     45 /*
     46 ===============
     47 Mod_Init
     48 ===============
     49 */
     50 void Mod_Init (void)
     51 {
     52 	memset (mod_novis, 0xff, sizeof(mod_novis));
     53 }
     54 
     55 /*
     56 ===============
     57 Mod_PointInLeaf
     58 ===============
     59 */
     60 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
     61 {
     62 	mnode_t		*node;
     63 	float		d;
     64 	mplane_t	*plane;
     65 
     66 	if (!model || !model->nodes)
     67 		SV_Error ("Mod_PointInLeaf: bad model");
     68 
     69 	node = model->nodes;
     70 	while (1)
     71 	{
     72 		if (node->contents < 0)
     73 			return (mleaf_t *)node;
     74 		plane = node->plane;
     75 		d = DotProduct (p,plane->normal) - plane->dist;
     76 		if (d > 0)
     77 			node = node->children[0];
     78 		else
     79 			node = node->children[1];
     80 	}
     81 
     82 	return NULL;	// never reached
     83 }
     84 
     85 
     86 /*
     87 ===================
     88 Mod_DecompressVis
     89 ===================
     90 */
     91 byte *Mod_DecompressVis (byte *in, model_t *model)
     92 {
     93 	static byte	decompressed[MAX_MAP_LEAFS/8];
     94 	int		c;
     95 	byte	*out;
     96 	int		row;
     97 
     98 	row = (model->numleafs+7)>>3;
     99 	out = decompressed;
    100 
    101 #if 0
    102 	memcpy (out, in, row);
    103 #else
    104 	if (!in)
    105 	{	// no vis info, so make all visible
    106 		while (row)
    107 		{
    108 			*out++ = 0xff;
    109 			row--;
    110 		}
    111 		return decompressed;
    112 	}
    113 
    114 	do
    115 	{
    116 		if (*in)
    117 		{
    118 			*out++ = *in++;
    119 			continue;
    120 		}
    121 
    122 		c = in[1];
    123 		in += 2;
    124 		while (c)
    125 		{
    126 			*out++ = 0;
    127 			c--;
    128 		}
    129 	} while (out - decompressed < row);
    130 #endif
    131 
    132 	return decompressed;
    133 }
    134 
    135 byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
    136 {
    137 	if (leaf == model->leafs)
    138 		return mod_novis;
    139 	return Mod_DecompressVis (leaf->compressed_vis, model);
    140 }
    141 
    142 /*
    143 ===================
    144 Mod_ClearAll
    145 ===================
    146 */
    147 void Mod_ClearAll (void)
    148 {
    149 	int		i;
    150 	model_t	*mod;
    151 
    152 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
    153 		if (mod->type != mod_alias)
    154 			mod->needload = true;
    155 }
    156 
    157 /*
    158 ==================
    159 Mod_FindName
    160 
    161 ==================
    162 */
    163 model_t *Mod_FindName (char *name)
    164 {
    165 	int		i;
    166 	model_t	*mod;
    167 
    168 	if (!name[0])
    169 		SV_Error ("Mod_ForName: NULL name");
    170 
    171 //
    172 // search the currently loaded models
    173 //
    174 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
    175 		if (!strcmp (mod->name, name) )
    176 			break;
    177 
    178 	if (i == mod_numknown)
    179 	{
    180 		if (mod_numknown == MAX_MOD_KNOWN)
    181 			SV_Error ("mod_numknown == MAX_MOD_KNOWN");
    182 		strcpy (mod->name, name);
    183 		mod->needload = true;
    184 		mod_numknown++;
    185 	}
    186 
    187 	return mod;
    188 }
    189 
    190 
    191 /*
    192 ==================
    193 Mod_LoadModel
    194 
    195 Loads a model into the cache
    196 ==================
    197 */
    198 model_t *Mod_LoadModel (model_t *mod, qboolean crash)
    199 {
    200 	void	*d;
    201 	unsigned *buf;
    202 	byte	stackbuf[1024];		// avoid dirtying the cache heap
    203 
    204 	if (!mod->needload)
    205 	{
    206 		if (mod->type == mod_alias)
    207 		{
    208 			d = Cache_Check (&mod->cache);
    209 			if (d)
    210 				return mod;
    211 		}
    212 		else
    213 			return mod;		// not cached at all
    214 	}
    215 
    216 //
    217 // load the file
    218 //
    219 	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
    220 	if (!buf)
    221 	{
    222 		if (crash)
    223 			SV_Error ("Mod_NumForName: %s not found", mod->name);
    224 		return NULL;
    225 	}
    226 
    227 //
    228 // allocate a new model
    229 //
    230 	COM_FileBase (mod->name, loadname);
    231 
    232 	loadmodel = mod;
    233 
    234 //
    235 // fill it in
    236 //
    237 
    238 // call the apropriate loader
    239 	mod->needload = false;
    240 
    241 	Mod_LoadBrushModel (mod, buf);
    242 
    243 	return mod;
    244 }
    245 
    246 /*
    247 ==================
    248 Mod_ForName
    249 
    250 Loads in a model for the given name
    251 ==================
    252 */
    253 model_t *Mod_ForName (char *name, qboolean crash)
    254 {
    255 	model_t	*mod;
    256 
    257 	mod = Mod_FindName (name);
    258 
    259 	return Mod_LoadModel (mod, crash);
    260 }
    261 
    262 
    263 /*
    264 ===============================================================================
    265 
    266 					BRUSHMODEL LOADING
    267 
    268 ===============================================================================
    269 */
    270 
    271 byte	*mod_base;
    272 
    273 
    274 /*
    275 =================
    276 Mod_LoadTextures
    277 =================
    278 */
    279 void Mod_LoadTextures (lump_t *l)
    280 {
    281 	int		i, j, pixels, num, max, altmax;
    282 	miptex_t	*mt;
    283 	texture_t	*tx, *tx2;
    284 	texture_t	*anims[10];
    285 	texture_t	*altanims[10];
    286 	dmiptexlump_t *m;
    287 
    288 	if (!l->filelen)
    289 	{
    290 		loadmodel->textures = NULL;
    291 		return;
    292 	}
    293 	m = (dmiptexlump_t *)(mod_base + l->fileofs);
    294 
    295 	m->nummiptex = LittleLong (m->nummiptex);
    296 
    297 	loadmodel->numtextures = m->nummiptex;
    298 	loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
    299 
    300 	for (i=0 ; i<m->nummiptex ; i++)
    301 	{
    302 		m->dataofs[i] = LittleLong(m->dataofs[i]);
    303 		if (m->dataofs[i] == -1)
    304 			continue;
    305 		mt = (miptex_t *)((byte *)m + m->dataofs[i]);
    306 		mt->width = LittleLong (mt->width);
    307 		mt->height = LittleLong (mt->height);
    308 		for (j=0 ; j<MIPLEVELS ; j++)
    309 			mt->offsets[j] = LittleLong (mt->offsets[j]);
    310 
    311 		if ( (mt->width & 15) || (mt->height & 15) )
    312 			SV_Error ("Texture %s is not 16 aligned", mt->name);
    313 		pixels = mt->width*mt->height/64*85;
    314 		tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
    315 		loadmodel->textures[i] = tx;
    316 
    317 		memcpy (tx->name, mt->name, sizeof(tx->name));
    318 		tx->width = mt->width;
    319 		tx->height = mt->height;
    320 		for (j=0 ; j<MIPLEVELS ; j++)
    321 			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
    322 		// the pixels immediately follow the structures
    323 		memcpy ( tx+1, mt+1, pixels);
    324 	}
    325 
    326 //
    327 // sequence the animations
    328 //
    329 	for (i=0 ; i<m->nummiptex ; i++)
    330 	{
    331 		tx = loadmodel->textures[i];
    332 		if (!tx || tx->name[0] != '+')
    333 			continue;
    334 		if (tx->anim_next)
    335 			continue;	// allready sequenced
    336 
    337 	// find the number of frames in the animation
    338 		memset (anims, 0, sizeof(anims));
    339 		memset (altanims, 0, sizeof(altanims));
    340 
    341 		max = tx->name[1];
    342 		altmax = 0;
    343 		if (max >= 'a' && max <= 'z')
    344 			max -= 'a' - 'A';
    345 		if (max >= '0' && max <= '9')
    346 		{
    347 			max -= '0';
    348 			altmax = 0;
    349 			anims[max] = tx;
    350 			max++;
    351 		}
    352 		else if (max >= 'A' && max <= 'J')
    353 		{
    354 			altmax = max - 'A';
    355 			max = 0;
    356 			altanims[altmax] = tx;
    357 			altmax++;
    358 		}
    359 		else
    360 			SV_Error ("Bad animating texture %s", tx->name);
    361 
    362 		for (j=i+1 ; j<m->nummiptex ; j++)
    363 		{
    364 			tx2 = loadmodel->textures[j];
    365 			if (!tx2 || tx2->name[0] != '+')
    366 				continue;
    367 			if (strcmp (tx2->name+2, tx->name+2))
    368 				continue;
    369 
    370 			num = tx2->name[1];
    371 			if (num >= 'a' && num <= 'z')
    372 				num -= 'a' - 'A';
    373 			if (num >= '0' && num <= '9')
    374 			{
    375 				num -= '0';
    376 				anims[num] = tx2;
    377 				if (num+1 > max)
    378 					max = num + 1;
    379 			}
    380 			else if (num >= 'A' && num <= 'J')
    381 			{
    382 				num = num - 'A';
    383 				altanims[num] = tx2;
    384 				if (num+1 > altmax)
    385 					altmax = num+1;
    386 			}
    387 			else
    388 				SV_Error ("Bad animating texture %s", tx->name);
    389 		}
    390 
    391 #define	ANIM_CYCLE	2
    392 	// link them all together
    393 		for (j=0 ; j<max ; j++)
    394 		{
    395 			tx2 = anims[j];
    396 			if (!tx2)
    397 				SV_Error ("Missing frame %i of %s",j, tx->name);
    398 			tx2->anim_total = max * ANIM_CYCLE;
    399 			tx2->anim_min = j * ANIM_CYCLE;
    400 			tx2->anim_max = (j+1) * ANIM_CYCLE;
    401 			tx2->anim_next = anims[ (j+1)%max ];
    402 			if (altmax)
    403 				tx2->alternate_anims = altanims[0];
    404 		}
    405 		for (j=0 ; j<altmax ; j++)
    406 		{
    407 			tx2 = altanims[j];
    408 			if (!tx2)
    409 				SV_Error ("Missing frame %i of %s",j, tx->name);
    410 			tx2->anim_total = altmax * ANIM_CYCLE;
    411 			tx2->anim_min = j * ANIM_CYCLE;
    412 			tx2->anim_max = (j+1) * ANIM_CYCLE;
    413 			tx2->anim_next = altanims[ (j+1)%altmax ];
    414 			if (max)
    415 				tx2->alternate_anims = anims[0];
    416 		}
    417 	}
    418 }
    419 
    420 /*
    421 =================
    422 Mod_LoadLighting
    423 =================
    424 */
    425 void Mod_LoadLighting (lump_t *l)
    426 {
    427 	if (!l->filelen)
    428 	{
    429 		loadmodel->lightdata = NULL;
    430 		return;
    431 	}
    432 	loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
    433 	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
    434 }
    435 
    436 
    437 /*
    438 =================
    439 Mod_LoadVisibility
    440 =================
    441 */
    442 void Mod_LoadVisibility (lump_t *l)
    443 {
    444 	if (!l->filelen)
    445 	{
    446 		loadmodel->visdata = NULL;
    447 		return;
    448 	}
    449 	loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);
    450 	memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
    451 }
    452 
    453 
    454 /*
    455 =================
    456 Mod_LoadEntities
    457 =================
    458 */
    459 void Mod_LoadEntities (lump_t *l)
    460 {
    461 	if (!l->filelen)
    462 	{
    463 		loadmodel->entities = NULL;
    464 		return;
    465 	}
    466 	loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);
    467 	memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
    468 }
    469 
    470 
    471 /*
    472 =================
    473 Mod_LoadVertexes
    474 =================
    475 */
    476 void Mod_LoadVertexes (lump_t *l)
    477 {
    478 	dvertex_t	*in;
    479 	mvertex_t	*out;
    480 	int			i, count;
    481 
    482 	in = (void *)(mod_base + l->fileofs);
    483 	if (l->filelen % sizeof(*in))
    484 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    485 	count = l->filelen / sizeof(*in);
    486 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    487 
    488 	loadmodel->vertexes = out;
    489 	loadmodel->numvertexes = count;
    490 
    491 	for ( i=0 ; i<count ; i++, in++, out++)
    492 	{
    493 		out->position[0] = LittleFloat (in->point[0]);
    494 		out->position[1] = LittleFloat (in->point[1]);
    495 		out->position[2] = LittleFloat (in->point[2]);
    496 	}
    497 }
    498 
    499 /*
    500 =================
    501 Mod_LoadSubmodels
    502 =================
    503 */
    504 void Mod_LoadSubmodels (lump_t *l)
    505 {
    506 	dmodel_t	*in;
    507 	dmodel_t	*out;
    508 	int			i, j, count;
    509 
    510 	in = (void *)(mod_base + l->fileofs);
    511 	if (l->filelen % sizeof(*in))
    512 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    513 	count = l->filelen / sizeof(*in);
    514 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    515 
    516 	loadmodel->submodels = out;
    517 	loadmodel->numsubmodels = count;
    518 
    519 	for ( i=0 ; i<count ; i++, in++, out++)
    520 	{
    521 		for (j=0 ; j<3 ; j++)
    522 		{	// spread the mins / maxs by a pixel
    523 			out->mins[j] = LittleFloat (in->mins[j]) - 1;
    524 			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
    525 			out->origin[j] = LittleFloat (in->origin[j]);
    526 		}
    527 		for (j=0 ; j<MAX_MAP_HULLS ; j++)
    528 			out->headnode[j] = LittleLong (in->headnode[j]);
    529 		out->visleafs = LittleLong (in->visleafs);
    530 		out->firstface = LittleLong (in->firstface);
    531 		out->numfaces = LittleLong (in->numfaces);
    532 	}
    533 }
    534 
    535 /*
    536 =================
    537 Mod_LoadEdges
    538 =================
    539 */
    540 void Mod_LoadEdges (lump_t *l)
    541 {
    542 	dedge_t *in;
    543 	medge_t *out;
    544 	int 	i, count;
    545 
    546 	in = (void *)(mod_base + l->fileofs);
    547 	if (l->filelen % sizeof(*in))
    548 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    549 	count = l->filelen / sizeof(*in);
    550 	out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
    551 
    552 	loadmodel->edges = out;
    553 	loadmodel->numedges = count;
    554 
    555 	for ( i=0 ; i<count ; i++, in++, out++)
    556 	{
    557 		out->v[0] = (unsigned short)LittleShort(in->v[0]);
    558 		out->v[1] = (unsigned short)LittleShort(in->v[1]);
    559 	}
    560 }
    561 
    562 /*
    563 =================
    564 Mod_LoadTexinfo
    565 =================
    566 */
    567 void Mod_LoadTexinfo (lump_t *l)
    568 {
    569 	texinfo_t *in;
    570 	mtexinfo_t *out;
    571 	int 	i, j, count;
    572 	int		miptex;
    573 	float	len1, len2;
    574 
    575 	in = (void *)(mod_base + l->fileofs);
    576 	if (l->filelen % sizeof(*in))
    577 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    578 	count = l->filelen / sizeof(*in);
    579 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    580 
    581 	loadmodel->texinfo = out;
    582 	loadmodel->numtexinfo = count;
    583 
    584 	for ( i=0 ; i<count ; i++, in++, out++)
    585 	{
    586 #if 0
    587 		for (j=0 ; j<8 ; j++)
    588 			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
    589 		len1 = Length (in->vecs[0]);
    590 		len2 = Length (in->vecs[1]);
    591 #else
    592 		for (j=0 ; j<4 ; j++) {
    593 			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
    594 			out->vecs[1][j] = LittleFloat (in->vecs[1][j]);
    595 		}
    596 		len1 = Length (out->vecs[0]);
    597 		len2 = Length (out->vecs[1]);
    598 #endif
    599 		if (len1 + len2 < 2 /*0.001*/)
    600 			out->mipadjust = 1;
    601 		else
    602 			out->mipadjust = 1 / floor( (len1+len2)/2 );
    603 
    604 		miptex = LittleLong (in->miptex);
    605 		out->flags = LittleLong (in->flags);
    606 
    607 		if (!loadmodel->textures)
    608 		{
    609 			out->texture = &r_notexture_mip;	// checkerboard texture
    610 			out->flags = 0;
    611 		}
    612 		else
    613 		{
    614 			if (miptex >= loadmodel->numtextures)
    615 				SV_Error ("miptex >= loadmodel->numtextures");
    616 			out->texture = loadmodel->textures[miptex];
    617 			if (!out->texture)
    618 			{
    619 				out->texture = &r_notexture_mip; // texture not found
    620 				out->flags = 0;
    621 			}
    622 		}
    623 	}
    624 }
    625 
    626 /*
    627 ================
    628 CalcSurfaceExtents
    629 
    630 Fills in s->texturemins[] and s->extents[]
    631 ================
    632 */
    633 void CalcSurfaceExtents (msurface_t *s)
    634 {
    635 	float	mins[2], maxs[2], val;
    636 	int		i,j, e;
    637 	mvertex_t	*v;
    638 	mtexinfo_t	*tex;
    639 	int		bmins[2], bmaxs[2];
    640 
    641 	mins[0] = mins[1] = 999999;
    642 	maxs[0] = maxs[1] = -99999;
    643 
    644 	tex = s->texinfo;
    645 
    646 	for (i=0 ; i<s->numedges ; i++)
    647 	{
    648 		e = loadmodel->surfedges[s->firstedge+i];
    649 		if (e >= 0)
    650 			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
    651 		else
    652 			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
    653 
    654 		for (j=0 ; j<2 ; j++)
    655 		{
    656 			val = v->position[0] * tex->vecs[j][0] +
    657 				v->position[1] * tex->vecs[j][1] +
    658 				v->position[2] * tex->vecs[j][2] +
    659 				tex->vecs[j][3];
    660 			if (val < mins[j])
    661 				mins[j] = val;
    662 			if (val > maxs[j])
    663 				maxs[j] = val;
    664 		}
    665 	}
    666 
    667 	for (i=0 ; i<2 ; i++)
    668 	{
    669 		bmins[i] = floor(mins[i]/16);
    670 		bmaxs[i] = ceil(maxs[i]/16);
    671 
    672 		s->texturemins[i] = bmins[i] * 16;
    673 		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
    674 		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
    675 			SV_Error ("Bad surface extents");
    676 	}
    677 }
    678 
    679 
    680 /*
    681 =================
    682 Mod_LoadFaces
    683 =================
    684 */
    685 void Mod_LoadFaces (lump_t *l)
    686 {
    687 	dface_t		*in;
    688 	msurface_t 	*out;
    689 	int			i, count, surfnum;
    690 	int			planenum, side;
    691 
    692 	in = (void *)(mod_base + l->fileofs);
    693 	if (l->filelen % sizeof(*in))
    694 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    695 	count = l->filelen / sizeof(*in);
    696 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    697 
    698 	loadmodel->surfaces = out;
    699 	loadmodel->numsurfaces = count;
    700 
    701 	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
    702 	{
    703 		out->firstedge = LittleLong(in->firstedge);
    704 		out->numedges = LittleShort(in->numedges);
    705 		out->flags = 0;
    706 
    707 		planenum = LittleShort(in->planenum);
    708 		side = LittleShort(in->side);
    709 		if (side)
    710 			out->flags |= SURF_PLANEBACK;
    711 
    712 		out->plane = loadmodel->planes + planenum;
    713 
    714 		out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
    715 
    716 		CalcSurfaceExtents (out);
    717 
    718 	// lighting info
    719 
    720 		for (i=0 ; i<MAXLIGHTMAPS ; i++)
    721 			out->styles[i] = in->styles[i];
    722 		i = LittleLong(in->lightofs);
    723 		if (i == -1)
    724 			out->samples = NULL;
    725 		else
    726 			out->samples = loadmodel->lightdata + i;
    727 
    728 	// set the drawing flags flag
    729 
    730 		if (!Q_strncmp(out->texinfo->texture->name,"sky",3))	// sky
    731 		{
    732 			out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
    733 			continue;
    734 		}
    735 
    736 		if (!Q_strncmp(out->texinfo->texture->name,"*",1))		// turbulent
    737 		{
    738 			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
    739 			for (i=0 ; i<2 ; i++)
    740 			{
    741 				out->extents[i] = 16384;
    742 				out->texturemins[i] = -8192;
    743 			}
    744 			continue;
    745 		}
    746 	}
    747 }
    748 
    749 
    750 /*
    751 =================
    752 Mod_SetParent
    753 =================
    754 */
    755 void Mod_SetParent (mnode_t *node, mnode_t *parent)
    756 {
    757 	node->parent = parent;
    758 	if (node->contents < 0)
    759 		return;
    760 	Mod_SetParent (node->children[0], node);
    761 	Mod_SetParent (node->children[1], node);
    762 }
    763 
    764 /*
    765 =================
    766 Mod_LoadNodes
    767 =================
    768 */
    769 void Mod_LoadNodes (lump_t *l)
    770 {
    771 	int			i, j, count, p;
    772 	dnode_t		*in;
    773 	mnode_t 	*out;
    774 
    775 	in = (void *)(mod_base + l->fileofs);
    776 	if (l->filelen % sizeof(*in))
    777 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    778 	count = l->filelen / sizeof(*in);
    779 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    780 
    781 	loadmodel->nodes = out;
    782 	loadmodel->numnodes = count;
    783 
    784 	for ( i=0 ; i<count ; i++, in++, out++)
    785 	{
    786 		for (j=0 ; j<3 ; j++)
    787 		{
    788 			out->minmaxs[j] = LittleShort (in->mins[j]);
    789 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
    790 		}
    791 
    792 		p = LittleLong(in->planenum);
    793 		out->plane = loadmodel->planes + p;
    794 
    795 		out->firstsurface = LittleShort (in->firstface);
    796 		out->numsurfaces = LittleShort (in->numfaces);
    797 
    798 		for (j=0 ; j<2 ; j++)
    799 		{
    800 			p = LittleShort (in->children[j]);
    801 			if (p >= 0)
    802 				out->children[j] = loadmodel->nodes + p;
    803 			else
    804 				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
    805 		}
    806 	}
    807 
    808 	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
    809 }
    810 
    811 /*
    812 =================
    813 Mod_LoadLeafs
    814 =================
    815 */
    816 void Mod_LoadLeafs (lump_t *l)
    817 {
    818 	dleaf_t 	*in;
    819 	mleaf_t 	*out;
    820 	int			i, j, count, p;
    821 
    822 	in = (void *)(mod_base + l->fileofs);
    823 	if (l->filelen % sizeof(*in))
    824 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    825 	count = l->filelen / sizeof(*in);
    826 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    827 
    828 	loadmodel->leafs = out;
    829 	loadmodel->numleafs = count;
    830 
    831 	for ( i=0 ; i<count ; i++, in++, out++)
    832 	{
    833 		for (j=0 ; j<3 ; j++)
    834 		{
    835 			out->minmaxs[j] = LittleShort (in->mins[j]);
    836 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
    837 		}
    838 
    839 		p = LittleLong(in->contents);
    840 		out->contents = p;
    841 
    842 		out->firstmarksurface = loadmodel->marksurfaces +
    843 			LittleShort(in->firstmarksurface);
    844 		out->nummarksurfaces = LittleShort(in->nummarksurfaces);
    845 
    846 		p = LittleLong(in->visofs);
    847 		if (p == -1)
    848 			out->compressed_vis = NULL;
    849 		else
    850 			out->compressed_vis = loadmodel->visdata + p;
    851 		out->efrags = NULL;
    852 
    853 		for (j=0 ; j<4 ; j++)
    854 			out->ambient_sound_level[j] = in->ambient_level[j];
    855 	}
    856 }
    857 
    858 /*
    859 =================
    860 Mod_LoadClipnodes
    861 =================
    862 */
    863 void Mod_LoadClipnodes (lump_t *l)
    864 {
    865 	dclipnode_t *in, *out;
    866 	int			i, count;
    867 	hull_t		*hull;
    868 
    869 	in = (void *)(mod_base + l->fileofs);
    870 	if (l->filelen % sizeof(*in))
    871 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    872 	count = l->filelen / sizeof(*in);
    873 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    874 
    875 	loadmodel->clipnodes = out;
    876 	loadmodel->numclipnodes = count;
    877 
    878 	hull = &loadmodel->hulls[1];
    879 	hull->clipnodes = out;
    880 	hull->firstclipnode = 0;
    881 	hull->lastclipnode = count-1;
    882 	hull->planes = loadmodel->planes;
    883 	hull->clip_mins[0] = -16;
    884 	hull->clip_mins[1] = -16;
    885 	hull->clip_mins[2] = -24;
    886 	hull->clip_maxs[0] = 16;
    887 	hull->clip_maxs[1] = 16;
    888 	hull->clip_maxs[2] = 32;
    889 
    890 	hull = &loadmodel->hulls[2];
    891 	hull->clipnodes = out;
    892 	hull->firstclipnode = 0;
    893 	hull->lastclipnode = count-1;
    894 	hull->planes = loadmodel->planes;
    895 	hull->clip_mins[0] = -32;
    896 	hull->clip_mins[1] = -32;
    897 	hull->clip_mins[2] = -24;
    898 	hull->clip_maxs[0] = 32;
    899 	hull->clip_maxs[1] = 32;
    900 	hull->clip_maxs[2] = 64;
    901 
    902 	for (i=0 ; i<count ; i++, out++, in++)
    903 	{
    904 		out->planenum = LittleLong(in->planenum);
    905 		out->children[0] = LittleShort(in->children[0]);
    906 		out->children[1] = LittleShort(in->children[1]);
    907 	}
    908 }
    909 
    910 /*
    911 =================
    912 Mod_MakeHull0
    913 
    914 Deplicate the drawing hull structure as a clipping hull
    915 =================
    916 */
    917 void Mod_MakeHull0 (void)
    918 {
    919 	mnode_t		*in, *child;
    920 	dclipnode_t *out;
    921 	int			i, j, count;
    922 	hull_t		*hull;
    923 
    924 	hull = &loadmodel->hulls[0];
    925 
    926 	in = loadmodel->nodes;
    927 	count = loadmodel->numnodes;
    928 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    929 
    930 	hull->clipnodes = out;
    931 	hull->firstclipnode = 0;
    932 	hull->lastclipnode = count-1;
    933 	hull->planes = loadmodel->planes;
    934 
    935 	for (i=0 ; i<count ; i++, out++, in++)
    936 	{
    937 		out->planenum = in->plane - loadmodel->planes;
    938 		for (j=0 ; j<2 ; j++)
    939 		{
    940 			child = in->children[j];
    941 			if (child->contents < 0)
    942 				out->children[j] = child->contents;
    943 			else
    944 				out->children[j] = child - loadmodel->nodes;
    945 		}
    946 	}
    947 }
    948 
    949 /*
    950 =================
    951 Mod_LoadMarksurfaces
    952 =================
    953 */
    954 void Mod_LoadMarksurfaces (lump_t *l)
    955 {
    956 	int		i, j, count;
    957 	short		*in;
    958 	msurface_t **out;
    959 
    960 	in = (void *)(mod_base + l->fileofs);
    961 	if (l->filelen % sizeof(*in))
    962 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    963 	count = l->filelen / sizeof(*in);
    964 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    965 
    966 	loadmodel->marksurfaces = out;
    967 	loadmodel->nummarksurfaces = count;
    968 
    969 	for ( i=0 ; i<count ; i++)
    970 	{
    971 		j = LittleShort(in[i]);
    972 		if (j >= loadmodel->numsurfaces)
    973 			SV_Error ("Mod_ParseMarksurfaces: bad surface number");
    974 		out[i] = loadmodel->surfaces + j;
    975 	}
    976 }
    977 
    978 /*
    979 =================
    980 Mod_LoadSurfedges
    981 =================
    982 */
    983 void Mod_LoadSurfedges (lump_t *l)
    984 {
    985 	int		i, count;
    986 	int		*in, *out;
    987 
    988 	in = (void *)(mod_base + l->fileofs);
    989 	if (l->filelen % sizeof(*in))
    990 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
    991 	count = l->filelen / sizeof(*in);
    992 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
    993 
    994 	loadmodel->surfedges = out;
    995 	loadmodel->numsurfedges = count;
    996 
    997 	for ( i=0 ; i<count ; i++)
    998 		out[i] = LittleLong (in[i]);
    999 }
   1000 
   1001 /*
   1002 =================
   1003 Mod_LoadPlanes
   1004 =================
   1005 */
   1006 void Mod_LoadPlanes (lump_t *l)
   1007 {
   1008 	int			i, j;
   1009 	mplane_t	*out;
   1010 	dplane_t 	*in;
   1011 	int			count;
   1012 	int			bits;
   1013 
   1014 	in = (void *)(mod_base + l->fileofs);
   1015 	if (l->filelen % sizeof(*in))
   1016 		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
   1017 	count = l->filelen / sizeof(*in);
   1018 	out = Hunk_AllocName ( count*2*sizeof(*out), loadname);
   1019 
   1020 	loadmodel->planes = out;
   1021 	loadmodel->numplanes = count;
   1022 
   1023 	for ( i=0 ; i<count ; i++, in++, out++)
   1024 	{
   1025 		bits = 0;
   1026 		for (j=0 ; j<3 ; j++)
   1027 		{
   1028 			out->normal[j] = LittleFloat (in->normal[j]);
   1029 			if (out->normal[j] < 0)
   1030 				bits |= 1<<j;
   1031 		}
   1032 
   1033 		out->dist = LittleFloat (in->dist);
   1034 		out->type = LittleLong (in->type);
   1035 		out->signbits = bits;
   1036 	}
   1037 }
   1038 
   1039 
   1040 /*
   1041 =================
   1042 Mod_LoadBrushModel
   1043 =================
   1044 */
   1045 void Mod_LoadBrushModel (model_t *mod, void *buffer)
   1046 {
   1047 	int			i, j;
   1048 	dheader_t	*header;
   1049 	dmodel_t 	*bm;
   1050 
   1051 	loadmodel->type = mod_brush;
   1052 
   1053 	header = (dheader_t *)buffer;
   1054 
   1055 	i = LittleLong (header->version);
   1056 	if (i != BSPVERSION)
   1057 		SV_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
   1058 
   1059 // swap all the lumps
   1060 	mod_base = (byte *)header;
   1061 
   1062 	for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
   1063 		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
   1064 
   1065 // load into heap
   1066 
   1067 	mod->checksum = 0;
   1068 	mod->checksum2 = 0;
   1069 
   1070 	// checksum all of the map, except for entities
   1071 	for (i = 0; i < HEADER_LUMPS; i++) {
   1072 		if (i == LUMP_ENTITIES)
   1073 			continue;
   1074 		mod->checksum ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
   1075 			header->lumps[i].filelen));
   1076 
   1077 		if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
   1078 			continue;
   1079 		mod->checksum2 ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
   1080 			header->lumps[i].filelen));
   1081 	}
   1082 
   1083 	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
   1084 	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
   1085 	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
   1086 	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
   1087 	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
   1088 	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
   1089 	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
   1090 	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
   1091 	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
   1092 	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
   1093 	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
   1094 	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
   1095 	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
   1096 	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
   1097 	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
   1098 
   1099 	Mod_MakeHull0 ();
   1100 
   1101 	mod->numframes = 2;		// regular and alternate animation
   1102 
   1103 //
   1104 // set up the submodels (FIXME: this is confusing)
   1105 //
   1106 	for (i=0 ; i<mod->numsubmodels ; i++)
   1107 	{
   1108 		bm = &mod->submodels[i];
   1109 
   1110 		mod->hulls[0].firstclipnode = bm->headnode[0];
   1111 		for (j=1 ; j<MAX_MAP_HULLS ; j++)
   1112 		{
   1113 			mod->hulls[j].firstclipnode = bm->headnode[j];
   1114 			mod->hulls[j].lastclipnode = mod->numclipnodes-1;
   1115 		}
   1116 
   1117 		mod->firstmodelsurface = bm->firstface;
   1118 		mod->nummodelsurfaces = bm->numfaces;
   1119 
   1120 		VectorCopy (bm->maxs, mod->maxs);
   1121 		VectorCopy (bm->mins, mod->mins);
   1122 
   1123 		mod->numleafs = bm->visleafs;
   1124 
   1125 		if (i < mod->numsubmodels-1)
   1126 		{	// duplicate the basic information
   1127 			char	name[10];
   1128 
   1129 			sprintf (name, "*%i", i+1);
   1130 			loadmodel = Mod_FindName (name);
   1131 			*loadmodel = *mod;
   1132 			strcpy (loadmodel->name, name);
   1133 			mod = loadmodel;
   1134 		}
   1135 	}
   1136 }
   1137 
   1138