• 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(const char * name)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 */
Mod_TouchModel(const char * name)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 */
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, 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 */
Mod_ForName(const char * name,qboolean crash)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 */
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 = (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 */
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 = (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 */
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 = (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 */
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 = (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 */
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 = (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 */
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 = (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 */
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 = (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 */
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 = (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 */
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] = (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 */
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 = (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 */
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 = (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 */
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 
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 */
Mod_LoadClipnodes(lump_t * l)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 */
Mod_MakeHull0(void)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 */
Mod_LoadMarksurfaces(lump_t * l)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 */
Mod_LoadSurfedges(lump_t * l)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 */
Mod_LoadPlanes(lump_t * l)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 */
RadiusFromBounds(vec3_t mins,vec3_t maxs)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 */
Mod_LoadBrushModel(model_t * mod,void * buffer)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 */
Mod_LoadAliasFrame(void * pin,maliasframedesc_t * frame)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 */
Mod_LoadAliasGroup(void * pin,maliasframedesc_t * frame)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 
Mod_FloodFillSkin(byte * skin,int skinwidth,int skinheight)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 */
Mod_LoadAllSkins(int numskins,daliasskintype_t * pskintype)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 */
Mod_LoadAliasModel(model_t * mod,void * buffer)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 */
Mod_LoadSpriteFrame(void * pin,mspriteframe_t ** ppframe,int framenum)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 */
Mod_LoadSpriteGroup(void * pin,mspriteframe_t ** ppframe,int framenum)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 */
Mod_LoadSpriteModel(model_t * mod,void * buffer)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 */
Mod_Print(void)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