• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
Mod_Init(void)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 */
Mod_Extradata(model_t * mod)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 */
Mod_PointInLeaf(vec3_t p,model_t * model)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 */
Mod_DecompressVis(byte * in,model_t * model)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 
Mod_LeafPVS(mleaf_t * leaf,model_t * model)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 */
Mod_ClearAll(void)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 */
Mod_FindName(char * name)184 model_t *Mod_FindName (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 */
Mod_TouchModel(char * name)217 void Mod_TouchModel (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 */
Mod_LoadModel(model_t * mod,qboolean crash)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);
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 */
Mod_ForName(char * name,qboolean crash)313 model_t *Mod_ForName (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 */
Mod_LoadTextures(lump_t * l)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 = 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 = 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 */
Mod_LoadLighting(lump_t * l)495 void Mod_LoadLighting (lump_t *l)
496 {
497 	if (!l->filelen)
498 	{
499 		loadmodel->lightdata = NULL;
500 		return;
501 	}
502 	loadmodel->lightdata = 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 */
Mod_LoadVisibility(lump_t * l)512 void Mod_LoadVisibility (lump_t *l)
513 {
514 	if (!l->filelen)
515 	{
516 		loadmodel->visdata = NULL;
517 		return;
518 	}
519 	loadmodel->visdata = 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 */
Mod_LoadEntities(lump_t * l)529 void Mod_LoadEntities (lump_t *l)
530 {
531 	if (!l->filelen)
532 	{
533 		loadmodel->entities = NULL;
534 		return;
535 	}
536 	loadmodel->entities = 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 */
Mod_LoadVertexes(lump_t * l)546 void Mod_LoadVertexes (lump_t *l)
547 {
548 	dvertex_t	*in;
549 	mvertex_t	*out;
550 	int			i, count;
551 
552 	in = (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 = 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 */
Mod_LoadSubmodels(lump_t * l)574 void Mod_LoadSubmodels (lump_t *l)
575 {
576 	dmodel_t	*in;
577 	dmodel_t	*out;
578 	int			i, j, count;
579 
580 	in = (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 = 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 */
Mod_LoadEdges(lump_t * l)610 void Mod_LoadEdges (lump_t *l)
611 {
612 	dedge_t *in;
613 	medge_t *out;
614 	int 	i, count;
615 
616 	in = (void *)(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 = 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 */
Mod_LoadTexinfo(lump_t * l)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 = (void *)(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 = 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 */
CalcSurfaceExtents(msurface_t * s)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] = floor(mins[i]/16);
742 		bmaxs[i] = ceil(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 */
Mod_LoadFaces(lump_t * l)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 = (void *)(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 = 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 */
Mod_SetParent(mnode_t * node,mnode_t * parent)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 */
Mod_LoadNodes(lump_t * l)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 = (void *)(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 = 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 */
Mod_LoadLeafs(lump_t * l)893 void Mod_LoadLeafs (lump_t *l)
894 {
895 	dleaf_t 	*in;
896 	mleaf_t 	*out;
897 	int			i, j, count, p;
898 	char s[80];
899 	qboolean isnotmap = true;
900 
901 	in = (void *)(mod_base + l->fileofs);
902 	if (l->filelen % sizeof(*in))
903 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
904 	count = l->filelen / sizeof(*in);
905 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
906 
907 	loadmodel->leafs = out;
908 	loadmodel->numleafs = count;
909 	sprintf(s, "maps/%s.bsp", Info_ValueForKey(cl.serverinfo,"map"));
910 	if (!strcmp(s, loadmodel->name))
911 		isnotmap = false;
912 	for ( i=0 ; i<count ; i++, in++, out++)
913 	{
914 		for (j=0 ; j<3 ; j++)
915 		{
916 			out->minmaxs[j] = LittleShort (in->mins[j]);
917 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
918 		}
919 
920 		p = LittleLong(in->contents);
921 		out->contents = p;
922 
923 		out->firstmarksurface = loadmodel->marksurfaces +
924 			LittleShort(in->firstmarksurface);
925 		out->nummarksurfaces = LittleShort(in->nummarksurfaces);
926 
927 		p = LittleLong(in->visofs);
928 		if (p == -1)
929 			out->compressed_vis = NULL;
930 		else
931 			out->compressed_vis = loadmodel->visdata + p;
932 		out->efrags = NULL;
933 
934 		for (j=0 ; j<4 ; j++)
935 			out->ambient_sound_level[j] = in->ambient_level[j];
936 
937 		// gl underwater warp
938 		if (out->contents != CONTENTS_EMPTY)
939 		{
940 			for (j=0 ; j<out->nummarksurfaces ; j++)
941 				out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
942 		}
943 		if (isnotmap)
944 		{
945 			for (j=0 ; j<out->nummarksurfaces ; j++)
946 				out->firstmarksurface[j]->flags |= SURF_DONTWARP;
947 		}
948 	}
949 }
950 
951 /*
952 =================
953 Mod_LoadClipnodes
954 =================
955 */
Mod_LoadClipnodes(lump_t * l)956 void Mod_LoadClipnodes (lump_t *l)
957 {
958 	dclipnode_t *in, *out;
959 	int			i, count;
960 	hull_t		*hull;
961 
962 	in = (void *)(mod_base + l->fileofs);
963 	if (l->filelen % sizeof(*in))
964 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
965 	count = l->filelen / sizeof(*in);
966 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
967 
968 	loadmodel->clipnodes = out;
969 	loadmodel->numclipnodes = count;
970 
971 	hull = &loadmodel->hulls[1];
972 	hull->clipnodes = out;
973 	hull->firstclipnode = 0;
974 	hull->lastclipnode = count-1;
975 	hull->planes = loadmodel->planes;
976 	hull->clip_mins[0] = -16;
977 	hull->clip_mins[1] = -16;
978 	hull->clip_mins[2] = -24;
979 	hull->clip_maxs[0] = 16;
980 	hull->clip_maxs[1] = 16;
981 	hull->clip_maxs[2] = 32;
982 
983 	hull = &loadmodel->hulls[2];
984 	hull->clipnodes = out;
985 	hull->firstclipnode = 0;
986 	hull->lastclipnode = count-1;
987 	hull->planes = loadmodel->planes;
988 	hull->clip_mins[0] = -32;
989 	hull->clip_mins[1] = -32;
990 	hull->clip_mins[2] = -24;
991 	hull->clip_maxs[0] = 32;
992 	hull->clip_maxs[1] = 32;
993 	hull->clip_maxs[2] = 64;
994 
995 	for (i=0 ; i<count ; i++, out++, in++)
996 	{
997 		out->planenum = LittleLong(in->planenum);
998 		out->children[0] = LittleShort(in->children[0]);
999 		out->children[1] = LittleShort(in->children[1]);
1000 	}
1001 }
1002 
1003 /*
1004 =================
1005 Mod_MakeHull0
1006 
1007 Deplicate the drawing hull structure as a clipping hull
1008 =================
1009 */
Mod_MakeHull0(void)1010 void Mod_MakeHull0 (void)
1011 {
1012 	mnode_t		*in, *child;
1013 	dclipnode_t *out;
1014 	int			i, j, count;
1015 	hull_t		*hull;
1016 
1017 	hull = &loadmodel->hulls[0];
1018 
1019 	in = loadmodel->nodes;
1020 	count = loadmodel->numnodes;
1021 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1022 
1023 	hull->clipnodes = out;
1024 	hull->firstclipnode = 0;
1025 	hull->lastclipnode = count-1;
1026 	hull->planes = loadmodel->planes;
1027 
1028 	for (i=0 ; i<count ; i++, out++, in++)
1029 	{
1030 		out->planenum = in->plane - loadmodel->planes;
1031 		for (j=0 ; j<2 ; j++)
1032 		{
1033 			child = in->children[j];
1034 			if (child->contents < 0)
1035 				out->children[j] = child->contents;
1036 			else
1037 				out->children[j] = child - loadmodel->nodes;
1038 		}
1039 	}
1040 }
1041 
1042 /*
1043 =================
1044 Mod_LoadMarksurfaces
1045 =================
1046 */
Mod_LoadMarksurfaces(lump_t * l)1047 void Mod_LoadMarksurfaces (lump_t *l)
1048 {
1049 	int		i, j, count;
1050 	short		*in;
1051 	msurface_t **out;
1052 
1053 	in = (void *)(mod_base + l->fileofs);
1054 	if (l->filelen % sizeof(*in))
1055 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1056 	count = l->filelen / sizeof(*in);
1057 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1058 
1059 	loadmodel->marksurfaces = out;
1060 	loadmodel->nummarksurfaces = count;
1061 
1062 	for ( i=0 ; i<count ; i++)
1063 	{
1064 		j = LittleShort(in[i]);
1065 		if (j >= loadmodel->numsurfaces)
1066 			Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
1067 		out[i] = loadmodel->surfaces + j;
1068 	}
1069 }
1070 
1071 /*
1072 =================
1073 Mod_LoadSurfedges
1074 =================
1075 */
Mod_LoadSurfedges(lump_t * l)1076 void Mod_LoadSurfedges (lump_t *l)
1077 {
1078 	int		i, count;
1079 	int		*in, *out;
1080 
1081 	in = (void *)(mod_base + l->fileofs);
1082 	if (l->filelen % sizeof(*in))
1083 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1084 	count = l->filelen / sizeof(*in);
1085 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1086 
1087 	loadmodel->surfedges = out;
1088 	loadmodel->numsurfedges = count;
1089 
1090 	for ( i=0 ; i<count ; i++)
1091 		out[i] = LittleLong (in[i]);
1092 }
1093 
1094 
1095 /*
1096 =================
1097 Mod_LoadPlanes
1098 =================
1099 */
Mod_LoadPlanes(lump_t * l)1100 void Mod_LoadPlanes (lump_t *l)
1101 {
1102 	int			i, j;
1103 	mplane_t	*out;
1104 	dplane_t 	*in;
1105 	int			count;
1106 	int			bits;
1107 
1108 	in = (void *)(mod_base + l->fileofs);
1109 	if (l->filelen % sizeof(*in))
1110 		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1111 	count = l->filelen / sizeof(*in);
1112 	out = Hunk_AllocName ( count*2*sizeof(*out), loadname);
1113 
1114 	loadmodel->planes = out;
1115 	loadmodel->numplanes = count;
1116 
1117 	for ( i=0 ; i<count ; i++, in++, out++)
1118 	{
1119 		bits = 0;
1120 		for (j=0 ; j<3 ; j++)
1121 		{
1122 			out->normal[j] = LittleFloat (in->normal[j]);
1123 			if (out->normal[j] < 0)
1124 				bits |= 1<<j;
1125 		}
1126 
1127 		out->dist = LittleFloat (in->dist);
1128 		out->type = LittleLong (in->type);
1129 		out->signbits = bits;
1130 	}
1131 }
1132 
1133 /*
1134 =================
1135 RadiusFromBounds
1136 =================
1137 */
RadiusFromBounds(vec3_t mins,vec3_t maxs)1138 float RadiusFromBounds (vec3_t mins, vec3_t maxs)
1139 {
1140 	int		i;
1141 	vec3_t	corner;
1142 
1143 	for (i=0 ; i<3 ; i++)
1144 	{
1145 		corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
1146 	}
1147 
1148 	return Length (corner);
1149 }
1150 
1151 /*
1152 =================
1153 Mod_LoadBrushModel
1154 =================
1155 */
Mod_LoadBrushModel(model_t * mod,void * buffer)1156 void Mod_LoadBrushModel (model_t *mod, void *buffer)
1157 {
1158 	int			i, j;
1159 	dheader_t	*header;
1160 	dmodel_t 	*bm;
1161 
1162 	loadmodel->type = mod_brush;
1163 
1164 	header = (dheader_t *)buffer;
1165 
1166 	i = LittleLong (header->version);
1167 	if (i != BSPVERSION)
1168 		Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
1169 
1170 // swap all the lumps
1171 	mod_base = (byte *)header;
1172 
1173 	for (i=0 ; i< (int) sizeof(dheader_t)/4 ; i++)
1174 		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
1175 
1176 // checksum all of the map, except for entities
1177 	mod->checksum = 0;
1178 	mod->checksum2 = 0;
1179 
1180 	for (i = 0; i < HEADER_LUMPS; i++) {
1181 		if (i == LUMP_ENTITIES)
1182 			continue;
1183 		mod->checksum ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
1184 			header->lumps[i].filelen);
1185 
1186 		if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
1187 			continue;
1188 		mod->checksum2 ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
1189 			header->lumps[i].filelen);
1190 	}
1191 
1192 
1193 // load into heap
1194 
1195 	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
1196 	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
1197 	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
1198 	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
1199 	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
1200 	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
1201 	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
1202 	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
1203 	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
1204 	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
1205 	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
1206 	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
1207 	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
1208 	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
1209 	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
1210 
1211 	Mod_MakeHull0 ();
1212 
1213 	mod->numframes = 2;		// regular and alternate animation
1214 
1215 //
1216 // set up the submodels (FIXME: this is confusing)
1217 //
1218 	for (i=0 ; i<mod->numsubmodels ; i++)
1219 	{
1220 		bm = &mod->submodels[i];
1221 
1222 		mod->hulls[0].firstclipnode = bm->headnode[0];
1223 		for (j=1 ; j<MAX_MAP_HULLS ; j++)
1224 		{
1225 			mod->hulls[j].firstclipnode = bm->headnode[j];
1226 			mod->hulls[j].lastclipnode = mod->numclipnodes-1;
1227 		}
1228 
1229 		mod->firstmodelsurface = bm->firstface;
1230 		mod->nummodelsurfaces = bm->numfaces;
1231 
1232 		VectorCopy (bm->maxs, mod->maxs);
1233 		VectorCopy (bm->mins, mod->mins);
1234 
1235 		mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
1236 
1237 		mod->numleafs = bm->visleafs;
1238 
1239 		if (i < mod->numsubmodels-1)
1240 		{	// duplicate the basic information
1241 			char	name[10];
1242 
1243 			sprintf (name, "*%i", i+1);
1244 			loadmodel = Mod_FindName (name);
1245 			*loadmodel = *mod;
1246 			strcpy (loadmodel->name, name);
1247 			mod = loadmodel;
1248 		}
1249 	}
1250 }
1251 
1252 /*
1253 ==============================================================================
1254 
1255 ALIAS MODELS
1256 
1257 ==============================================================================
1258 */
1259 
1260 aliashdr_t	*pheader;
1261 
1262 stvert_t	stverts[MAXALIASVERTS];
1263 mtriangle_t	triangles[MAXALIASTRIS];
1264 
1265 // a pose is a single set of vertexes.  a frame may be
1266 // an animating sequence of poses
1267 trivertx_t	*poseverts[MAXALIASFRAMES];
1268 int			posenum;
1269 
1270 byte		player_8bit_texels[320*200];
1271 
1272 /*
1273 =================
1274 Mod_LoadAliasFrame
1275 =================
1276 */
Mod_LoadAliasFrame(void * pin,maliasframedesc_t * frame)1277 void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
1278 {
1279 	trivertx_t		*pinframe;
1280 	int				i;
1281 	daliasframe_t	*pdaliasframe;
1282 
1283 	pdaliasframe = (daliasframe_t *)pin;
1284 
1285 	strcpy (frame->name, pdaliasframe->name);
1286 	frame->firstpose = posenum;
1287 	frame->numposes = 1;
1288 
1289 	for (i=0 ; i<3 ; i++)
1290 	{
1291 	// these are byte values, so we don't have to worry about
1292 	// endianness
1293 		frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
1294 		frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
1295 	}
1296 
1297 	pinframe = (trivertx_t *)(pdaliasframe + 1);
1298 
1299 	poseverts[posenum] = pinframe;
1300 	posenum++;
1301 
1302 	pinframe += pheader->numverts;
1303 
1304 	return (void *)pinframe;
1305 }
1306 
1307 
1308 /*
1309 =================
1310 Mod_LoadAliasGroup
1311 =================
1312 */
Mod_LoadAliasGroup(void * pin,maliasframedesc_t * frame)1313 void *Mod_LoadAliasGroup (void * pin,  maliasframedesc_t *frame)
1314 {
1315 	daliasgroup_t		*pingroup;
1316 	int					i, numframes;
1317 	daliasinterval_t	*pin_intervals;
1318 	void				*ptemp;
1319 
1320 	pingroup = (daliasgroup_t *)pin;
1321 
1322 	numframes = LittleLong (pingroup->numframes);
1323 
1324 	frame->firstpose = posenum;
1325 	frame->numposes = numframes;
1326 
1327 	for (i=0 ; i<3 ; i++)
1328 	{
1329 	// these are byte values, so we don't have to worry about endianness
1330 		frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
1331 		frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
1332 	}
1333 
1334 	pin_intervals = (daliasinterval_t *)(pingroup + 1);
1335 
1336 	frame->interval = LittleFloat (pin_intervals->interval);
1337 
1338 	pin_intervals += numframes;
1339 
1340 	ptemp = (void *)pin_intervals;
1341 
1342 	for (i=0 ; i<numframes ; i++)
1343 	{
1344 		poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
1345 		posenum++;
1346 
1347 		ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
1348 	}
1349 
1350 	return ptemp;
1351 }
1352 
1353 //=========================================================
1354 
1355 /*
1356 =================
1357 Mod_FloodFillSkin
1358 
1359 Fill background pixels so mipmapping doesn't have haloes - Ed
1360 =================
1361 */
1362 
1363 typedef struct
1364 {
1365 	short		x, y;
1366 } floodfill_t;
1367 
1368 extern unsigned d_8to24table[];
1369 
1370 // must be a power of 2
1371 #define FLOODFILL_FIFO_SIZE 0x1000
1372 #define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
1373 
1374 #define FLOODFILL_STEP( off, dx, dy ) \
1375 { \
1376 	if (pos[off] == fillcolor) \
1377 	{ \
1378 		pos[off] = 255; \
1379 		fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
1380 		inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
1381 	} \
1382 	else if (pos[off] != 255) fdc = pos[off]; \
1383 }
1384 
Mod_FloodFillSkin(byte * skin,int skinwidth,int skinheight)1385 void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
1386 {
1387 	byte				fillcolor = *skin; // assume this is the pixel to fill
1388 	floodfill_t			fifo[FLOODFILL_FIFO_SIZE];
1389 	int					inpt = 0, outpt = 0;
1390 	int					filledcolor = -1;
1391 	int					i;
1392 
1393 	if (filledcolor == -1)
1394 	{
1395 		filledcolor = 0;
1396 		// attempt to find opaque black
1397 		for (i = 0; i < 256; ++i)
1398 			if (d_8to24table[i] == (255 << 0)) // alpha 1.0
1399 			{
1400 				filledcolor = i;
1401 				break;
1402 			}
1403 	}
1404 
1405 	// can't fill to filled color or to transparent color (used as visited marker)
1406 	if ((fillcolor == filledcolor) || (fillcolor == 255))
1407 	{
1408 		//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
1409 		return;
1410 	}
1411 
1412 	fifo[inpt].x = 0, fifo[inpt].y = 0;
1413 	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
1414 
1415 	while (outpt != inpt)
1416 	{
1417 		int			x = fifo[outpt].x, y = fifo[outpt].y;
1418 		int			fdc = filledcolor;
1419 		byte		*pos = &skin[x + skinwidth * y];
1420 
1421 		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
1422 
1423 		if (x > 0)				FLOODFILL_STEP( -1, -1, 0 );
1424 		if (x < skinwidth - 1)	FLOODFILL_STEP( 1, 1, 0 );
1425 		if (y > 0)				FLOODFILL_STEP( -skinwidth, 0, -1 );
1426 		if (y < skinheight - 1)	FLOODFILL_STEP( skinwidth, 0, 1 );
1427 		skin[x + skinwidth * y] = fdc;
1428 	}
1429 }
1430 
1431 /*
1432 ===============
1433 Mod_LoadAllSkins
1434 ===============
1435 */
Mod_LoadAllSkins(int numskins,daliasskintype_t * pskintype)1436 void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
1437 {
1438 	int		i, j, k;
1439 	char	name[32];
1440 	int		s;
1441 	byte	*skin;
1442 	daliasskingroup_t		*pinskingroup;
1443 	int		groupskins;
1444 	daliasskininterval_t	*pinskinintervals;
1445 
1446 	skin = (byte *)(pskintype + 1);
1447 
1448 	if (numskins < 1 || numskins > MAX_SKINS)
1449 		Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
1450 
1451 	s = pheader->skinwidth * pheader->skinheight;
1452 
1453 	for (i=0 ; i<numskins ; i++)
1454 	{
1455 		if (pskintype->type == ALIAS_SKIN_SINGLE) {
1456 			Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
1457 
1458 			// save 8 bit texels for the player model to remap
1459 			// save 8 bit texels for the player model to remap
1460 			if (!strcmp(loadmodel->name,"progs/player.mdl"))
1461 			{
1462 				if (s > (int) sizeof(player_8bit_texels))
1463 					Sys_Error ("Player skin too large");
1464 				memcpy (player_8bit_texels, (byte *)(pskintype + 1), s);
1465 			}
1466 			sprintf (name, "%s_%i", loadmodel->name, i);
1467 			pheader->gl_texturenum[i][0] =
1468 			pheader->gl_texturenum[i][1] =
1469 			pheader->gl_texturenum[i][2] =
1470 			pheader->gl_texturenum[i][3] =
1471 				GL_LoadTexture (name, pheader->skinwidth,
1472 				pheader->skinheight, (byte *)(pskintype + 1), true, false);
1473 			pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
1474 		} else {
1475 			// animating skin group.  yuck.
1476 			pskintype++;
1477 			pinskingroup = (daliasskingroup_t *)pskintype;
1478 			groupskins = LittleLong (pinskingroup->numskins);
1479 			pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
1480 
1481 			pskintype = (void *)(pinskinintervals + groupskins);
1482 
1483 			for (j=0 ; j<groupskins ; j++)
1484 			{
1485 					Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
1486 					sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
1487 					pheader->gl_texturenum[i][j&3] =
1488 						GL_LoadTexture (name, pheader->skinwidth,
1489 						pheader->skinheight, (byte *)(pskintype), true, false);
1490 					pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
1491 			}
1492 			k = j;
1493 			for (/* */; j < 4; j++)
1494 				pheader->gl_texturenum[i][j&3] =
1495 				pheader->gl_texturenum[i][j - k];
1496 		}
1497 	}
1498 
1499 	return (void *)pskintype;
1500 }
1501 
1502 
1503 //=========================================================================
1504 
1505 /*
1506 =================
1507 Mod_LoadAliasModel
1508 =================
1509 */
Mod_LoadAliasModel(model_t * mod,void * buffer)1510 void Mod_LoadAliasModel (model_t *mod, void *buffer)
1511 {
1512 	int					i, j;
1513 	mdl_t				*pinmodel;
1514 	stvert_t			*pinstverts;
1515 	dtriangle_t			*pintriangles;
1516 	int					version, numframes;
1517 	int					size;
1518 	daliasframetype_t	*pframetype;
1519 	daliasskintype_t	*pskintype;
1520 	int					start, end, total;
1521 
1522 	if (!strcmp(loadmodel->name, "progs/player.mdl") ||
1523 		!strcmp(loadmodel->name, "progs/eyes.mdl")) {
1524 		unsigned short crc;
1525 		byte *p;
1526 		int len;
1527 		char st[40];
1528 
1529 		CRC_Init(&crc);
1530 		for (len = com_filesize, p = buffer; len; len--, p++)
1531 			CRC_ProcessByte(&crc, *p);
1532 
1533 		sprintf(st, "%d", (int) crc);
1534 		Info_SetValueForKey (cls.userinfo,
1535 			!strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name,
1536 			st, MAX_INFO_STRING);
1537 
1538 		if (cls.state >= ca_connected) {
1539 			MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
1540 			sprintf(st, "setinfo %s %d",
1541 				!strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name,
1542 				(int)crc);
1543 			SZ_Print (&cls.netchan.message, st);
1544 		}
1545 	}
1546 
1547 	start = Hunk_LowMark ();
1548 
1549 	pinmodel = (mdl_t *)buffer;
1550 
1551 	version = LittleLong (pinmodel->version);
1552 	if (version != ALIAS_VERSION)
1553 		Sys_Error ("%s has wrong version number (%i should be %i)",
1554 				 mod->name, version, ALIAS_VERSION);
1555 
1556 //
1557 // allocate space for a working header, plus all the data except the frames,
1558 // skin and group info
1559 //
1560 	size = 	sizeof (aliashdr_t)
1561 			+ (LittleLong (pinmodel->numframes) - 1) *
1562 			sizeof (pheader->frames[0]);
1563 	pheader = Hunk_AllocName (size, loadname);
1564 
1565 	mod->flags = LittleLong (pinmodel->flags);
1566 
1567 //
1568 // endian-adjust and copy the data, starting with the alias model header
1569 //
1570 	pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
1571 	pheader->numskins = LittleLong (pinmodel->numskins);
1572 	pheader->skinwidth = LittleLong (pinmodel->skinwidth);
1573 	pheader->skinheight = LittleLong (pinmodel->skinheight);
1574 
1575 	if (pheader->skinheight > MAX_LBM_HEIGHT)
1576 		Sys_Error ("model %s has a skin taller than %d", mod->name,
1577 				   MAX_LBM_HEIGHT);
1578 
1579 	pheader->numverts = LittleLong (pinmodel->numverts);
1580 
1581 	if (pheader->numverts <= 0)
1582 		Sys_Error ("model %s has no vertices", mod->name);
1583 
1584 	if (pheader->numverts > MAXALIASVERTS)
1585 		Sys_Error ("model %s has too many vertices", mod->name);
1586 
1587 	pheader->numtris = LittleLong (pinmodel->numtris);
1588 
1589 	if (pheader->numtris <= 0)
1590 		Sys_Error ("model %s has no triangles", mod->name);
1591 
1592 	pheader->numframes = LittleLong (pinmodel->numframes);
1593 	numframes = pheader->numframes;
1594 	if (numframes < 1)
1595 		Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
1596 
1597 	pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
1598 	mod->synctype = LittleLong (pinmodel->synctype);
1599 	mod->numframes = pheader->numframes;
1600 
1601 	for (i=0 ; i<3 ; i++)
1602 	{
1603 		pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
1604 		pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
1605 		pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
1606 	}
1607 
1608 
1609 //
1610 // load the skins
1611 //
1612 	pskintype = (daliasskintype_t *)&pinmodel[1];
1613 	pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype);
1614 
1615 //
1616 // load base s and t vertices
1617 //
1618 	pinstverts = (stvert_t *)pskintype;
1619 
1620 	for (i=0 ; i<pheader->numverts ; i++)
1621 	{
1622 		stverts[i].onseam = LittleLong (pinstverts[i].onseam);
1623 		stverts[i].s = LittleLong (pinstverts[i].s);
1624 		stverts[i].t = LittleLong (pinstverts[i].t);
1625 	}
1626 
1627 //
1628 // load triangle lists
1629 //
1630 	pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
1631 
1632 	for (i=0 ; i<pheader->numtris ; i++)
1633 	{
1634 		triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
1635 
1636 		for (j=0 ; j<3 ; j++)
1637 		{
1638 			triangles[i].vertindex[j] =
1639 					LittleLong (pintriangles[i].vertindex[j]);
1640 		}
1641 	}
1642 
1643 //
1644 // load the frames
1645 //
1646 	posenum = 0;
1647 	pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
1648 
1649 	for (i=0 ; i<numframes ; i++)
1650 	{
1651 		aliasframetype_t	frametype;
1652 
1653 		frametype = LittleLong (pframetype->type);
1654 
1655 		if (frametype == ALIAS_SINGLE)
1656 		{
1657 			pframetype = (daliasframetype_t *)
1658 					Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
1659 		}
1660 		else
1661 		{
1662 			pframetype = (daliasframetype_t *)
1663 					Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
1664 		}
1665 	}
1666 
1667 	pheader->numposes = posenum;
1668 
1669 	mod->type = mod_alias;
1670 
1671 // FIXME: do this right
1672 	mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
1673 	mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
1674 
1675 	//
1676 	// build the draw lists
1677 	//
1678 	GL_MakeAliasModelDisplayLists (mod, pheader);
1679 
1680 //
1681 // move the complete, relocatable alias model to the cache
1682 //
1683 	end = Hunk_LowMark ();
1684 	total = end - start;
1685 
1686 	Cache_Alloc (&mod->cache, total, loadname);
1687 	if (!mod->cache.data)
1688 		return;
1689 	memcpy (mod->cache.data, pheader, total);
1690 
1691 	Hunk_FreeToLowMark (start);
1692 }
1693 
1694 //=============================================================================
1695 
1696 /*
1697 =================
1698 Mod_LoadSpriteFrame
1699 =================
1700 */
Mod_LoadSpriteFrame(void * pin,mspriteframe_t ** ppframe,int framenum)1701 void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
1702 {
1703 	dspriteframe_t		*pinframe;
1704 	mspriteframe_t		*pspriteframe;
1705 	int					width, height, size, origin[2];
1706 	char				name[64];
1707 
1708 	pinframe = (dspriteframe_t *)pin;
1709 
1710 	width = LittleLong (pinframe->width);
1711 	height = LittleLong (pinframe->height);
1712 	size = width * height;
1713 
1714 	pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);
1715 
1716 	Q_memset (pspriteframe, 0, sizeof (mspriteframe_t));
1717 
1718 	*ppframe = pspriteframe;
1719 
1720 	pspriteframe->width = width;
1721 	pspriteframe->height = height;
1722 	origin[0] = LittleLong (pinframe->origin[0]);
1723 	origin[1] = LittleLong (pinframe->origin[1]);
1724 
1725 	pspriteframe->up = origin[1];
1726 	pspriteframe->down = origin[1] - height;
1727 	pspriteframe->left = origin[0];
1728 	pspriteframe->right = width + origin[0];
1729 
1730 	sprintf (name, "%s_%i", loadmodel->name, framenum);
1731 	pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true);
1732 
1733 	return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
1734 }
1735 
1736 
1737 /*
1738 =================
1739 Mod_LoadSpriteGroup
1740 =================
1741 */
Mod_LoadSpriteGroup(void * pin,mspriteframe_t ** ppframe,int framenum)1742 void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum)
1743 {
1744 	dspritegroup_t		*pingroup;
1745 	mspritegroup_t		*pspritegroup;
1746 	int					i, numframes;
1747 	dspriteinterval_t	*pin_intervals;
1748 	float				*poutintervals;
1749 	void				*ptemp;
1750 
1751 	pingroup = (dspritegroup_t *)pin;
1752 
1753 	numframes = LittleLong (pingroup->numframes);
1754 
1755 	pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
1756 				(numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
1757 
1758 	pspritegroup->numframes = numframes;
1759 
1760 	*ppframe = (mspriteframe_t *)pspritegroup;
1761 
1762 	pin_intervals = (dspriteinterval_t *)(pingroup + 1);
1763 
1764 	poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
1765 
1766 	pspritegroup->intervals = poutintervals;
1767 
1768 	for (i=0 ; i<numframes ; i++)
1769 	{
1770 		*poutintervals = LittleFloat (pin_intervals->interval);
1771 		if (*poutintervals <= 0.0)
1772 			Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
1773 
1774 		poutintervals++;
1775 		pin_intervals++;
1776 	}
1777 
1778 	ptemp = (void *)pin_intervals;
1779 
1780 	for (i=0 ; i<numframes ; i++)
1781 	{
1782 		ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i);
1783 	}
1784 
1785 	return ptemp;
1786 }
1787 
1788 
1789 /*
1790 =================
1791 Mod_LoadSpriteModel
1792 =================
1793 */
Mod_LoadSpriteModel(model_t * mod,void * buffer)1794 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
1795 {
1796 	int					i;
1797 	int					version;
1798 	dsprite_t			*pin;
1799 	msprite_t			*psprite;
1800 	int					numframes;
1801 	int					size;
1802 	dspriteframetype_t	*pframetype;
1803 
1804 	pin = (dsprite_t *)buffer;
1805 
1806 	version = LittleLong (pin->version);
1807 	if (version != SPRITE_VERSION)
1808 		Sys_Error ("%s has wrong version number "
1809 				 "(%i should be %i)", mod->name, version, SPRITE_VERSION);
1810 
1811 	numframes = LittleLong (pin->numframes);
1812 
1813 	size = sizeof (msprite_t) +	(numframes - 1) * sizeof (psprite->frames);
1814 
1815 	psprite = Hunk_AllocName (size, loadname);
1816 
1817 	mod->cache.data = psprite;
1818 
1819 	psprite->type = LittleLong (pin->type);
1820 	psprite->maxwidth = LittleLong (pin->width);
1821 	psprite->maxheight = LittleLong (pin->height);
1822 	psprite->beamlength = LittleFloat (pin->beamlength);
1823 	mod->synctype = LittleLong (pin->synctype);
1824 	psprite->numframes = numframes;
1825 
1826 	mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
1827 	mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
1828 	mod->mins[2] = -psprite->maxheight/2;
1829 	mod->maxs[2] = psprite->maxheight/2;
1830 
1831 //
1832 // load the frames
1833 //
1834 	if (numframes < 1)
1835 		Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
1836 
1837 	mod->numframes = numframes;
1838 
1839 	pframetype = (dspriteframetype_t *)(pin + 1);
1840 
1841 	for (i=0 ; i<numframes ; i++)
1842 	{
1843 		spriteframetype_t	frametype;
1844 
1845 		frametype = LittleLong (pframetype->type);
1846 		psprite->frames[i].type = frametype;
1847 
1848 		if (frametype == SPR_SINGLE)
1849 		{
1850 			pframetype = (dspriteframetype_t *)
1851 					Mod_LoadSpriteFrame (pframetype + 1,
1852 										 &psprite->frames[i].frameptr, i);
1853 		}
1854 		else
1855 		{
1856 			pframetype = (dspriteframetype_t *)
1857 					Mod_LoadSpriteGroup (pframetype + 1,
1858 										 &psprite->frames[i].frameptr, i);
1859 		}
1860 	}
1861 
1862 	mod->type = mod_sprite;
1863 }
1864 
1865 //=============================================================================
1866 
1867 /*
1868 ================
1869 Mod_Print
1870 ================
1871 */
Mod_Print(void)1872 void Mod_Print (void)
1873 {
1874 	int		i;
1875 	model_t	*mod;
1876 
1877 	Con_Printf ("Cached models:\n");
1878 	for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
1879 	{
1880 		Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
1881 	}
1882 }
1883 
1884 
1885