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 #include "neh.h"
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	2048 //512
38 model_t	mod_known[MAX_MOD_KNOWN];
39 int		mod_numknown;
40 
41 cvar_t gl_subdivide_size = {"gl_subdivide_size", "512", true}; //256
42 cvar_t gl_autobright = {"gl_autobright", "1"};
43 
44 /*
45 ===============
46 Mod_Init
47 ===============
48 */
Mod_Init(void)49 void Mod_Init (void)
50 {
51 	Cvar_RegisterVariable (&gl_subdivide_size);
52 	Cvar_RegisterVariable (&gl_autobright);
53 	memset (mod_novis, 0xff, sizeof(mod_novis));
54 }
55 
56 /*
57 ===============
58 Mod_Extradata
59 
60 Caches the data if needed
61 ===============
62 */
Mod_Extradata(model_t * mod)63 void *Mod_Extradata (model_t *mod)
64 {
65 	void	*r;
66 
67 	r = Cache_Check (&mod->cache);
68 	if (r)
69 		return r;
70 
71 	Mod_LoadModel (mod, true);
72 
73 	if (!mod->cache.data)
74 		Sys_Error ("Mod_Extradata: caching failed, model %s", mod->name);
75 	return mod->cache.data;
76 }
77 
78 /*
79 ===============
80 Mod_PointInLeaf
81 ===============
82 */
Mod_PointInLeaf(vec3_t p,model_t * model)83 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
84 {
85 	mnode_t		*node;
86 	float		d;
87 	mplane_t	*plane;
88 
89 	if (!model || !model->nodes)
90 		Sys_Error ("Mod_PointInLeaf: bad model");
91 
92 	node = model->nodes;
93 	while (1)
94 	{
95 		if (node->contents < 0)
96 			return (mleaf_t *)node;
97 		plane = node->plane;
98 		d = DotProduct (p,plane->normal) - plane->dist;
99 		if (d > 0)
100 			node = node->children[0];
101 		else
102 			node = node->children[1];
103 	}
104 
105 	return NULL;	// never reached
106 }
107 
108 
109 /*
110 ===================
111 Mod_DecompressVis
112 ===================
113 */
Mod_DecompressVis(byte * in,model_t * model)114 byte *Mod_DecompressVis (byte *in, model_t *model)
115 {
116 	static byte	decompressed[MAX_MAP_LEAFS/8];
117 	int		c;
118 	byte	*out;
119 	int		row;
120 
121 	row = (model->numleafs+7)>>3;
122 	out = decompressed;
123 
124 	if (!in || r_novis.value == 2)
125 	{	// no vis info, so make all visible
126 		while (row)
127 		{
128 			*out++ = 0xff;
129 			row--;
130 		}
131 		return decompressed;
132 	}
133 
134 	do
135 	{
136 		if (*in)
137 		{
138 			*out++ = *in++;
139 			continue;
140 		}
141 
142 		c = in[1];
143 		in += 2;
144 		while (c)
145 		{
146 			*out++ = 0;
147 			c--;
148 		}
149 	} while (out - decompressed < row);
150 
151 	return decompressed;
152 }
153 
Mod_LeafPVS(mleaf_t * leaf,model_t * model)154 byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
155 {
156 	if (leaf == model->leafs)
157 		return mod_novis;
158 	return Mod_DecompressVis (leaf->compressed_vis, model);
159 }
160 
161 /*
162 ===================
163 Mod_ClearAll
164 ===================
165 */
Mod_ClearAll(void)166 void Mod_ClearAll (void)
167 {
168 	int	i;
169 	model_t	*mod;
170 
171 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
172 		if (mod->type != mod_alias)
173 			mod->needload = true;
174 
175 	if (!isDedicated)
176 		GL_FreeTextures ();
177 }
178 
179 /*
180 ==================
181 Mod_FindName
182 
183 ==================
184 */
Mod_FindName(char * name)185 model_t *Mod_FindName (char *name)
186 {
187 	int		i;
188 	model_t	*mod;
189 
190 	if (!name[0])
191 		Sys_Error ("Mod_FindName: NULL name");
192 
193 //
194 // search the currently loaded models
195 //
196 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
197 		if (!strcmp (mod->name, name) )
198 			break;
199 
200 	if (i == mod_numknown)
201 	{
202 		if (mod_numknown == MAX_MOD_KNOWN)
203 			Sys_Error ("mod_numknown == MAX_MOD_KNOWN (%d)", MAX_MOD_KNOWN);
204 		strcpy (mod->name, name);
205 		mod->needload = true;
206 		mod_numknown++;
207 	}
208 
209 	return mod;
210 }
211 
212 /*
213 ==================
214 Mod_TouchModel
215 
216 ==================
217 */
Mod_TouchModel(char * name)218 void Mod_TouchModel (char *name)
219 {
220 	model_t	*mod;
221 
222 	mod = Mod_FindName (name);
223 
224 	if (!mod->needload)
225 	{
226 		if (mod->type == mod_alias)
227 			Cache_Check (&mod->cache);
228 	}
229 }
230 
231 /*
232 ==================
233 Mod_LoadModel
234 
235 Loads a model into the cache
236 ==================
237 */
Mod_LoadModel(model_t * mod,qboolean crash)238 model_t *Mod_LoadModel (model_t *mod, qboolean crash)
239 {
240 	void	*d;
241 	unsigned *buf;
242 	byte	stackbuf[1024];		// avoid dirtying the cache heap
243 
244 	if (!mod->needload)
245 	{
246 		if (mod->type == mod_alias)
247 		{
248 			d = Cache_Check (&mod->cache);
249 			if (d)
250 				return mod;
251 		}
252 		else
253 			return mod;		// not cached at all
254 	}
255 
256 //
257 // because the world is so huge, load it one piece at a time
258 //
259 
260 //
261 // load the file
262 //
263 	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
264 	if (!buf)
265 	{
266 		if (crash)
267 //                        Sys_Error ("Mod_LoadModel: %s not found", mod->name);
268                         Host_Error ("Mod_LoadModel: %s not found", mod->name);
269 		return NULL;
270 	}
271 
272 //
273 // allocate a new model
274 //
275 	COM_FileBase (mod->name, loadname);
276 
277 	loadmodel = mod;
278 
279 //
280 // fill it in
281 //
282 
283 // call the apropriate loader
284 	mod->needload = false;
285 
286 	switch (LittleLong(*(unsigned *)buf))
287 	{
288 	case IDPOLYHEADER:
289 		Mod_LoadAliasModel (mod, buf);
290 		break;
291 
292 	case IDSPRITEHEADER:
293 		Mod_LoadSpriteModel (mod, buf);
294 		break;
295 
296 	default:
297 		Mod_LoadBrushModel (mod, buf);
298 		break;
299 	}
300 
301 	return mod;
302 }
303 
304 /*
305 ==================
306 Mod_ForName
307 
308 Loads in a model for the given name
309 ==================
310 */
Mod_ForName(char * name,qboolean crash)311 model_t *Mod_ForName (char *name, qboolean crash)
312 {
313 	model_t	*mod;
314 
315 	mod = Mod_FindName (name);
316 
317 	return Mod_LoadModel (mod, crash);
318 }
319 
320 
321 /*
322 ===============================================================================
323 
324 					BRUSHMODEL LOADING
325 
326 ===============================================================================
327 */
328 
329 static int MissTex;
330 byte	   *mod_base;
331 
332 /*
333 =================
334 Mod_ChkLumpSize
335 =================
336 */
Mod_ChkLumpSize(char * Function,lump_t * l,int Size)337 static void Mod_ChkLumpSize (char *Function, lump_t *l, int Size)
338 {
339 	if (l->filelen % Size)
340 		Sys_Error ("%s: lump size %d is not a multiple of %d in %s", Function, l->filelen, Size, loadmodel->name);
341 }
342 
343 /*
344 =================
345 WithinBounds
346 =================
347 */
WithinBounds(int SItem,int Items,int Limit,int * ErrItem)348 static qboolean WithinBounds (int SItem, int Items, int Limit, int *ErrItem)
349 {
350 	int EItem = 0;
351 
352 	if (SItem < 0)
353 		EItem = SItem;
354 	else if (Items < 0)
355 		EItem = Items;
356 	else if (SItem + Items < 0 || SItem + Items > Limit)
357 		EItem = SItem + Items;
358 
359 	if (ErrItem)
360 		*ErrItem = EItem;
361 
362 	return EItem == 0;
363 }
364 
365 /*
366 =================
367 Mod_ChkBounds
368 =================
369 */
Mod_ChkBounds(char * Function,char * Object,int SItem,int Items,int Limit)370 static void Mod_ChkBounds (char *Function, char *Object, int SItem, int Items, int Limit)
371 {
372 	int ErrItem;
373 
374 	if (!WithinBounds (SItem, Items, Limit, &ErrItem))
375 		Sys_Error ("%s: %s is out of bounds (%d, max = %d) in %s", Function, Object, ErrItem, Limit, loadmodel->name);
376 }
377 
378 /*
379 =================
380 Mod_ChkFileSize
381 =================
382 */
Mod_ChkFileSize(char * Function,char * Object,int SItem,int Items)383 static void Mod_ChkFileSize (char *Function, char *Object, int SItem, int Items)
384 {
385 	int ErrItem;
386 
387 	if (!WithinBounds (SItem, Items, com_filesize, &ErrItem))
388 		Sys_Error ("%s: %s is outside file (%d, max = %d) in %s", Function, Object, ErrItem, com_filesize, loadmodel->name);
389 }
390 
391 /*
392 =================
393 Mod_ChkType
394 =================
395 */
Mod_ChkType(char * Function,char * Object,char * ObjNum,int Type,int Type1,int Type2)396 static void Mod_ChkType (char *Function, char *Object, char *ObjNum, int Type, int Type1, int Type2)
397 {
398 	if (Type != Type1 && Type != Type2)
399 	{
400 		// Should be an error but ...
401 		Con_Printf ("\002%s: ", Function);
402 		Con_Printf ("invalid %s %d in %s in %s\n", Object, Type, ObjNum, loadmodel->name);
403 //		Sys_Error ("%s: invalid %s %d in %s in %s", Function, Object, Type, ObjNum, loadmodel->name);
404 	}
405 }
406 
407 /*
408 =================
409 Mod_LoadTextures
410 =================
411 */
Mod_LoadTextures(lump_t * l)412 void Mod_LoadTextures (lump_t *l)
413 {
414 	int		i, j, pixels, num, max, altmax;
415 	miptex_t	*mt;
416 	texture_t	*tx, *tx2;
417 	texture_t	*anims[10];
418 	texture_t	*altanims[10];
419 	dmiptexlump_t   *m;
420 	char		texname[16 + 1];
421 
422 	if (!l->filelen)
423 	{
424 		loadmodel->textures = NULL;
425 		Con_Printf ("\x02Mod_LoadTextures: ");
426 		Con_Printf ("no textures in %s\n", loadmodel->name);
427 		return;
428 	}
429 
430 	// Check bounds for nummiptex var
431 	Mod_ChkBounds ("Mod_LoadTextures", "nummiptex", 0, sizeof(int), l->filelen);
432 
433 	m = (dmiptexlump_t *)(mod_base + l->fileofs);
434 	m->nummiptex = LittleLong (m->nummiptex);
435 
436 	// Check bounds for dataofs array
437 	if (m->nummiptex > 0)
438 		Mod_ChkBounds ("Mod_LoadTextures", "miptex lump", sizeof(int), m->nummiptex * sizeof(int), l->filelen);
439 
440 	loadmodel->numtextures = m->nummiptex;
441 	loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
442 
443 	MissTex = 0;
444 
445 	for (i=0 ; i<m->nummiptex ; i++)
446 	{
447 		int size, copypixels;
448 
449 		m->dataofs[i] = LittleLong (m->dataofs[i]);
450 		if (m->dataofs[i] == -1)
451 		{
452 			++MissTex;
453 			continue;
454 		}
455 		mt = (miptex_t *)((byte *)m + m->dataofs[i]);
456 
457 		// Check bounds for miptex entry
458 		Mod_ChkBounds ("Mod_LoadTextures", "miptex entry", (byte *)mt - (mod_base + l->fileofs), sizeof(miptex_t), l->filelen);
459 
460 		mt->width = LittleLong (mt->width);
461 		mt->height = LittleLong (mt->height);
462 		for (j=0 ; j<MIPLEVELS ; j++)
463 			mt->offsets[j] = LittleLong (mt->offsets[j]);
464 
465 		// Make sure tex name is terminated
466 		memset (texname, 0, sizeof(texname));
467 		memcpy (texname, mt->name, sizeof(texname) - 1);
468 
469 		if (mt->width <= 0 || mt->height <= 0 || (mt->width & 15) || (mt->height & 15))
470 			Sys_Error ("Mod_LoadTextures: texture '%s' is not 16 aligned (%dx%d) in %s", texname, mt->width, mt->height, loadmodel->name);
471 
472 		// Check bounds for miptex objects
473 		for (j=0 ; j<MIPLEVELS ; j++)
474 		{
475 			int ErrItem, Offset = (byte *)mt - (mod_base + l->fileofs) + mt->offsets[j];
476 			int MipSize = mt->width * mt->height / (1 << j * 2);
477 
478 			if (!WithinBounds(Offset, MipSize, l->filelen, &ErrItem))
479 			{
480 				Con_Printf ("\x02Mod_LoadTextures: ");
481 				Con_Printf ("miptex object %d for '%s' is outside texture lump (%d, max = %d) in %s\n", j, texname, ErrItem, l->filelen, loadmodel->name);
482 				mt->offsets[j] = sizeof (miptex_t); // OK?
483 			}
484 		}
485 
486 		pixels = copypixels = mt->width*mt->height/64*85;
487 
488 		size = (byte *)(mt + 1) + pixels - (mod_base + l->fileofs);
489 
490 		// Check bounds for pixels
491 		if (size > l->filelen)
492 		{
493 			Con_Printf ("\x02Mod_LoadTextures: ");
494 			Con_Printf ("pixels for '%s' is outside texture lump (%d, max = %d) in %s\n", texname, size, l->filelen, loadmodel->name);
495 			copypixels -= size - l->filelen; // Prevent access violation
496 		}
497 
498 		tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
499 		loadmodel->textures[i] = tx;
500 
501 		strcpy (tx->name, texname);
502 #ifdef _WIN32
503 		_strlwr (tx->name);
504 #else
505 		strlwr (tx->name);
506 #endif
507 		tx->width = mt->width;
508 		tx->height = mt->height;
509 		for (j=0 ; j<MIPLEVELS ; j++)
510 			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
511 		// the pixels immediately follow the structures
512 		memcpy ( tx+1, mt+1, copypixels);
513 
514 		if (!isDedicated) //no texture uploading for dedicated server
515 		{
516 			if (!Q_strncmp(tx->name,"sky",3))
517 				R_InitSky (tx);
518 			else
519 			{
520 				texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR;
521 				tx->gl_texturenum = GL_LoadTextureFree (tx->name, tx->width, tx->height, (byte *)(tx+1), true, false);
522 				texture_mode = GL_LINEAR;
523 			}
524 		}
525 	}
526 
527 //
528 // sequence the animations
529 //
530 	for (i=0 ; i<m->nummiptex ; i++)
531 	{
532 		tx = loadmodel->textures[i];
533 		if (!tx || tx->name[0] != '+')
534 			continue;
535 		if (tx->anim_next)
536 			continue;	// allready sequenced
537 
538 	// find the number of frames in the animation
539 		memset (anims, 0, sizeof(anims));
540 		memset (altanims, 0, sizeof(altanims));
541 
542 		max = tx->name[1];
543 		altmax = 0;
544 		if (max >= 'a' && max <= 'z')
545 			max -= 'a' - 'A';
546 		if (max >= '0' && max <= '9')
547 		{
548 			max -= '0';
549 			altmax = 0;
550 			anims[max] = tx;
551 			max++;
552 		}
553 		else if (max >= 'A' && max <= 'J')
554 		{
555 			altmax = max - 'A';
556 			max = 0;
557 			altanims[altmax] = tx;
558 			altmax++;
559 		}
560 		else
561 			Sys_Error ("Bad animating texture '%s'", tx->name);
562 
563 		for (j=i+1 ; j<m->nummiptex ; j++)
564 		{
565 			tx2 = loadmodel->textures[j];
566 			if (!tx2 || tx2->name[0] != '+')
567 				continue;
568 			if (strcmp (tx2->name+2, tx->name+2))
569 				continue;
570 
571 			num = tx2->name[1];
572 			if (num >= 'a' && num <= 'z')
573 				num -= 'a' - 'A';
574 			if (num >= '0' && num <= '9')
575 			{
576 				num -= '0';
577 				anims[num] = tx2;
578 				if (num+1 > max)
579 					max = num + 1;
580 			}
581 			else if (num >= 'A' && num <= 'J')
582 			{
583 				num = num - 'A';
584 				altanims[num] = tx2;
585 				if (num+1 > altmax)
586 					altmax = num+1;
587 			}
588 			else
589 				Sys_Error ("Bad animating texture '%s'", tx->name);
590 		}
591 
592 #define	ANIM_CYCLE	2
593 	// link them all together
594 		for (j=0 ; j<max ; j++)
595 		{
596 			tx2 = anims[j];
597 			if (!tx2)
598 				Sys_Error ("Missing frame %i of '%s'", j, tx->name);
599 			tx2->anim_total = max * ANIM_CYCLE;
600 			tx2->anim_min = j * ANIM_CYCLE;
601 			tx2->anim_max = (j+1) * ANIM_CYCLE;
602 			tx2->anim_next = anims[ (j+1)%max ];
603 			if (altmax)
604 				tx2->alternate_anims = altanims[0];
605 		}
606 		for (j=0 ; j<altmax ; j++)
607 		{
608 			tx2 = altanims[j];
609 			if (!tx2)
610 				Sys_Error ("Missing frame %i of '%s'", j, tx->name);
611 			tx2->anim_total = altmax * ANIM_CYCLE;
612 			tx2->anim_min = j * ANIM_CYCLE;
613 			tx2->anim_max = (j+1) * ANIM_CYCLE;
614 			tx2->anim_next = altanims[ (j+1)%altmax ];
615 			if (max)
616 				tx2->alternate_anims = anims[0];
617 		}
618 	}
619 }
620 
621 /*
622 =================
623 Mod_LoadLighting
624 =================
625 */
Mod_LoadLighting(lump_t * l)626 void Mod_LoadLighting (lump_t *l)
627 {
628 	if (!l->filelen)
629 	{
630 		loadmodel->lightdata = NULL;
631 		return;
632 	}
633 	loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
634 	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
635 }
636 
637 
638 /*
639 =================
640 Mod_LoadVisibility
641 =================
642 */
Mod_LoadVisibility(lump_t * l)643 void Mod_LoadVisibility (lump_t *l)
644 {
645 	if (!l->filelen)
646 	{
647 		loadmodel->visdata = NULL;
648 		return;
649 	}
650 	loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);
651 	memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
652 }
653 
654 
655 /*
656 =================
657 Mod_LoadEntities
658 =================
659 */
Mod_LoadEntities(lump_t * l)660 void Mod_LoadEntities (lump_t *l)
661 {
662 	if (!l->filelen)
663 	{
664 		loadmodel->entities = NULL;
665 		return;
666 	}
667 	loadmodel->entities = Hunk_AllocName ( l->filelen + 1, loadname); // +1 for extra NUL below
668 	memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
669 	loadmodel->entities[l->filelen] = 0;
670 
671 	if (loadmodel->entities[l->filelen - 1] != 0)
672 	{
673 		Con_Printf ("\x02Mod_LoadEntities: ");
674 		Con_Printf ("missing NUL in entity lump in %s\n", loadmodel->name);
675 	}
676 }
677 
678 /*
679 =================
680 Mod_LoadVertexes
681 =================
682 */
Mod_LoadVertexes(lump_t * l)683 void Mod_LoadVertexes (lump_t *l)
684 {
685 	dvertex_t	*in;
686 	mvertex_t	*out;
687 	int		i, j, count;
688 
689 	in = (void *)(mod_base + l->fileofs);
690 	Mod_ChkLumpSize ("Mod_LoadVertexes", l, sizeof(*in));
691 	count = l->filelen / sizeof(*in);
692 
693 	if (count > 65535)
694 	{
695 		Con_Printf ("\x02Mod_LoadVertexes: ");
696 		Con_Printf ("excessive vertexes (%d, normal max = %d) in %s\n", count, 65535, loadmodel->name);
697 	}
698 
699 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
700 
701 	loadmodel->vertexes = out;
702 	loadmodel->numvertexes = count;
703 
704 	for ( i=0 ; i<count ; i++, in++, out++)
705 	{
706 		for (j = 0; j < 3; ++j)
707 		{
708 			out->position[j] = LittleFloat (in->point[j]);
709 
710 			// Check bounds
711 			if (fabs(out->position[j]) > 65536)
712 //				Sys_Error ("Mod_LoadVertexes: vertex way out of bounds (%.0f, max = %d) in %s", out->position[j], 4096, loadmodel->name);
713 			{
714 				Con_SafePrintf ("\x02Mod_LoadVertexes: ");
715 				Con_SafePrintf ("vertex way out of bounds (%.g, max = %d) in %s\n", out->position[j], 4096, loadmodel->name);
716 				out->position[j] = 0; // OK?
717 			}
718 		}
719 	}
720 }
721 
722 /*
723 =================
724 Mod_LoadSubmodels
725 =================
726 */
Mod_LoadSubmodels(lump_t * l)727 void Mod_LoadSubmodels (lump_t *l)
728 {
729 	dmodel_t	*in;
730 	dmodel_t	*out;
731 	int		i, j, count, firstface;
732 
733 	in = (void *)(mod_base + l->fileofs);
734 	Mod_ChkLumpSize ("Mod_LoadSubmodels", l, sizeof(*in));
735 	count = l->filelen / sizeof(*in);
736 
737 	if (count > MAX_MODELS) // Why not MAX_MAP_MODELS?
738 		Sys_Error ("Mod_LoadSubmodels: too many models (%d, max = %d) in %s", count, MAX_MODELS, loadmodel->name);
739 
740 	if (count > 256) // Old limit
741 	{
742 		Con_Printf ("\x02Mod_LoadSubmodels: ");
743 		Con_Printf ("excessive models (%d, normal max = %d) in %s\n", count, 256, loadmodel->name);
744 	}
745 
746 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
747 
748 	loadmodel->submodels = out;
749 	loadmodel->numsubmodels = count;
750 
751 	for ( i=0 ; i<count ; i++, in++, out++)
752 	{
753 		for (j=0 ; j<3 ; j++)
754 		{	// spread the mins / maxs by a pixel
755 			out->mins[j] = LittleFloat (in->mins[j]) - 1;
756 			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
757 			out->origin[j] = LittleFloat (in->origin[j]);
758 		}
759 		for (j=0 ; j<MAX_MAP_HULLS ; j++)
760 			out->headnode[j] = LittleLong (in->headnode[j]);
761 		out->visleafs = LittleLong (in->visleafs);
762 
763 		firstface = LittleLong (in->firstface);
764 		out->numfaces = LittleLong (in->numfaces);
765 
766 		// Check bounds
767 		Mod_ChkBounds ("Mod_LoadSubmodels", "face", firstface, out->numfaces, loadmodel->numsurfaces);
768 
769 		out->firstface = firstface;
770 	}
771 
772 	// Check world visleafs
773 	out = loadmodel->submodels;
774 
775 	if (out->visleafs > MAX_MAP_LEAFS)
776 		Sys_Error ("Mod_LoadSubmodels: too many visleafs (%d, max = %d) in %s", out->visleafs, MAX_MAP_LEAFS, loadmodel->name);
777 
778 	if (out->visleafs > 8192) // Old limit
779 	{
780 		Con_Printf ("\x02Mod_LoadSubmodels: ");
781 		Con_Printf ("excessive visleafs (%d, normal max = %d) in %s\n", out->visleafs, 8192, loadmodel->name);
782 	}
783 }
784 
785 /*
786 =================
787 Mod_LoadEdges
788 =================
789 */
Mod_LoadEdges(lump_t * l)790 void Mod_LoadEdges (lump_t *l)
791 {
792 	dedge_t *in;
793 	medge_t *out;
794 	int 	i, j, count;
795 
796 	in = (void *)(mod_base + l->fileofs);
797 	Mod_ChkLumpSize ("Mod_LoadEdges", l, sizeof(*in));
798 	count = l->filelen / sizeof(*in);
799 	out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
800 
801 	loadmodel->edges = out;
802 	loadmodel->numedges = count;
803 
804 	for ( i=0 ; i<count ; i++, in++, out++)
805 	{
806 		for (j = 0; j < 2; ++j)
807 		{
808 			out->v[j] = (unsigned short)LittleShort (in->v[j]);
809 
810 			if (i == 0 && j == 0)
811 				continue; // Why is sometimes this edge invalid?
812 
813 			// Check bounds
814 			if (out->v[j] >= loadmodel->numvertexes)
815 			{
816 				Con_SafePrintf ("\x02Mod_LoadEdges: ");
817 				Con_SafePrintf ("vertex out of bounds (%d, max = %d) in %s\n", out->v[j], loadmodel->numvertexes, loadmodel->name);
818 				out->v[j] = 0; // OK?
819 			}
820 		}
821 	}
822 }
823 
824 /*
825 =================
826 Mod_LoadTexinfo
827 =================
828 */
Mod_LoadTexinfo(lump_t * l)829 void Mod_LoadTexinfo (lump_t *l)
830 {
831 	texinfo_t   *in;
832 	mtexinfo_t  *out;
833 	int 	    i, j, count;
834 	int	    miptex;
835 	float	    len1, len2;
836 
837 	in = (void *)(mod_base + l->fileofs);
838 	Mod_ChkLumpSize ("Mod_LoadTexinfo", l, sizeof(*in));
839 	count = l->filelen / sizeof(*in);
840 
841 	if (count > 32767)
842 	{
843 		Con_Printf ("\x02Mod_LoadTexinfo: ");
844 		Con_Printf ("excessive texinfo (%d, normal max = %d) in %s\n", count, 32767, loadmodel->name);
845 	}
846 
847 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
848 
849 	loadmodel->texinfo = out;
850 	loadmodel->numtexinfo = count;
851 
852 	for ( i=0 ; i<count ; i++, in++, out++)
853 	{
854 		for (j=0 ; j<8 ; j++)
855 			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
856 		len1 = Length (out->vecs[0]);
857 		len2 = Length (out->vecs[1]);
858 		len1 = (len1 + len2)/2;
859 		if (len1 < 0.32)
860 			out->mipadjust = 4;
861 		else if (len1 < 0.49)
862 			out->mipadjust = 3;
863 		else if (len1 < 0.99)
864 			out->mipadjust = 2;
865 		else
866 			out->mipadjust = 1;
867 #if 0
868 		if (len1 + len2 < 0.001)
869 			out->mipadjust = 1;		// don't crash
870 		else
871 			out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
872 #endif
873 
874 		miptex = LittleLong (in->miptex);
875 		out->flags = LittleLong (in->flags);
876 
877 		if (!loadmodel->textures)
878 		{
879 			out->texture = r_notexture_mip;	// checkerboard texture
880 			out->flags = 0;
881 		}
882 		else
883 		{
884 			Mod_ChkBounds ("Mod_LoadTexinfo", "miptex", miptex, 1, loadmodel->numtextures);
885 			out->texture = loadmodel->textures[miptex];
886 			if (!out->texture)
887 			{
888 				out->texture = r_notexture_mip; // texture not found
889 				out->flags = 0;
890 			}
891 		}
892 	}
893 
894 	if (MissTex > 0)
895 	{
896 		Con_Printf ("\x02Mod_LoadTexinfo: ");
897 		Con_Printf ("%d texture%s missing in %s\n", MissTex, MissTex == 1 ? " is" : "s are", loadmodel->name);
898 	}
899 
900 	if (!loadmodel->textures || MissTex > 0)
901 	{
902 		texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR;
903 		r_notexture_mip->gl_texturenum = GL_LoadTexture (r_notexture_mip->name, r_notexture_mip->width, r_notexture_mip->height, (byte *)(r_notexture_mip+1), true, false);
904 		texture_mode = GL_LINEAR;
905 	}
906 }
907 
908 #define MAX_SURF_EXTENTS 512
909 
910 /*
911 ================
912 CalcSurfaceExtents
913 
914 Fills in s->texturemins[] and s->extents[]
915 ================
916 */
CalcSurfaceExtents(msurface_t * s)917 void CalcSurfaceExtents (msurface_t *s)
918 {
919 	float	mins[2], maxs[2], val;
920 	int		i,j, e;
921 	mvertex_t	*v;
922 	mtexinfo_t	*tex;
923 	int		bmins[2], bmaxs[2];
924 
925 	mins[0] = mins[1] = 999999;
926 	maxs[0] = maxs[1] = -99999;
927 
928 	tex = s->texinfo;
929 
930 	for (i=0 ; i<s->numedges ; i++)
931 	{
932 		e = loadmodel->surfedges[s->firstedge+i];
933 		if (e >= 0)
934 			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
935 		else
936 			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
937 
938 		for (j=0 ; j<2 ; j++)
939 		{
940 			val = v->position[0] * tex->vecs[j][0] +
941 				v->position[1] * tex->vecs[j][1] +
942 				v->position[2] * tex->vecs[j][2] +
943 				tex->vecs[j][3];
944 			if (val < mins[j])
945 				mins[j] = val;
946 			if (val > maxs[j])
947 				maxs[j] = val;
948 		}
949 	}
950 
951 	for (i=0 ; i<2 ; i++)
952 	{
953 		bmins[i] = floor(mins[i]/16);
954 		bmaxs[i] = ceil(maxs[i]/16);
955 
956 		s->texturemins[i] = bmins[i] * 16;
957 		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
958 		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > MAX_SURF_EXTENTS /* 256 */ )
959 		{
960 			Con_SafePrintf ("\002CalcSurfaceExtents: ");
961 			Con_SafePrintf ("excessive surface extents (%d, normal max = %d), texture %s in %s\n", s->extents[i], MAX_SURF_EXTENTS, tex->texture->name, loadmodel->name);
962 			s->extents[i] = MAX_SURF_EXTENTS; // Kludge, but seems to work
963 		}
964 	}
965 }
966 
967 
968 /*
969 =================
970 Mod_LoadFaces
971 =================
972 */
Mod_LoadFaces(lump_t * l)973 void Mod_LoadFaces (lump_t *l)
974 {
975 	dface_t		*in;
976 	msurface_t 	*out;
977 	int		i, count, surfnum, texinfo, firstsurfedge;
978 	int		planenum, side;
979 
980 	in = (void *)(mod_base + l->fileofs);
981 	Mod_ChkLumpSize ("Mod_LoadFaces", l, sizeof(*in));
982 	count = l->filelen / sizeof(*in);
983 
984 	if (count > 32767)
985 	{
986 		Con_Printf ("\x02Mod_LoadFaces: ");
987 		Con_Printf ("excessive faces (%d, normal max = %d) in %s\n", count, 32767, loadmodel->name);
988 	}
989 
990 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
991 
992 	loadmodel->surfaces = out;
993 	loadmodel->numsurfaces = count;
994 
995 	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
996 	{
997 		firstsurfedge = LittleLong (in->firstedge);
998 		out->numedges = LittleShort (in->numedges);
999 
1000 		// Check bounds
1001 		Mod_ChkBounds ("MOD_LoadFaces", "surfedge", firstsurfedge, out->numedges, loadmodel->numsurfedges);
1002 
1003 		out->firstedge = firstsurfedge;
1004 		out->flags = 0;
1005 
1006 		planenum = LittleShort (in->planenum);
1007 
1008 		Mod_ChkBounds ("MOD_LoadFaces", "plane", planenum, 1, loadmodel->numplanes);
1009 
1010 		side = LittleShort (in->side);
1011 		if (side)
1012 			out->flags |= SURF_PLANEBACK;
1013 
1014 		out->plane = loadmodel->planes + planenum;
1015 
1016 		texinfo = LittleShort (in->texinfo);
1017 
1018 		Mod_ChkBounds ("MOD_LoadFaces", "texinfo", texinfo, 1, loadmodel->numtexinfo);
1019 
1020 		out->texinfo = loadmodel->texinfo + texinfo;
1021 
1022 		CalcSurfaceExtents (out);
1023 
1024 	// lighting info
1025 
1026 		for (i=0 ; i<MAXLIGHTMAPS ; i++)
1027 			out->styles[i] = in->styles[i];
1028 		i = LittleLong(in->lightofs);
1029 
1030 		if (i != -1)
1031 		{
1032 			int LightSize = ((dheader_t *)mod_base)->lumps[LUMP_LIGHTING].filelen;
1033 
1034 			if (!WithinBounds (i, 1, LightSize, NULL))
1035 			{
1036 				Con_SafePrintf ("\002MOD_LoadFaces: ");
1037 				Con_SafePrintf ("lightofs out of bounds (%d, max = %d) in %s\n", i, LightSize, loadmodel->name);
1038 				i = -1;
1039 			}
1040 		}
1041 
1042 		if (i == -1)
1043 			out->samples = NULL;
1044 		else
1045 			out->samples = loadmodel->lightdata + i;
1046 
1047 	// set the drawing flags flag
1048 
1049 		if (!Q_strncmp(out->texinfo->texture->name,"sky",3))	// sky
1050 		{
1051 			out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
1052 // Nehahra
1053 			GL_SubdivideSurface (out);	// cut up polygon for warps
1054 
1055 			continue;
1056 		}
1057 
1058 		if (out->texinfo->texture->name[0] == '*')		// turbulent
1059 		{
1060 			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
1061 			for (i=0 ; i<2 ; i++)
1062 			{
1063 				out->extents[i] = 16384;
1064 				out->texturemins[i] = -8192;
1065 			}
1066 			GL_SubdivideSurface (out);	// cut up polygon for warps
1067 			continue;
1068 		}
1069 
1070 	}
1071 }
1072 
1073 static unsigned RecursLevel;
1074 
1075 /*
1076 =================
1077 Mod_SetParent
1078 =================
1079 */
Mod_SetParent(mnode_t * node,mnode_t * parent)1080 void static Mod_SetParent (mnode_t *node, mnode_t *parent)
1081 {
1082 	if (!node || ++RecursLevel > 4096) // 512 seems enough for huge maps and 8192 might create stack overflow
1083 		Sys_Error ("Mod_SetParent: %s in %s", !node ? "invalid node" : "excessive tree depth", loadmodel->name);
1084 
1085 	node->parent = parent;
1086 	if (node->contents >= 0)
1087 	{
1088 		Mod_SetParent (node->children[0], node);
1089 		Mod_SetParent (node->children[1], node);
1090 	}
1091 
1092 	--RecursLevel;
1093 }
1094 
1095 /*
1096 =================
1097 Mod_LoadNodes
1098 =================
1099 */
Mod_LoadNodes(lump_t * l)1100 void Mod_LoadNodes (lump_t *l)
1101 {
1102 	int	i, j, count, p, firstface;
1103 	dnode_t	*in;
1104 	mnode_t *out;
1105 
1106 	in = (void *)(mod_base + l->fileofs);
1107 	Mod_ChkLumpSize ("Mod_LoadNodes", l, sizeof(*in));
1108 	count = l->filelen / sizeof(*in);
1109 
1110 	// Check nodes
1111 	if (count > 32767)
1112 //		Sys_Error ("MOD_LoadNodes: too many nodes (%d, max = %d) in %s", count, 32767, loadmodel->name);
1113 	{
1114 		Con_Printf ("\x02Mod_LoadNodes: ");
1115 		Con_Printf ("excessive nodes (%d, normal max = %d) in %s\n", count, 32767, loadmodel->name);
1116 	}
1117 
1118 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1119 
1120 	loadmodel->nodes = out;
1121 	loadmodel->numnodes = count;
1122 
1123 	for ( i=0 ; i<count ; i++, in++, out++)
1124 	{
1125 		for (j=0 ; j<3 ; j++)
1126 		{
1127 			out->minmaxs[j] = LittleShort (in->mins[j]);
1128 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
1129 		}
1130 
1131 		p = LittleLong (in->planenum);
1132 
1133 		Mod_ChkBounds ("MOD_LoadNodes", "plane", p, 1, loadmodel->numplanes);
1134 
1135 		out->plane = loadmodel->planes + p;
1136 
1137 		firstface = (unsigned short)LittleShort (in->firstface);
1138 		out->numsurfaces = (unsigned short)LittleShort (in->numfaces);
1139 
1140 		// Check bounds
1141 		Mod_ChkBounds ("MOD_LoadNodes", "face", firstface, out->numsurfaces, loadmodel->numsurfaces);
1142 
1143 		out->firstsurface = firstface;
1144 
1145 		for (j=0 ; j<2 ; j++)
1146 		{
1147 			p = LittleShort (in->children[j]);
1148 
1149 			if (p < -loadmodel->numleafs)
1150 				p += 65536; // Gross hack to connect as much as possible of the crippled bsp tree
1151 
1152 			if (p >= 0)
1153 			{
1154 				if (p >= loadmodel->numnodes)
1155 //					Sys_Error ("MOD_LoadNodes: node out of bounds (%d, max = %d)", p, loadmodel->numnodes);
1156 					p = loadmodel->numnodes - 1;
1157 
1158 				out->children[j] = loadmodel->nodes + p;
1159 			}
1160 			else
1161 			{
1162 				if ((-1 - p) >= loadmodel->numleafs)
1163 //					Sys_Error ("MOD_LoadNodes: leaf out of bounds (%d, max = %d)", (-1 - p), loadmodel->numleafs);
1164 					p = -loadmodel->numleafs;
1165 
1166 				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
1167 			}
1168 		}
1169 	}
1170 
1171 	RecursLevel = 0;
1172 	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
1173 }
1174 
1175 /*
1176 =================
1177 Mod_LoadLeafs
1178 =================
1179 */
Mod_LoadLeafs(lump_t * l)1180 void Mod_LoadLeafs (lump_t *l)
1181 {
1182 	dleaf_t *in;
1183 	mleaf_t *out;
1184 	int	i, j, count, p, firstmarksurface;
1185 
1186 	in = (void *)(mod_base + l->fileofs);
1187 	Mod_ChkLumpSize ("Mod_LoadLeafs", l, sizeof(*in));
1188 	count = l->filelen / sizeof(*in);
1189 
1190 	// Check leafs
1191 	if (count > 32767)
1192 		Sys_Error ("MOD_LoadLeafs: too many leafs (%d, max = %d) in %s", count, 32767, loadmodel->name);
1193 
1194 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1195 
1196 	loadmodel->leafs = out;
1197 	loadmodel->numleafs = count;
1198 
1199 	for ( i=0 ; i<count ; i++, in++, out++)
1200 	{
1201 		for (j=0 ; j<3 ; j++)
1202 		{
1203 			out->minmaxs[j] = LittleShort (in->mins[j]);
1204 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
1205 		}
1206 
1207 		p = LittleLong(in->contents);
1208 		out->contents = p;
1209 
1210 		firstmarksurface = (unsigned short)LittleShort (in->firstmarksurface);
1211 		out->nummarksurfaces = (unsigned short)LittleShort (in->nummarksurfaces);
1212 
1213 		// Check bounds
1214 		Mod_ChkBounds ("MOD_LoadLeafs", "marksurfaces", firstmarksurface, out->nummarksurfaces, loadmodel->nummarksurfaces);
1215 
1216 		out->firstmarksurface = loadmodel->marksurfaces + firstmarksurface;
1217 
1218 		p = LittleLong(in->visofs);
1219 		if (p == -1)
1220 			out->compressed_vis = NULL;
1221 		else
1222 			out->compressed_vis = loadmodel->visdata + p;
1223 		out->efrags = NULL;
1224 
1225 		for (j=0 ; j<4 ; j++)
1226 			out->ambient_sound_level[j] = in->ambient_level[j];
1227 
1228 		// gl underwater warp
1229 		if (out->contents != CONTENTS_EMPTY)
1230 		{
1231 			for (j=0 ; j<out->nummarksurfaces ; j++)
1232 			{
1233 				if (!strcmp(out->firstmarksurface[j]->texinfo->texture->name, "notexture"))
1234 					out->firstmarksurface[j]->flags |= SURF_DRAWSKY;
1235 				else
1236 					out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
1237 			}
1238 		}
1239 	}
1240 }
1241 
1242 /*
1243 =================
1244 Mod_LoadClipnodes
1245 =================
1246 */
Mod_LoadClipnodes(lump_t * l)1247 void Mod_LoadClipnodes (lump_t *l)
1248 {
1249 	dclipnode_t *in, *out;
1250 	int	    i, count;
1251 	hull_t	    *hull;
1252 
1253 	in = (void *)(mod_base + l->fileofs);
1254 	Mod_ChkLumpSize ("Mod_LoadClipnodes", l, sizeof(*in));
1255 	count = l->filelen / sizeof(*in);
1256 
1257 	if (count > 32767) // Normal limit
1258 	{
1259 		Con_Printf ("\x02Mod_LoadClipnodes: ");
1260 		Con_Printf ("excessive clipnodes (%d, normal max = %d) in %s\n", count, 32767, loadmodel->name);
1261 	}
1262 
1263 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1264 
1265 	loadmodel->clipnodes = out;
1266 	loadmodel->numclipnodes = count;
1267 
1268 	hull = &loadmodel->hulls[1];
1269 	hull->clipnodes = out;
1270 	hull->firstclipnode = 0;
1271 	hull->lastclipnode = count-1;
1272 	hull->planes = loadmodel->planes;
1273 	hull->clip_mins[0] = -16;
1274 	hull->clip_mins[1] = -16;
1275 	hull->clip_mins[2] = -24;
1276 	hull->clip_maxs[0] = 16;
1277 	hull->clip_maxs[1] = 16;
1278 	hull->clip_maxs[2] = 32;
1279 
1280 	hull = &loadmodel->hulls[2];
1281 	hull->clipnodes = out;
1282 	hull->firstclipnode = 0;
1283 	hull->lastclipnode = count-1;
1284 	hull->planes = loadmodel->planes;
1285 	hull->clip_mins[0] = -32;
1286 	hull->clip_mins[1] = -32;
1287 	hull->clip_mins[2] = -24;
1288 	hull->clip_maxs[0] = 32;
1289 	hull->clip_maxs[1] = 32;
1290 	hull->clip_maxs[2] = 64;
1291 
1292 	for (i=0 ; i<count ; i++, out++, in++)
1293 	{
1294 		out->planenum = LittleLong(in->planenum);
1295 
1296 		// Check bounds
1297 		if (out->planenum < 0 || out->planenum >= loadmodel->numplanes)
1298 		{
1299 			Con_SafePrintf ("\x02Mod_LoadClipnodes: ");
1300 			Con_SafePrintf ("plane out of bounds (%d, max = %d) in %s\n", out->planenum, loadmodel->numplanes, loadmodel->name);
1301 			out->planenum = 0; // Kludge, but seems to work
1302 		}
1303 
1304 		out->children[0] = LittleShort(in->children[0]);
1305 		out->children[1] = LittleShort(in->children[1]);
1306 	}
1307 }
1308 
1309 /*
1310 =================
1311 Mod_MakeHull0
1312 
1313 Deplicate the drawing hull structure as a clipping hull
1314 =================
1315 */
Mod_MakeHull0(void)1316 void Mod_MakeHull0 (void)
1317 {
1318 	mnode_t		*in, *child;
1319 	dclipnode_t *out;
1320 	int			i, j, count;
1321 	hull_t		*hull;
1322 
1323 	hull = &loadmodel->hulls[0];
1324 
1325 	in = loadmodel->nodes;
1326 	count = loadmodel->numnodes;
1327 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1328 
1329 	hull->clipnodes = out;
1330 	hull->firstclipnode = 0;
1331 	hull->lastclipnode = count-1;
1332 	hull->planes = loadmodel->planes;
1333 
1334 	for (i=0 ; i<count ; i++, out++, in++)
1335 	{
1336 		out->planenum = in->plane - loadmodel->planes;
1337 		for (j=0 ; j<2 ; j++)
1338 		{
1339 			child = in->children[j];
1340 			if (child->contents < 0)
1341 				out->children[j] = child->contents;
1342 			else
1343 				out->children[j] = child - loadmodel->nodes;
1344 		}
1345 	}
1346 }
1347 
1348 /*
1349 =================
1350 Mod_LoadMarksurfaces
1351 =================
1352 */
Mod_LoadMarksurfaces(lump_t * l)1353 void Mod_LoadMarksurfaces (lump_t *l)
1354 {
1355 	int		i, j, count;
1356 	unsigned short	*in;
1357 	msurface_t      **out;
1358 
1359 	in = (void *)(mod_base + l->fileofs);
1360 	Mod_ChkLumpSize ("Mod_LoadMarksurfaces", l, sizeof(*in));
1361 	count = l->filelen / sizeof(*in);
1362 
1363 	// Check marksurfaces
1364 //	if (count > 65535)
1365 //		Sys_Error ("Mod_LoadMarksurfaces: too many marksurfaces (%d, max = %d) in %s", count, 65535, loadmodel->name);
1366 
1367 	if (count > 32767) // Normal limit
1368 	{
1369 		Con_Printf ("\x02Mod_LoadMarksurfaces: ");
1370 		Con_Printf ("excessive marksurfaces (%d, normal max = %d) in %s\n", count, 32767, loadmodel->name);
1371 	}
1372 
1373 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1374 
1375 	loadmodel->marksurfaces = out;
1376 	loadmodel->nummarksurfaces = count;
1377 
1378 	for ( i=0 ; i<count ; i++)
1379 	{
1380 		j = (unsigned short)LittleShort(in[i]);
1381 		Mod_ChkBounds ("Mod_LoadMarksurfaces", "face", j, 1, loadmodel->numsurfaces);
1382 		out[i] = loadmodel->surfaces + j;
1383 	}
1384 }
1385 
1386 /*
1387 =================
1388 Mod_LoadSurfedges
1389 =================
1390 */
Mod_LoadSurfedges(lump_t * l)1391 void Mod_LoadSurfedges (lump_t *l)
1392 {
1393 	int	i, count;
1394 	int	*in, *out;
1395 
1396 	in = (void *)(mod_base + l->fileofs);
1397 	Mod_ChkLumpSize ("Mod_LoadSurfedges", l, sizeof(*in));
1398 	count = l->filelen / sizeof(*in);
1399 	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1400 
1401 	loadmodel->surfedges = out;
1402 	loadmodel->numsurfedges = count;
1403 
1404 	for ( i=0 ; i<count ; i++)
1405 	{
1406 		out[i] = LittleLong (in[i]);
1407 
1408 		// Check bounds
1409 		if (abs(out[i]) >= loadmodel->numedges)
1410 		{
1411 			Con_SafePrintf ("\x02Mod_LoadSurfedges: ");
1412 			Con_SafePrintf ("edge out of bounds (%d, max = %d) in %s\n", out[i], loadmodel->numedges, loadmodel->name);
1413 			out[i] = 0; // OK?
1414 		}
1415 	}
1416 }
1417 
1418 /*
1419 =================
1420 Mod_LoadPlanes
1421 =================
1422 */
Mod_LoadPlanes(lump_t * l)1423 void Mod_LoadPlanes (lump_t *l)
1424 {
1425 	int		i, j;
1426 	mplane_t	*out;
1427 	dplane_t 	*in;
1428 	int		count;
1429 	int		bits;
1430 
1431 	in = (void *)(mod_base + l->fileofs);
1432 	Mod_ChkLumpSize ("Mod_LoadPlanes", l, sizeof(*in));
1433 	count = l->filelen / sizeof(*in);
1434 
1435 	if (count > 32767)
1436 	{
1437 		Con_Printf ("\x02Mod_LoadPlanes: ");
1438 		Con_Printf ("excessive planes (%d, normal max = %d) in %s\n", count, 32767, loadmodel->name);
1439 	}
1440 
1441 	out = Hunk_AllocName ( count*2*sizeof(*out), loadname);
1442 
1443 	loadmodel->planes = out;
1444 	loadmodel->numplanes = count;
1445 
1446 	for ( i=0 ; i<count ; i++, in++, out++)
1447 	{
1448 		bits = 0;
1449 		for (j=0 ; j<3 ; j++)
1450 		{
1451 			out->normal[j] = LittleFloat (in->normal[j]);
1452 			if (out->normal[j] < 0)
1453 				bits |= 1<<j;
1454 		}
1455 
1456 		out->dist = LittleFloat (in->dist);
1457 		out->type = LittleLong (in->type);
1458 		out->signbits = bits;
1459 	}
1460 }
1461 
1462 /*
1463 =================
1464 RadiusFromBounds
1465 =================
1466 */
RadiusFromBounds(vec3_t mins,vec3_t maxs)1467 float RadiusFromBounds (vec3_t mins, vec3_t maxs)
1468 {
1469 	int		i;
1470 	vec3_t	corner;
1471 
1472 	for (i=0 ; i<3 ; i++)
1473 	{
1474 		corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
1475 	}
1476 
1477 	return Length (corner);
1478 }
1479 
1480 static char *LumpDesc[] =
1481 {
1482 	"entities",
1483 	"planes",
1484 	"textures",
1485 	"vertexes",
1486 	"visdata",
1487 	"nodes",
1488 	"texinfo",
1489 	"faces",
1490 	"lighting",
1491 	"clipnodes",
1492 	"leafs",
1493 	"marksurfaces",
1494 	"edges",
1495 	"surfedges",
1496 	"models",
1497 };
1498 
1499 /*
1500 =================
1501 Mod_LoadBrushModel
1502 =================
1503 */
Mod_LoadBrushModel(model_t * mod,void * buffer)1504 void Mod_LoadBrushModel (model_t *mod, void *buffer)
1505 {
1506 	int		i, j;
1507 	dheader_t	*header;
1508 	dmodel_t 	*bm;
1509 
1510 	loadmodel->type = mod_brush;
1511 
1512 	header = (dheader_t *)buffer;
1513 
1514 	// Check header is inside file buffer
1515 	Mod_ChkFileSize ("Mod_LoadBrushModel", "header", 0, sizeof(dheader_t));
1516 
1517 	i = LittleLong (header->version);
1518 	if (i != BSPVERSION)
1519 		Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
1520 
1521 // swap all the lumps
1522 	mod_base = (byte *)header;
1523 
1524 	for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
1525 		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
1526 
1527 	// Check all lumps are OK and inside file buffer
1528 	for (i = 0; i < HEADER_LUMPS; ++i)
1529 		Mod_ChkFileSize ("Mod_LoadBrushModel", LumpDesc[i], header->lumps[i].fileofs, header->lumps[i].filelen);
1530 
1531 // load into heap
1532 
1533 	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
1534 	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
1535 	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
1536 	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
1537 	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
1538 	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
1539 	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
1540 	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
1541 	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
1542 	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
1543 	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
1544 	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
1545 	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
1546 	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
1547 	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
1548 
1549 	Mod_MakeHull0 ();
1550 
1551 	mod->numframes = 2;		// regular and alternate animation
1552 
1553 //
1554 // set up the submodels (FIXME: this is confusing)
1555 //
1556 	for (i=0 ; i<mod->numsubmodels ; i++)
1557 	{
1558 		bm = &mod->submodels[i];
1559 
1560 		mod->hulls[0].firstclipnode = bm->headnode[0];
1561 		for (j=1 ; j<MAX_MAP_HULLS ; j++)
1562 		{
1563 			mod->hulls[j].firstclipnode = bm->headnode[j];
1564 			mod->hulls[j].lastclipnode = mod->numclipnodes-1;
1565 		}
1566 
1567 		mod->firstmodelsurface = bm->firstface;
1568 		mod->nummodelsurfaces = bm->numfaces;
1569 
1570 		VectorCopy (bm->maxs, mod->maxs);
1571 		VectorCopy (bm->mins, mod->mins);
1572 
1573 		mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
1574 
1575 		mod->numleafs = bm->visleafs;
1576 
1577 		if (i < mod->numsubmodels-1)
1578 		{	// duplicate the basic information
1579 			char	name[10];
1580 
1581 			sprintf (name, "*%i", i+1);
1582 			loadmodel = Mod_FindName (name);
1583 			*loadmodel = *mod;
1584 			strcpy (loadmodel->name, name);
1585 			mod = loadmodel;
1586 		}
1587 	}
1588 }
1589 
1590 /*
1591 ==============================================================================
1592 
1593 ALIAS MODELS
1594 
1595 ==============================================================================
1596 */
1597 
1598 aliashdr_t	*pheader;
1599 
1600 stvert_t	stverts[MAXALIASVERTS];
1601 mtriangle_t	triangles[MAXALIASTRIS];
1602 
1603 // a pose is a single set of vertexes.  a frame may be
1604 // an animating sequence of poses
1605 trivertx_t	*poseverts[MAXALIASFRAMES];
1606 int			posenum;
1607 
1608 byte		**player_8bit_texels_tbl;
1609 byte		*player_8bit_texels;
1610 
1611 int             aliasbboxmin[3], aliasbboxmax[3]; // Nehahra: LordHavoc - proper bounding box considerations
1612 /*
1613 =================
1614 Mod_LoadAliasFrame
1615 =================
1616 */
Mod_LoadAliasFrame(void * pin,maliasframedesc_t * frame)1617 void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
1618 {
1619 	trivertx_t	*pframe, *pinframe;
1620 	int		i, j;
1621 	daliasframe_t	*pdaliasframe;
1622 
1623 	pdaliasframe = (daliasframe_t *)pin;
1624 
1625 	// Check frame is inside file buffer
1626 	Mod_ChkFileSize ("Mod_LoadAliasFrame", "frame", (byte *)pdaliasframe - mod_base, sizeof(daliasframe_t));
1627 
1628 	strcpy (frame->name, pdaliasframe->name);
1629 	frame->firstpose = posenum;
1630 	frame->numposes = 1;
1631 
1632 	for (i=0 ; i<3 ; i++)
1633 	{
1634 	// these are byte values, so we don't have to worry about
1635 	// endianness
1636 		frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
1637                 frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i]; // Nehahra - EnderFIX
1638 
1639 		if (frame->bboxmin.v[i] < aliasbboxmin[i]) // LordHavoc: doing proper bbox for model
1640 			aliasbboxmin[i] = frame->bboxmin.v[i];
1641 		if (frame->bboxmax.v[i] > aliasbboxmax[i])
1642                         aliasbboxmax[i] = frame->bboxmax.v[i];
1643 
1644 	}
1645 
1646 	pinframe = (trivertx_t *)(pdaliasframe + 1);
1647 
1648 	// Check trivertex is inside file buffer
1649 	Mod_ChkFileSize ("Mod_LoadAliasFrame", "trivertex", (byte *)pinframe - mod_base, sizeof(trivertx_t));
1650 
1651 	if (posenum >= MAXALIASFRAMES)
1652 		Sys_Error ("Mod_LoadAliasFrame: invalid # of frames (%d, max = %d) in %s", posenum, MAXALIASFRAMES, loadmodel->name);
1653 
1654 	poseverts[posenum] = pinframe;
1655 	posenum++;
1656 
1657 	pinframe += pheader->numverts;
1658 
1659 	return (void *)pinframe;
1660 }
1661 
1662 
1663 /*
1664 =================
1665 Mod_LoadAliasGroup
1666 =================
1667 */
Mod_LoadAliasGroup(void * pin,maliasframedesc_t * frame)1668 void *Mod_LoadAliasGroup (void * pin,  maliasframedesc_t *frame)
1669 {
1670 	daliasgroup_t		*pingroup;
1671 	int			i, numframes;
1672 	daliasinterval_t	*pin_intervals;
1673 	void			*ptemp;
1674 
1675 	pingroup = (daliasgroup_t *)pin;
1676 
1677 	// Check group is inside file buffer
1678 	Mod_ChkFileSize ("Mod_LoadAliasGroup", "group", (byte *)pingroup - mod_base, sizeof(daliasgroup_t));
1679 
1680 	numframes = LittleLong (pingroup->numframes);
1681 
1682 	frame->firstpose = posenum;
1683 	frame->numposes = numframes;
1684 
1685 	for (i=0 ; i<3 ; i++)
1686 	{
1687 	// these are byte values, so we don't have to worry about endianness
1688 		frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
1689                 frame->bboxmax.v[i] = pingroup->bboxmax.v[i]; // Nehahra - EnderFIX
1690 
1691 		if (frame->bboxmin.v[i] < aliasbboxmin[i]) // LordHavoc: doing proper bbox for model
1692 			aliasbboxmin[i] = frame->bboxmin.v[i];
1693 		if (frame->bboxmax.v[i] > aliasbboxmax[i])
1694                         aliasbboxmax[i] = frame->bboxmax.v[i];
1695  	}
1696 
1697 	pin_intervals = (daliasinterval_t *)(pingroup + 1);
1698 
1699 	// Check intervals are inside file buffer
1700 	Mod_ChkFileSize ("Mod_LoadAliasGroup", "intervals", (byte *)pin_intervals - mod_base, numframes * sizeof(daliasinterval_t));
1701 
1702 	frame->interval = LittleFloat (pin_intervals->interval);
1703 
1704 	pin_intervals += numframes;
1705 
1706 	ptemp = (void *)pin_intervals;
1707 
1708 	for (i=0 ; i<numframes ; i++)
1709 	{
1710 		// Check trivertex is inside file buffer
1711 		Mod_ChkFileSize ("Mod_LoadAliasGroup", "trivertex", (byte *)((daliasframe_t *)ptemp + 1) - mod_base, sizeof(trivertx_t));
1712 
1713 		if (posenum >= MAXALIASFRAMES)
1714 			Sys_Error ("Mod_LoadAliasGroup: invalid # of frames (%d, max = %d) in %s", posenum, MAXALIASFRAMES, loadmodel->name);
1715 
1716 		poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
1717 		posenum++;
1718 
1719 		ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
1720 	}
1721 
1722 	return ptemp;
1723 }
1724 
1725 //=========================================================
1726 
1727 /*
1728 =================
1729 Mod_FloodFillSkin
1730 
1731 Fill background pixels so mipmapping doesn't have haloes - Ed
1732 =================
1733 */
1734 
1735 typedef struct
1736 {
1737 	short		x, y;
1738 } floodfill_t;
1739 
1740 extern unsigned d_8to24table[];
1741 
1742 // must be a power of 2
1743 #define FLOODFILL_FIFO_SIZE 0x1000
1744 #define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
1745 
1746 #define FLOODFILL_STEP( off, dx, dy ) \
1747 { \
1748 	if (pos[off] == fillcolor) \
1749 	{ \
1750 		pos[off] = 255; \
1751 		fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
1752 		inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
1753 	} \
1754 	else if (pos[off] != 255) fdc = pos[off]; \
1755 }
1756 
Mod_FloodFillSkin(byte * skin,int skinwidth,int skinheight)1757 void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
1758 {
1759 	byte				fillcolor = *skin; // assume this is the pixel to fill
1760 	floodfill_t			fifo[FLOODFILL_FIFO_SIZE];
1761 	int					inpt = 0, outpt = 0;
1762 	int					filledcolor = -1;
1763 	int					i;
1764 
1765 	if (filledcolor == -1)
1766 	{
1767 		filledcolor = 0;
1768 		// attempt to find opaque black
1769 		for (i = 0; i < 256; ++i)
1770 			if (d_8to24table[i] == (255 << 0)) // alpha 1.0
1771 			{
1772 				filledcolor = i;
1773 				break;
1774 			}
1775 	}
1776 
1777 	// can't fill to filled color or to transparent color (used as visited marker)
1778 	if ((fillcolor == filledcolor) || (fillcolor == 255))
1779 	{
1780 		//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
1781 		return;
1782 	}
1783 
1784 	fifo[inpt].x = 0, fifo[inpt].y = 0;
1785 	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
1786 
1787 	while (outpt != inpt)
1788 	{
1789 		int			x = fifo[outpt].x, y = fifo[outpt].y;
1790 		int			fdc = filledcolor;
1791 		byte		*pos = &skin[x + skinwidth * y];
1792 
1793 		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
1794 
1795 		if (x > 0)				FLOODFILL_STEP( -1, -1, 0 );
1796 		if (x < skinwidth - 1)	FLOODFILL_STEP( 1, 1, 0 );
1797 		if (y > 0)				FLOODFILL_STEP( -skinwidth, 0, -1 );
1798 		if (y < skinheight - 1)	FLOODFILL_STEP( skinwidth, 0, 1 );
1799 		skin[x + skinwidth * y] = fdc;
1800 	}
1801 }
1802 
1803 /*
1804 ===============
1805 Mod_LoadAllSkins
1806 ===============
1807 */
Mod_LoadAllSkins(int numskins,daliasskintype_t * pskintype)1808 void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
1809 {
1810 	int			i, j, k;
1811 	char			name[32];
1812 	int			s;
1813 	byte			*copy;
1814 	byte			*skin;
1815 	byte			*texels;
1816 	daliasskingroup_t	*pinskingroup;
1817 	int			groupskins;
1818 	daliasskininterval_t	*pinskinintervals;
1819 
1820 	skin = (byte *)(pskintype + 1);
1821 
1822 	if (numskins < 1 || numskins > MAX_SKINS)
1823 		Sys_Error ("Mod_LoadAllSkins: invalid # of skins (%d, max = %d) in %s", numskins, MAX_SKINS, loadmodel->name);
1824 
1825 	s = pheader->skinwidth * pheader->skinheight;
1826 
1827 	for (i=0 ; i<numskins ; i++)
1828 	{
1829 		char Str[256];
1830 
1831 		sprintf (Str, "skin %d", i);
1832 		Mod_ChkFileSize ("Mod_LoadAllSkins", Str, (byte *)pskintype - mod_base, sizeof(daliasskintype_t));
1833 
1834 		Mod_ChkType ("Mod_LoadAllSkins", "skintype", Str, pskintype->type, ALIAS_SKIN_SINGLE, ALIAS_SKIN_GROUP);
1835 
1836 		if (pskintype->type == ALIAS_SKIN_SINGLE) {
1837 			Mod_ChkFileSize ("Mod_LoadAllSkins", Str, (byte *)(pskintype + 1) - mod_base, s);
1838 
1839 			Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
1840 
1841 			// save 8 bit texels for the player model to remap
1842 	//		if (!strcmp(loadmodel->name,"progs/player.mdl")) {
1843 				texels = Hunk_AllocName(s, loadname);
1844 				pheader->texels[i] = texels - (byte *)pheader;
1845 				memcpy (texels, (byte *)(pskintype + 1), s);
1846 	//		}
1847 			sprintf (name, "%s_%i", loadmodel->name, i);
1848 			pheader->gl_texturenum[i][0] =
1849 			pheader->gl_texturenum[i][1] =
1850 			pheader->gl_texturenum[i][2] =
1851 			pheader->gl_texturenum[i][3] =
1852 				GL_LoadTexture (name, pheader->skinwidth,
1853 				pheader->skinheight, (byte *)(pskintype + 1), true, false);
1854 			pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
1855 		}
1856 		else
1857 		{
1858 			// animating skin group.  yuck.
1859 			pskintype++;
1860 			pinskingroup = (daliasskingroup_t *)pskintype;
1861 
1862 			sprintf (Str, "group %d", i);
1863 			Mod_ChkFileSize ("Mod_LoadAllSkins", Str, (byte *)pinskingroup - mod_base, sizeof(daliasskingroup_t));
1864 
1865 			groupskins = LittleLong (pinskingroup->numskins);
1866 			pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
1867 
1868 			pskintype = (void *)(pinskinintervals + groupskins);
1869 
1870 			for (j=0 ; j<groupskins ; j++)
1871 			{
1872 				sprintf (Str, "group %d, skin %d", i, j);
1873 				Mod_ChkFileSize ("Mod_LoadAllSkins", Str, (byte *)pskintype - mod_base, s);
1874 
1875 				Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
1876 				if (j == 0) {
1877 					texels = Hunk_AllocName(s, loadname);
1878 					pheader->texels[i] = texels - (byte *)pheader;
1879 					memcpy (texels, (byte *)(pskintype), s);
1880 				}
1881 				sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
1882 				pheader->gl_texturenum[i][j&3] =
1883 					GL_LoadTexture (name, pheader->skinwidth,
1884 					pheader->skinheight, (byte *)(pskintype), true, false);
1885 				pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
1886 			}
1887 			k = j;
1888 			for (/* */; j < 4; j++)
1889 				pheader->gl_texturenum[i][j&3] =
1890 				pheader->gl_texturenum[i][j - k];
1891 		}
1892 	}
1893 
1894 	return (void *)pskintype;
1895 }
1896 
1897 //=========================================================================
1898 
1899 /*
1900 =================
1901 Mod_LoadAliasModel
1902 =================
1903 */
Mod_LoadAliasModel(model_t * mod,void * buffer)1904 void Mod_LoadAliasModel (model_t *mod, void *buffer)
1905 {
1906 	int			i, j;
1907 	mdl_t			*pinmodel;
1908 	stvert_t		*pinstverts;
1909 	dtriangle_t		*pintriangles;
1910 	int			version, numframes, numskins;
1911 	int			size;
1912 	daliasframetype_t	*pframetype;
1913 	daliasskintype_t	*pskintype;
1914 	int			start, end, total;
1915 	char			*Name;
1916 
1917 	// HACK HACK HACK -- no fullbright colors, so make torches/flames full light
1918 
1919 	Name = strrchr (mod->name, '/');
1920 
1921 	if (Name)
1922 	{
1923 		int autobright = 0, abstart = 0;
1924 
1925 		++Name;
1926 
1927 		if (!strcmp (mod->name, "progs/flame.mdl") ||
1928 		    !strcmp (mod->name, "progs/flame2.mdl"))
1929 			mod->fullbright = true;		    // GLQuake compatibility
1930 		else if (!strcmp (mod->name, "progs/eyes.mdl"))
1931 			mod->eyes = true;
1932 		else if (!strcmp (mod->name, "progs/bolt.mdl"))
1933 			mod->bolt = true;
1934 		else if (!strcmp (mod->name, "progs/missile.mdl"))
1935 			mod->missile = true;
1936 		else if (!strcmp (mod->name, "progs/quaddama.mdl"))
1937 			mod->quaddama = true;
1938 		else if (!strcmp (mod->name, "progs/invulner.mdl"))
1939 			mod->invulner = true;
1940 		else if (!strncmp (Name, "flame", 5) ||
1941 			 !strcmp (Name, "newfire.mdl") ||   // For Kinn ...
1942 			 !strcmp (Name, "longtrch.mdl"))    // For Chapters ...
1943 			autobright = 255;
1944 		else if (!strncmp (Name, "lantern", 7) ||
1945 			 !strcmp (Name, "brazshrt.mdl") ||  // For Chapters ...
1946 			 !strcmp (Name, "braztall.mdl"))
1947 		{
1948 			mod->lantern = true;
1949 			autobright = 150;
1950 		}
1951 		else if (!strncmp (Name, "bolt", 4) ||	    // Bolts ...
1952 			 !strcmp (Name, "s_light.mdl"))
1953 		{
1954 			mod->autobright[abstart++] = 100;
1955 			autobright = 150;
1956 		}
1957 		else if (!strncmp (Name, "candle", 6))
1958 		{
1959 			mod->candle = true;
1960 			autobright = 125;
1961 		}
1962 		else if (!strcmp (&Name[1], "_g_key.mdl") ||// Keys ...
1963 			 !strcmp (&Name[1], "_s_key.mdl") ||
1964 			 !strcmp (Name, "bloodkey.mdl") ||
1965 			 !strcmp (Name, "catkey.mdl") ||
1966 			 !strcmp (Name, "spikekey.mdl") ||
1967 			 !strcmp (Name, "end1.mdl") ||
1968 			 !strcmp (Name, "end2.mdl") ||
1969 			 !strcmp (Name, "end3.mdl") ||
1970 			 !strcmp (Name, "end4.mdl"))
1971 			autobright = 125;
1972 
1973 		if (autobright)
1974 		{
1975 			for (i = abstart; i < AUTOBRIGHTS; ++i)
1976 				mod->autobright[i] = autobright;
1977 
1978 //			Con_DPrintf ("\002autobright ");
1979 //			Con_DPrintf ("%s (level %d)\n", mod->name, autobright);
1980 		}
1981 	}
1982 
1983 	start = Hunk_LowMark ();
1984 
1985 	mod_base = (byte *)buffer;
1986 	pinmodel = (mdl_t *)buffer;
1987 
1988 	// Check version+header is inside file buffer
1989 	Mod_ChkFileSize ("Mod_LoadAliasModel", "model header", 0, sizeof(int) + sizeof(mdl_t));
1990 
1991 	version = LittleLong (pinmodel->version);
1992 	if (version != ALIAS_VERSION)
1993 		Sys_Error ("Mod_LoadAliasModel: %s has wrong version number (%i should be %i)",
1994 				 mod->name, version, ALIAS_VERSION);
1995 
1996 //
1997 // allocate space for a working header, plus all the data except the frames,
1998 // skin and group info
1999 //
2000 	size = 	sizeof (aliashdr_t)
2001 			+ (LittleLong (pinmodel->numframes) - 1) *
2002 			sizeof (pheader->frames[0]);
2003 	pheader = Hunk_AllocName (size, loadname);
2004 
2005 	mod->flags = LittleLong (pinmodel->flags);
2006 
2007 //
2008 // endian-adjust and copy the data, starting with the alias model header
2009 //
2010 	pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
2011 	pheader->numskins = LittleLong (pinmodel->numskins);
2012 	pheader->skinwidth = LittleLong (pinmodel->skinwidth);
2013 	pheader->skinheight = LittleLong (pinmodel->skinheight);
2014 
2015 	if (pheader->skinheight > MAX_LBM_HEIGHT)
2016 		Sys_Error ("Mod_LoadAliasModel: model %s has a skin taller than %d (%d)", mod->name,
2017 				   MAX_LBM_HEIGHT, pheader->skinheight);
2018 
2019 	pheader->numverts = LittleLong (pinmodel->numverts);
2020 
2021 	if (pheader->numverts <= 0)
2022 		Sys_Error ("Mod_LoadAliasModel: model %s has no vertices", mod->name);
2023 
2024 	if (pheader->numverts > 1024)
2025 	{
2026 		// Old limit
2027 		Con_Printf ("\002Mod_LoadAliasModel: ");
2028 		Con_Printf ("excessive vertices (%d, normal max = %d) in %s\n", pheader->numverts, 1024, loadmodel->name);
2029 	}
2030 
2031 	if (pheader->numverts > MAXALIASVERTS)
2032 		Sys_Error ("Mod_LoadAliasModel: model %s has too many vertices (%d, max = %d)", mod->name, pheader->numverts, MAXALIASVERTS);
2033 
2034 	pheader->numtris = LittleLong (pinmodel->numtris);
2035 
2036 	if (pheader->numtris <= 0)
2037 		Sys_Error ("Mod_LoadAliasModel: model %s has no triangles", mod->name);
2038 
2039 	pheader->numframes = LittleLong (pinmodel->numframes);
2040 
2041 	if (pheader->numframes > MAXALIASFRAMES)
2042 	{
2043 		Con_Printf ("\002Mod_LoadAliasModel: ");
2044 		Con_Printf ("too many frames (%d, max = %d) in %s\n", pheader->numframes, MAXALIASFRAMES, loadmodel->name);
2045 		pheader->numframes = MAXALIASFRAMES; // Cap
2046 	}
2047 
2048 	numframes = pheader->numframes;
2049 	if (numframes < 1)
2050 		Sys_Error ("Mod_LoadAliasModel: invalid # of frames %d in %s", numframes, mod->name);
2051 
2052 	pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
2053 	mod->synctype = LittleLong (pinmodel->synctype);
2054 	mod->numframes = pheader->numframes;
2055 
2056 	for (i=0 ; i<3 ; i++)
2057 	{
2058 		pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
2059 		pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
2060 		pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
2061 	}
2062 
2063 
2064 //
2065 // load the skins
2066 //
2067 	pskintype = (daliasskintype_t *)&pinmodel[1];
2068 	pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype);
2069 
2070 	if (!mod->fullbright && !mod->autobright[0])
2071 	{
2072 		byte *skin = (byte *)((daliasskintype_t *)&pinmodel[1] + 1);
2073 		int  s = pheader->skinwidth * pheader->skinheight;
2074 		int  FullBrights, FullBrights2, Yellow, Blue;
2075 
2076 		Yellow = Blue = 0;
2077 
2078 		for (i = 0; i < s; ++i)
2079 		{
2080 			if (skin[i] >= 224 && skin[i] <= 254)
2081 			{
2082 				if (skin[i] >= 244 && skin[i] <= 246)
2083 					++Blue;
2084 				else
2085 					++Yellow;
2086 			}
2087 		}
2088 
2089 		for (i = 0; i < AUTOBRIGHTS; ++i)
2090 		{
2091 			// gl_autobright == 0 : GLQuake compatibility
2092 			// gl_autobright == 1 : default, count mostly yellow/red fullbrights
2093 			// gl_autobright == 2 : count all fullbrights
2094 			// gl_autobright == 3 : count all fullbrights, high intensity
2095 			if (i == 0)
2096 			{
2097 				FullBrights = Yellow;
2098 				FullBrights2 = Blue;
2099 			}
2100 			else
2101 			{
2102 				FullBrights = Yellow + Blue;
2103 				FullBrights2 = 0;
2104 			}
2105 
2106 			FullBrights *= 100.0 / s;
2107 			FullBrights2 *= 100.0 / s;
2108 
2109 			if (FullBrights > 75)
2110 				mod->autobright[i] = 150;
2111 			else if (FullBrights > 50)
2112 				mod->autobright[i] = 125;
2113 			else if (FullBrights2 > 75)
2114 				mod->autobright[i] = 100;
2115 
2116 			if (mod->autobright[i])
2117 			{
2118 //				Con_DPrintf ("\002autobright ");
2119 //				Con_DPrintf ("%s (type %d, level %d, fb %d, fb2 %d)\n", mod->name, i, mod->autobright[i], FullBrights, FullBrights2);
2120 			}
2121 		}
2122 	}
2123 
2124 //
2125 // load base s and t vertices
2126 //
2127 	pinstverts = (stvert_t *)pskintype;
2128 
2129 	// Check vertices are inside file buffer
2130 	Mod_ChkFileSize ("Mod_LoadAliasModel", "vertices", (byte *)pinstverts - mod_base, pheader->numverts * sizeof(stvert_t));
2131 
2132 	for (i=0 ; i<pheader->numverts ; i++)
2133 	{
2134 		stverts[i].onseam = LittleLong (pinstverts[i].onseam);
2135 		stverts[i].s = LittleLong (pinstverts[i].s);
2136 		stverts[i].t = LittleLong (pinstverts[i].t);
2137 	}
2138 
2139 //
2140 // load triangle lists
2141 //
2142 	pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
2143 
2144 	// Check triangles are inside file buffer
2145 	Mod_ChkFileSize ("Mod_LoadAliasModel", "triangles", (byte *)pintriangles - mod_base, pheader->numtris * sizeof(dtriangle_t));
2146 
2147 	for (i=0 ; i<pheader->numtris ; i++)
2148 	{
2149 		triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
2150 
2151 		for (j=0 ; j<3 ; j++)
2152 		{
2153 			triangles[i].vertindex[j] =
2154 					LittleLong (pintriangles[i].vertindex[j]);
2155 
2156 			if (triangles[i].vertindex[j] < 0 || triangles[i].vertindex[j] >= MAXALIASVERTS)
2157 				Sys_Error ("Mod_LoadAliasModel: invalid triangles[%d].vertindex[%d] (%d, max = %d) in %s", i, j, triangles[i].vertindex[j], MAXALIASVERTS, mod->name);
2158 		}
2159 	}
2160 
2161 //
2162 // load the frames
2163 //
2164 	posenum = 0;
2165 	pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
2166 
2167         // Nehahra: LordHavoc - doing proper bbox for model
2168 	aliasbboxmin[0] = aliasbboxmin[1] = aliasbboxmin[2] = 1000;
2169 	aliasbboxmax[0] = aliasbboxmax[1] = aliasbboxmax[2] = -1000;
2170 
2171 	for (i=0 ; i<numframes ; i++)
2172 	{
2173 		aliasframetype_t frametype;
2174 		char		 Str[256];
2175 
2176 		sprintf (Str, "frame %d", i);
2177 		Mod_ChkFileSize ("Mod_LoadAliasModel", Str, (byte *)pframetype - mod_base, sizeof(aliasframetype_t));
2178 
2179 		frametype = LittleLong (pframetype->type);
2180 
2181 		Mod_ChkType ("Mod_LoadAliasModel", "frametype", Str, frametype, ALIAS_SINGLE, ALIAS_GROUP);
2182 
2183 		if (frametype == ALIAS_SINGLE)
2184 		{
2185 			pframetype = (daliasframetype_t *)
2186 					Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
2187 		}
2188 		else
2189 		{
2190 			pframetype = (daliasframetype_t *)
2191 					Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
2192 		}
2193 	}
2194 
2195 	pheader->numposes = posenum;
2196 
2197 	mod->type = mod_alias;
2198 
2199 // FIXME: do this right
2200 //        mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
2201 //        mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
2202 
2203 // Nehahra: LordHavoc - Fixed :>
2204 	for (j = 0;j < 3;j++)
2205 	{
2206 		mod->mins[j] = aliasbboxmin[j] * pheader->scale[j] + pheader->scale_origin[j];
2207 		mod->maxs[j] = aliasbboxmax[j] * pheader->scale[j] + pheader->scale_origin[j];
2208 	}
2209 
2210 // Nehahra: End
2211 
2212 	//
2213 	// build the draw lists
2214 	//
2215 	GL_MakeAliasModelDisplayLists (mod, pheader);
2216 
2217 //
2218 // move the complete, relocatable alias model to the cache
2219 //
2220 	end = Hunk_LowMark ();
2221 	total = end - start;
2222 
2223 	Cache_Alloc (&mod->cache, total, loadname);
2224 	if (!mod->cache.data)
2225 		return;
2226 	memcpy (mod->cache.data, pheader, total);
2227 
2228 	Hunk_FreeToLowMark (start);
2229 }
2230 
2231 //=============================================================================
2232 
2233 /*
2234 =================
2235 Mod_LoadSpriteFrame
2236 =================
2237 */
Mod_LoadSpriteFrame(void * pin,mspriteframe_t ** ppframe,int framenum,int bytes)2238 void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, int bytes)
2239 {
2240 	dspriteframe_t	*pinframe;
2241 	mspriteframe_t	*pspriteframe;
2242 	int		i, width, height, size, origin[2];
2243 	unsigned short	*ppixout;
2244 	byte		*ppixin;
2245 	char		name[64], str[256];
2246 
2247 	pinframe = (dspriteframe_t *)pin;
2248 
2249 	// Check sprite frame is inside file buffer
2250 	sprintf (str, "frame %d", framenum);
2251 	Mod_ChkFileSize ("Mod_LoadSpriteFrame", str, (byte *)pinframe - mod_base, sizeof(dspriteframe_t));
2252 
2253 	width = LittleLong (pinframe->width);
2254 	height = LittleLong (pinframe->height);
2255 	size = width * height;
2256 
2257 	Mod_ChkFileSize ("Mod_LoadSpriteFrame", str, (byte *)(pinframe + 1) - mod_base, size);
2258 
2259 	pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);
2260 
2261 	Q_memset (pspriteframe, 0, sizeof (mspriteframe_t));
2262 
2263 	*ppframe = pspriteframe;
2264 
2265 	pspriteframe->width = width;
2266 	pspriteframe->height = height;
2267 	origin[0] = LittleLong (pinframe->origin[0]);
2268 	origin[1] = LittleLong (pinframe->origin[1]);
2269 
2270 	pspriteframe->up = origin[1];
2271 	pspriteframe->down = origin[1] - height;
2272 	pspriteframe->left = origin[0];
2273 	pspriteframe->right = width + origin[0];
2274 
2275 	if (size)
2276 	{
2277 		sprintf (name, "%s_%i", loadmodel->name, framenum);
2278 
2279 		if (bytes == 1)
2280 			pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true);
2281 		else
2282 			pspriteframe->gl_texturenum = GL_LoadTexture32 (name, width, height, (byte *)(pinframe + 1), true, true);
2283 	}
2284 
2285 	return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
2286 }
2287 
2288 
2289 /*
2290 =================
2291 Mod_LoadSpriteGroup
2292 =================
2293 */
Mod_LoadSpriteGroup(void * pin,mspriteframe_t ** ppframe,int framenum,int bytes)2294 void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum, int bytes)
2295 {
2296 	dspritegroup_t		*pingroup;
2297 	mspritegroup_t		*pspritegroup;
2298 	int			i, numframes;
2299 	dspriteinterval_t	*pin_intervals;
2300 	float			*poutintervals;
2301 	void			*ptemp;
2302 
2303 	pingroup = (dspritegroup_t *)pin;
2304 
2305 	numframes = LittleLong (pingroup->numframes);
2306 
2307 	pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
2308 				(numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
2309 
2310 	pspritegroup->numframes = numframes;
2311 
2312 	*ppframe = (mspriteframe_t *)pspritegroup;
2313 
2314 	pin_intervals = (dspriteinterval_t *)(pingroup + 1);
2315 
2316 	poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
2317 
2318 	pspritegroup->intervals = poutintervals;
2319 
2320 	for (i=0 ; i<numframes ; i++)
2321 	{
2322 		*poutintervals = LittleFloat (pin_intervals->interval);
2323 		if (*poutintervals <= 0.0)
2324 			Sys_Error ("Mod_LoadSpriteGroup: interval %f <= 0 in %s", *poutintervals, loadmodel->name);
2325 
2326 		poutintervals++;
2327 		pin_intervals++;
2328 	}
2329 
2330 	ptemp = (void *)pin_intervals;
2331 
2332 	for (i=0 ; i<numframes ; i++)
2333 	{
2334                 ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i, bytes);
2335 	}
2336 
2337 	return ptemp;
2338 }
2339 
2340 
2341 /*
2342 =================
2343 Mod_LoadSpriteModel
2344 =================
2345 */
Mod_LoadSpriteModel(model_t * mod,void * buffer)2346 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
2347 {
2348 	int			i;
2349 	int			version;
2350 	dsprite_t		*pin;
2351 	msprite_t		*psprite;
2352 	int			numframes;
2353 	int			size;
2354 	dspriteframetype_t	*pframetype;
2355         int			bytesperpixel = 1;
2356 
2357 	mod_base = (byte *)buffer;
2358 	pin = (dsprite_t *)buffer;
2359 
2360 	// Check version+header is inside file buffer
2361 	Mod_ChkFileSize ("Mod_LoadSpriteModel", "sprite header", 0, sizeof(int) + sizeof(dsprite_t));
2362 
2363 	version = LittleLong (pin->version);
2364 
2365         // Nehahra - LordHavoc: 32bit textures
2366         if (version != SPRITE_VERSION && version != SPRITE32_VERSION)
2367 		Sys_Error ("Mod_LoadSpriteModel: %s has wrong version number (%i should be %i or %i)", mod->name, version, SPRITE_VERSION, SPRITE32_VERSION);
2368 
2369         if ((nospr32.value) && (version == SPRITE32_VERSION))
2370 		Sys_Error("Mod_LoadSpriteModel: precaching spr32 with nospr32 cvar in %s!", mod->name);
2371 
2372 //        if (version == SPRITE32_VERSION)
2373 //		Con_DPrintf("Mod_LoadSpriteModel: WARNING: SPR32 HAS VERSION NUMBER2\nTHIS HAS BEEN DEPRECATED\n");
2374 
2375 	if (version == SPRITE32_VERSION)
2376 		bytesperpixel = 4;
2377 
2378 	numframes = LittleLong (pin->numframes);
2379 
2380 	size = sizeof (msprite_t) +	(numframes - 1) * sizeof (psprite->frames);
2381 
2382 	psprite = Hunk_AllocName (size, loadname);
2383 
2384 	mod->cache.data = psprite;
2385 
2386 	psprite->type = LittleLong (pin->type);
2387 	psprite->maxwidth = LittleLong (pin->width);
2388 	psprite->maxheight = LittleLong (pin->height);
2389 	psprite->beamlength = LittleFloat (pin->beamlength);
2390 	mod->synctype = LittleLong (pin->synctype);
2391 	psprite->numframes = numframes;
2392 
2393 	mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
2394 	mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
2395 	mod->mins[2] = -psprite->maxheight/2;
2396 	mod->maxs[2] = psprite->maxheight/2;
2397 
2398 //
2399 // load the frames
2400 //
2401 	if (numframes < 1)
2402 		Sys_Error ("Mod_LoadSpriteModel: invalid # of frames %d in %s", numframes, mod->name);
2403 
2404 	mod->numframes = numframes;
2405 
2406 	pframetype = (dspriteframetype_t *)(pin + 1);
2407 
2408 	for (i=0 ; i<numframes ; i++)
2409 	{
2410 		spriteframetype_t   frametype;
2411 		char		    Str[256];
2412 
2413 		sprintf (Str, "frame %d", i);
2414 		Mod_ChkFileSize ("Mod_LoadSpriteModel", Str, (byte *)pframetype - mod_base, sizeof(spriteframetype_t));
2415 
2416 		frametype = LittleLong (pframetype->type);
2417 		psprite->frames[i].type = frametype;
2418 
2419 		Mod_ChkType ("Mod_LoadSpriteModel", "frametype", Str, frametype, SPR_SINGLE, SPR_GROUP);
2420 
2421 		if (frametype == SPR_SINGLE)
2422 		{
2423 			pframetype = (dspriteframetype_t *)
2424 					Mod_LoadSpriteFrame (pframetype + 1,
2425                                                                                  &psprite->frames[i].frameptr, i, bytesperpixel);
2426 		}
2427 		else
2428 		{
2429 			pframetype = (dspriteframetype_t *)
2430 					Mod_LoadSpriteGroup (pframetype + 1,
2431                                                                                  &psprite->frames[i].frameptr, i, bytesperpixel);
2432 		}
2433 	}
2434 
2435 	mod->type = mod_sprite;
2436 }
2437 
2438 //=============================================================================
2439 
2440 /*
2441 ================
2442 Mod_Print
2443 ================
2444 */
Mod_Print(void)2445 void Mod_Print (void)
2446 {
2447 	int		i;
2448 	model_t	*mod;
2449 
2450 	Con_SafePrintf ("Cached models:\n");
2451 	for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
2452 	{
2453 		Con_SafePrintf ("%8p : %s\n",mod->cache.data, mod->name);
2454 	}
2455 
2456 	Con_SafePrintf ("\n%d models\n", mod_numknown);
2457 }
2458 
2459 
2460