1 /*
2 Copyright (C) 1997-2001 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 #include "gl_local.h"
23 
24 model_t	*loadmodel;
25 int		modfilelen;
26 
27 void Mod_LoadSpriteModel (model_t *mod, void *buffer);
28 void Mod_LoadBrushModel (model_t *mod, void *buffer);
29 void Mod_LoadAliasModel (model_t *mod, void *buffer);
30 model_t *Mod_LoadModel (model_t *mod, qboolean crash);
31 
32 byte	mod_novis[MAX_MAP_LEAFS/8];
33 
34 #define	MAX_MOD_KNOWN	512
35 model_t	mod_known[MAX_MOD_KNOWN];
36 int		mod_numknown;
37 
38 // the inline * models from the current map are kept seperate
39 model_t	mod_inline[MAX_MOD_KNOWN];
40 
41 int		registration_sequence;
42 
43 typedef struct {
44 	char	name[MAX_OSPATH];
45 	int	width;
46 	int	height;
47 } texSize_t;
48 
49 static texSize_t	r_texSizes[MAX_IMAGES];
50 static int		r_numTexSizes;
51 
52 int			numentitychars;
53 char		map_entitystring[MAX_MAP_ENTSTRING];
54 
55 byte	*mod_base;
56 
57 /*
58 =================
59 Mod_LoadEntityString
60 =================
61 */
Mod_LoadEntityString(lump_t * l)62 void Mod_LoadEntityString (lump_t *l)
63 {
64 	numentitychars = l->filelen;
65 	if (l->filelen > MAX_MAP_ENTSTRING)
66 		Sys_Error ("Map has too large entity lump");
67 
68 	memcpy (map_entitystring, mod_base + l->fileofs, l->filelen);
69 }
70 
CM_EntityString(void)71 char	*CM_EntityString (void)
72 {
73 	return map_entitystring;
74 }
75 
76 /*
77 ================
78 R_ParseLightEntities - BERSERK
79 
80 parses light entity string
81 ================
82 */
83 
R_ParseLightEntities(void)84 static void R_ParseLightEntities (void)
85 {
86 
87 	int			i;
88 	char		*entString;
89 	char		*buf, *tok;
90 	char		block[2048], *bl;
91 	vec3_t		origin, color;
92 	float		intensity;
93 
94 	//DONT LOAD MAP ETS
95 //	return;
96 
97 	entString = map_entitystring;
98 
99 	buf = CM_EntityString();
100 	while (1){
101 		tok = Com_ParseExt(&buf, true);
102 		if (!tok[0])
103 			break;			// End of data
104 
105 		if (Q_stricmp(tok, "{"))
106 			continue;		// Should never happen!
107 
108 		// Parse the text inside brackets
109 		block[0] = 0;
110 		do {
111 			tok = Com_ParseExt(&buf, false);
112 			if (!Q_stricmp(tok, "}"))
113 				break;		// Done
114 
115 			if (!tok[0])	// Newline
116 				Q_strcat(block, "\n", sizeof(block));
117 			else {			// Token
118 				Q_strcat(block, " ", sizeof(block));
119 				Q_strcat(block, tok, sizeof(block));
120 			}
121 		} while (buf);
122 
123 		// Now look for "classname"
124 		tok = strstr(block, "classname");
125 		if (!tok)
126 			continue;		// Not found
127 
128 		// Skip over "classname" and whitespace
129 		tok += strlen("classname");
130 		while (*tok && *tok == ' ')
131 			tok++;
132 
133 		// Next token must be "light"
134 		if (Q_strnicmp(tok, "light", 5))
135 			continue;		// Not "light"
136 
137 		// Finally parse the light entity
138 		VectorClear(origin);
139 		intensity = 0;
140 
141 		bl = block;
142 		while (1){
143 			tok = Com_ParseExt(&bl, true);
144 			if (!tok[0])
145 				break;		// End of data
146 
147 			if (!Q_stricmp("origin", tok)){
148 				for (i = 0; i < 3; i++){
149 					tok = Com_ParseExt(&bl, false);
150 					origin[i] = atof(tok);
151 				}
152 			}
153 			else if (!Q_stricmp("light", tok) || !Q_stricmp("_light", tok)){
154 				tok = Com_ParseExt(&bl, false);
155 				intensity = atof(tok);
156 			}
157 			else
158 				Com_SkipRestOfLine(&bl);
159 		}
160 
161 		if (!intensity)
162 			intensity = 150;
163 
164 		// Add it to the list
165 		if (r_numWorldLights == MAX_LIGHTS)
166 			break;
167 
168 		VectorCopy(origin, r_worldLights[r_numWorldLights].origin);
169 		r_worldLights[r_numWorldLights].intensity = intensity/2;
170 		r_worldLights[r_numWorldLights].surf = NULL;
171 		r_numWorldLights++;
172 	}
173 }
174 void GL_LightmapColor (msurface_t *surf, vec3_t color);
175 //only add one light per light surface
GL_AddSurfaceWorldLight(msurface_t * surf)176 void GL_AddSurfaceWorldLight (msurface_t *surf)
177 {
178 	int i, intensity;
179 	glpoly_t *poly;
180 	vec3_t origin = {0,0,0}, color = {0,0,0};
181 
182 	if (!(surf->texinfo->flags & SURF_LIGHT))
183 		return;
184 	if (r_numWorldLights == MAX_LIGHTS)
185 		return;
186 
187 	for (poly=surf->polys, i=0 ; poly ; poly=poly->next, i++)
188 		VectorAdd(origin, poly->center, origin);
189 
190 	VectorScale(origin, 1.0/(float)i, origin);
191 	VectorCopy(origin, r_worldLights[r_numWorldLights].origin);
192 
193 	intensity = surf->texinfo->value/2;
194 	if (intensity>200) intensity = 200;
195 	r_worldLights[r_numWorldLights].intensity = intensity;
196 
197 	r_worldLights[r_numWorldLights].surf = surf;
198 
199 	r_numWorldLights++;
200 }
201 
202 /*
203  =================
204  R_GetTexSize
205  =================
206 */
R_GetTexSize(char * name,mtexinfo_t * out)207 static void R_GetTexSize (char *name, mtexinfo_t *out)
208 {
209 	int			i;
210 	char		fullname[MAX_QPATH];
211 	miptex_t	*mt;
212 	rscript_t	*rs;
213 	int			*width, *height;
214 
215 	width = &out->texWidth;
216 	height = &out->texHeight;
217 
218 	// Look in the script file
219 	for (i = 0; i < r_numTexSizes; i++)
220 	{
221 		if (!Q_stricmp(r_texSizes[i].name, name))
222 		{
223 			*width = r_texSizes[i].width;
224 			*height = r_texSizes[i].height;
225 			return;
226 		}
227 	}
228 
229 
230 	out->script = rs = out->script = RS_FindScript(va("textures/%s",name) );
231 	if (rs && rs->picsize.enable)
232 	{
233 		if (r_numTexSizes < MAX_IMAGES)
234 		{
235 			strcpy(r_texSizes[r_numTexSizes].name, name);
236 			r_texSizes[r_numTexSizes].width = LittleLong(rs->picsize.width);
237 			r_texSizes[r_numTexSizes].height = LittleLong(rs->picsize.height);
238 			r_numTexSizes++;
239 		}
240 
241 		out->texWidth = rs->picsize.width;
242 		out->texHeight= rs->picsize.height;
243 	}
244 
245 	// Load it from disk, but also cache the width and height to avoid
246 	// reloading it during the map loading process if it's referenced
247 	// again later
248 	Com_sprintf(fullname, sizeof(fullname), "textures/%s.wal", name);
249 	ri.FS_LoadFile(fullname, (void **)&mt);
250 	if (mt)
251 	{
252 		if (r_numTexSizes < MAX_IMAGES)
253 		{
254 			strcpy(r_texSizes[r_numTexSizes].name, name);
255 			r_texSizes[r_numTexSizes].width = LittleLong(mt->width);
256 			r_texSizes[r_numTexSizes].height = LittleLong(mt->height);
257 			r_numTexSizes++;
258 		}
259 
260 		*width = LittleLong(mt->width);
261 		*height = LittleLong(mt->height);
262 
263 		ri.FS_FreeFile(mt);
264 		return;
265 	}
266 	else
267 	{
268 		image_t *img = GL_FindImage (va("textures/%s.wal", name), it_wall);
269 		if (img)
270 		{
271 			*width = LittleLong(img->width);
272 			*height = LittleLong(img->height);
273 			return;
274 		}
275 	}
276 	// This is not the best solution, but what could we do?
277 	*width = 64;
278 	*height = 64;
279 }
280 
281 /*
282 ===============
283 Mod_PointInLeaf
284 ===============
285 */
Mod_PointInLeaf(vec3_t p,model_t * model)286 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
287 {
288 	mnode_t		*node;
289 	float		d;
290 	cplane_t	*plane;
291 
292 	if (!model || !model->nodes)
293 		ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model");
294 
295 	node = model->nodes;
296 	while (1)
297 	{
298 		if (node->contents != -1)
299 			return (mleaf_t *)node;
300 
301 		plane = node->plane;
302 
303 		d = DotProduct (p,plane->normal) - plane->dist;
304 
305 		if (d > 0)
306 			node = node->children[0];
307 		else
308 			node = node->children[1];
309 	}
310 
311 	return NULL;	// never reached
312 }
313 
314 
315 /*
316 ===================
317 Mod_DecompressVis
318 ===================
319 */
Mod_DecompressVis(byte * in,model_t * model)320 byte *Mod_DecompressVis (byte *in, model_t *model)
321 {
322 	static byte	decompressed[MAX_MAP_LEAFS/8];
323 	int		c;
324 	byte	*out;
325 	int		row;
326 
327 	row = (model->vis->numclusters+7)>>3;
328 	out = decompressed;
329 
330 	if (!in)
331 	{	// no vis info, so make all visible
332 		while (row)
333 		{
334 			*out++ = 0xff;
335 			row--;
336 		}
337 		return decompressed;
338 	}
339 
340 	do
341 	{
342 		if (*in)
343 		{
344 			*out++ = *in++;
345 			continue;
346 		}
347 
348 		c = in[1];
349 		in += 2;
350 		while (c)
351 		{
352 			*out++ = 0;
353 			c--;
354 		}
355 	} while (out - decompressed < row);
356 
357 	return decompressed;
358 }
359 
360 /*
361 ==============
362 Mod_ClusterPVS
363 ==============
364 */
Mod_ClusterPVS(int cluster,model_t * model)365 byte *Mod_ClusterPVS (int cluster, model_t *model)
366 {
367 	if (cluster == -1 || !model->vis)
368 		return mod_novis;
369 	return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS],
370 		model);
371 }
372 
373 
374 //===============================================================================
375 
376 /*
377 ================
378 Mod_Modellist_f
379 ================
380 */
Mod_Modellist_f(void)381 void Mod_Modellist_f (void)
382 {
383 	int		i;
384 	model_t	*mod;
385 	int		total;
386 
387 	total = 0;
388 	ri.Con_Printf (PRINT_ALL,"Loaded models:\n");
389 	for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
390 	{
391 		if (!mod->name[0])
392 			continue;
393 		ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name);
394 		total += mod->extradatasize;
395 	}
396 	ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total);
397 }
398 
399 /*
400 ===============
401 Mod_Init
402 ===============
403 */
Mod_Init(void)404 void Mod_Init (void)
405 {
406 	memset (mod_novis, 0xff, sizeof(mod_novis));
407 }
408 
409 
410 
411 /*
412 ==================
413 Mod_ForName
414 
415 Loads in a model for the given name
416 ==================
417 */
418 
Get_ModelName(struct model_s * mod)419 char *Get_ModelName (struct model_s *mod)
420 {
421 	return mod->name;
422 }
423 
Mod_ForName(const char * name,qboolean crash)424 model_t *Mod_ForName (const char *name, qboolean crash)
425 {
426 	model_t	*mod;
427 	unsigned *buf;
428 	int		i;
429 
430 	if (!name[0])
431 		ri.Sys_Error (ERR_DROP, "Mod_ForName: NULL name");
432 
433 	//
434 	// inline models are grabbed only from worldmodel
435 	//
436 	if (name[0] == '*')
437 	{
438 		i = atoi(name+1);
439 		if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
440 			ri.Sys_Error (ERR_DROP, "bad inline model number");
441 		return &mod_inline[i];
442 	}
443 
444 	//
445 	// search the currently loaded models
446 	//
447 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
448 	{
449 		if (!mod->name[0])
450 			continue;
451 		if (!strcmp (mod->name, name) ) {
452 			if (mod->type == mod_alias) {
453 				// Make sure models scripts are definately reloaded between maps - MrG
454 				char rs[MAX_OSPATH];
455 				int i = 0;
456 				image_t *img;
457 
458 				img=mod->skins[i];
459 				while (img != NULL) {
460 					strcpy(rs,mod->skins[i]->name);
461 					rs[strlen(rs)-4]=0;
462 					mod->script[i] = RS_FindScript(rs);
463 					if (mod->script[i])
464 						RS_ReadyScript((rscript_t *)mod->script[i]);
465 					i++;
466 					img=mod->skins[i];
467 				}
468 			}
469 
470 			return mod;
471 		}
472 	}
473 
474 	//
475 	// find a free model slot spot
476 	//
477 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
478 	{
479 		if (!mod->name[0])
480 			break;	// free spot
481 	}
482 	if (i == mod_numknown)
483 	{
484 		if (mod_numknown == MAX_MOD_KNOWN)
485 			ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
486 		mod_numknown++;
487 	}
488 	strcpy (mod->name, name);
489 
490 	//
491 	// load the file
492 	//
493 	modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf);
494 	if (!buf)
495 	{
496 		if (crash)
497 			ri.Sys_Error (ERR_DROP, "Mod_NumForName: %s not found", mod->name);
498 		memset (mod->name, 0, sizeof(mod->name));
499 		return NULL;
500 	}
501 
502 	loadmodel = mod;
503 
504 	//
505 	// fill it in
506 	//
507 
508 
509 	// call the apropriate loader
510 
511 	switch (LittleLong(*(unsigned *)buf))
512 	{
513 	case IDALIASHEADER:
514 		loadmodel->extradata = Hunk_Begin (0x200000);
515 		Mod_LoadAliasModel (mod, buf);
516 		break;
517 
518 	case IDSPRITEHEADER:
519 		loadmodel->extradata = Hunk_Begin (0x10000);
520 		Mod_LoadSpriteModel (mod, buf);
521 		break;
522 
523 	case IDBSPHEADER:
524 		loadmodel->extradata = Hunk_Begin (0x1000000);
525 		Mod_LoadBrushModel (mod, buf);
526 		break;
527 
528 	default:
529 		ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name);
530 		break;
531 	}
532 
533 	loadmodel->extradatasize = Hunk_End ();
534 
535 	ri.FS_FreeFile (buf);
536 
537 	return mod;
538 }
539 
540 /*
541 ===============================================================================
542 
543 					BRUSHMODEL LOADING
544 
545 ===============================================================================
546 */
547 
548 
549 /*
550 =================
551 Mod_LoadLighting
552 =================
553 */
Mod_LoadLighting(lump_t * l)554 void Mod_LoadLighting (lump_t *l)
555 {
556 	if (!l->filelen)
557 	{
558 		loadmodel->lightdata = NULL;
559 		return;
560 	}
561 	loadmodel->lightdata = Hunk_Alloc ( l->filelen);
562 	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
563 }
564 
565 
566 /*
567 =================
568 Mod_LoadVisibility
569 =================
570 */
Mod_LoadVisibility(lump_t * l)571 void Mod_LoadVisibility (lump_t *l)
572 {
573 	int		i;
574 
575 	if (!l->filelen)
576 	{
577 		loadmodel->vis = NULL;
578 		return;
579 	}
580 	loadmodel->vis = Hunk_Alloc ( l->filelen);
581 	memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen);
582 
583 	loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters);
584 	for (i=0 ; i<loadmodel->vis->numclusters ; i++)
585 	{
586 		loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]);
587 		loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]);
588 	}
589 }
590 
591 
592 /*
593 =================
594 Mod_LoadVertexes
595 =================
596 */
Mod_LoadVertexes(lump_t * l)597 void Mod_LoadVertexes (lump_t *l)
598 {
599 	dvertex_t	*in;
600 	mvertex_t	*out;
601 	int			i, count;
602 
603 	in = (void *)(mod_base + l->fileofs);
604 	if (l->filelen % sizeof(*in))
605 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
606 	count = l->filelen / sizeof(*in);
607 	out = Hunk_Alloc ( count*sizeof(*out));
608 
609 	loadmodel->vertexes = out;
610 	loadmodel->numvertexes = count;
611 
612 	for ( i=0 ; i<count ; i++, in++, out++)
613 	{
614 		out->position[0] = LittleFloat (in->point[0]);
615 		out->position[1] = LittleFloat (in->point[1]);
616 		out->position[2] = LittleFloat (in->point[2]);
617 	}
618 }
619 
620 /*
621 =================
622 RadiusFromBounds
623 =================
624 */
RadiusFromBounds(vec3_t mins,vec3_t maxs)625 float RadiusFromBounds (vec3_t mins, vec3_t maxs)
626 {
627 	int		i;
628 	vec3_t	corner;
629 
630 	for (i=0 ; i<3 ; i++)
631 	{
632 		corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
633 	}
634 
635 	return VectorLength (corner);
636 }
637 
638 
639 /*
640 =================
641 Mod_LoadSubmodels
642 =================
643 */
Mod_LoadSubmodels(lump_t * l)644 void Mod_LoadSubmodels (lump_t *l)
645 {
646 	dmodel_t	*in;
647 	mmodel_t	*out;
648 	int			i, j, count;
649 
650 	in = (void *)(mod_base + l->fileofs);
651 	if (l->filelen % sizeof(*in))
652 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
653 	count = l->filelen / sizeof(*in);
654 	out = Hunk_Alloc ( count*sizeof(*out));
655 
656 	loadmodel->submodels = out;
657 	loadmodel->numsubmodels = count;
658 
659 	for ( i=0 ; i<count ; i++, in++, out++)
660 	{
661 		for (j=0 ; j<3 ; j++)
662 		{	// spread the mins / maxs by a pixel
663 			out->mins[j] = LittleFloat (in->mins[j]) - 1;
664 			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
665 			out->origin[j] = LittleFloat (in->origin[j]);
666 		}
667 		out->radius = RadiusFromBounds (out->mins, out->maxs);
668 		out->headnode = LittleLong (in->headnode);
669 		out->firstface = LittleLong (in->firstface);
670 		out->numfaces = LittleLong (in->numfaces);
671 	}
672 }
673 
674 /*
675 =================
676 Mod_LoadEdges
677 =================
678 */
Mod_LoadEdges(lump_t * l)679 void Mod_LoadEdges (lump_t *l)
680 {
681 	dedge_t *in;
682 	medge_t *out;
683 	int 	i, count;
684 
685 	in = (void *)(mod_base + l->fileofs);
686 	if (l->filelen % sizeof(*in))
687 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
688 	count = l->filelen / sizeof(*in);
689 	out = Hunk_Alloc ( (count + 1) * sizeof(*out));
690 
691 	loadmodel->edges = out;
692 	loadmodel->numedges = count;
693 
694 	for ( i=0 ; i<count ; i++, in++, out++)
695 	{
696 		out->v[0] = (unsigned short)LittleShort(in->v[0]);
697 		out->v[1] = (unsigned short)LittleShort(in->v[1]);
698 	}
699 }
700 
701 /*
702 =================
703 Mod_LoadTexinfo
704 =================
705 */
Mod_LoadTexinfo(lump_t * l)706 void Mod_LoadTexinfo (lump_t *l)
707 {
708 	texinfo_t *in;
709 	mtexinfo_t *out, *step;
710 	int 	i, j, count;
711 	char	name[MAX_QPATH];
712 	int		next;
713 
714 	in = (void *)(mod_base + l->fileofs);
715 	if (l->filelen % sizeof(*in))
716 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
717 	count = l->filelen / sizeof(*in);
718 	out = Hunk_Alloc ( count*sizeof(*out));
719 
720 	loadmodel->texinfo = out;
721 	loadmodel->numtexinfo = count;
722 
723 	for ( i=0 ; i<count ; i++, in++, out++)
724 	{
725 		for (j=0 ; j<8 ; j++)
726 			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
727 
728 		out->flags = LittleLong (in->flags);
729 		next = LittleLong (in->nexttexinfo);
730 		if (next > 0)
731 			out->next = loadmodel->texinfo + next;
732 		else
733 		    out->next = NULL;
734 
735 		//get light level
736 		out->value = in->value;
737 		R_GetTexSize(in->texture, out);
738 
739 		Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
740 		if (!(out->image = GL_FindImage (name, it_wall)))
741 		{
742 			ri.Con_Printf (PRINT_ALL, "Couldn't load %s\n", name);
743 			out->image = r_notexture;
744 		}
745 	}
746 
747 	// count animation frames
748 	for (i=0 ; i<count ; i++)
749 	{
750 		out = &loadmodel->texinfo[i];
751 		out->numframes = 1;
752 		for (step = out->next ; step && step != out ; step=step->next)
753 			out->numframes++;
754 	}
755 }
756 
757 /*
758 ================
759 CalcSurfaceExtents
760 
761 Fills in s->texturemins[] and s->extents[]
762 ================
763 */
CalcSurfaceExtents(msurface_t * s)764 void CalcSurfaceExtents (msurface_t *s)
765 {
766 	float	mins[2], maxs[2], val;
767 	int		i,j, e;
768 	mvertex_t	*v;
769 	mtexinfo_t	*tex;
770 	int		bmins[2], bmaxs[2];
771 
772 	mins[0] = mins[1] = 999999;
773 	maxs[0] = maxs[1] = -99999;
774 
775 	tex = s->texinfo;
776 
777 	for (i=0 ; i<s->numedges ; i++)
778 	{
779 		e = loadmodel->surfedges[s->firstedge+i];
780 		if (e >= 0)
781 			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
782 		else
783 			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
784 
785 		for (j=0 ; j<2 ; j++)
786 		{
787 			val = v->position[0] * tex->vecs[j][0] +
788 				v->position[1] * tex->vecs[j][1] +
789 				v->position[2] * tex->vecs[j][2] +
790 				tex->vecs[j][3];
791 			if (val < mins[j])
792 				mins[j] = val;
793 			if (val > maxs[j])
794 				maxs[j] = val;
795 		}
796 	}
797 
798 	for (i=0 ; i<2 ; i++)
799 	{
800 		bmins[i] = floor(mins[i]/16);
801 		bmaxs[i] = ceil(maxs[i]/16);
802 
803 		s->texturemins[i] = bmins[i] * 16;
804 		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
805 
806 //		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
807 //			ri.Sys_Error (ERR_DROP, "Bad surface extents");
808 	}
809 }
810 
811 
812 void GL_AddSurfaceWorldLight (msurface_t *surf);
813 void GL_FindPolyCenters (msurface_t *surf);
814 void GL_BuildPolygonFromSurface(msurface_t *fa);
815 void GL_CreateVertexLightmap (msurface_t *surf);
816 void GL_CreateSurfaceLightmap (msurface_t *surf);
817 void GL_EndBuildingLightmaps (void);
818 void GL_BeginBuildingLightmaps (model_t *m);
819 
820 /*
821 =================
822 Mod_LoadFaces
823 =================
824 */
825 
Mod_LoadFaces(lump_t * l)826 void Mod_LoadFaces (lump_t *l)
827 {
828 	dface_t		*in;
829 	msurface_t 	*out;
830 	int			i, j, count, surfnum;
831 	int			planenum, side;
832 	int			ti;
833 	qboolean	lit;
834 
835 	in = (void *)(mod_base + l->fileofs);
836 	if (l->filelen % sizeof(*in))
837 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
838 	count = l->filelen / sizeof(*in);
839 	out = Hunk_Alloc ( count*sizeof(*out));
840 
841 	loadmodel->surfaces = out;
842 	loadmodel->numsurfaces = count;
843 
844 	currentmodel = loadmodel;
845 
846 	GL_BeginBuildingLightmaps (loadmodel);
847 
848 	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
849 	{
850 		//refresh ent link...
851 		out->firstedge = LittleLong(in->firstedge);
852 		out->numedges = LittleShort(in->numedges);
853 		out->flags = 0;
854 		out->polys = NULL;
855 
856 		planenum = LittleShort(in->planenum);
857 		side = LittleShort(in->side);
858 		if (side)
859 			out->flags |= SURF_PLANEBACK;
860 
861 		out->plane = loadmodel->planes + planenum;
862 
863 		ti = LittleShort (in->texinfo);
864 		if (ti < 0 || ti >= loadmodel->numtexinfo)
865 			ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: bad texinfo number");
866 		out->texinfo = loadmodel->texinfo + ti;
867 
868 		CalcSurfaceExtents (out);
869 
870 	// lighting info
871 
872 		for (i=0 ; i<MAXLIGHTMAPS ; i++)
873 			out->styles[i] = in->styles[i];
874 		i = LittleLong(in->lightofs);
875 		if (i == -1)
876 		{
877 			out->samples = NULL;
878 		}
879 		else
880 		{
881 			out->samples = loadmodel->lightdata + i;
882 		}
883 
884 	// set the drawing flags
885 
886 		if (out->texinfo->flags & SURF_WARP)
887 		{
888 
889 			out->flags |= SURF_DRAWTURB;
890 			for (i=0 ; i<2 ; i++)
891 			{
892 				out->extents[i] = 16384;
893 				out->texturemins[i] = -8192;
894 			}
895 			GL_SubdivideSurface (out);	// cut up polygon for warps
896 		}
897 
898 		// create lightmaps and polygons
899 		if ( !(out->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP) ) )
900 		{
901 			GL_CreateSurfaceLightmap (out);
902 
903 		}
904 
905 		if (! (out->texinfo->flags & SURF_WARP) )
906 		{
907 			if(!out->texinfo->script)
908 			{
909 				GL_BuildPolygonFromSurface(out);
910 			}
911 			else
912 			{
913 				rscript_t *rs = (rscript_t *)out->texinfo->script;
914 
915 				if(rs->subdivide)
916 					GL_SubdivideLightmappedSurface(out, rs->subdivide);
917 				else
918 				{
919 					rscript_t *rs = (rscript_t *)out->texinfo->script;
920 
921 					if (rs->stage->texture != NULL)
922 						out->texinfo->image = rs->stage->texture;
923 					else if (rs->stage->anim_stage != NULL)
924 						out->texinfo->image = rs->stage->anim_stage->texture;
925 
926 					GL_BuildPolygonFromSurface(out);
927 				}
928 			}
929 		}
930 
931 		if (out->polys)
932 		{
933 			GL_CreateVertexLightmap(out);
934 			GL_FindPolyCenters(out);
935 		}
936 
937 		GL_AddSurfaceWorldLight(out);
938 	}
939 
940 	GL_EndBuildingLightmaps ();
941 }
942 
943 
944 /*
945 =================
946 Mod_SetParent
947 =================
948 */
Mod_SetParent(mnode_t * node,mnode_t * parent)949 void Mod_SetParent (mnode_t *node, mnode_t *parent)
950 {
951 	node->parent = parent;
952 	if (node->contents != -1)
953 		return;
954 	Mod_SetParent (node->children[0], node);
955 	Mod_SetParent (node->children[1], node);
956 }
957 
958 /*
959 =================
960 Mod_LoadNodes
961 =================
962 */
Mod_LoadNodes(lump_t * l)963 void Mod_LoadNodes (lump_t *l)
964 {
965 	int			i, j, count, p;
966 	dnode_t		*in;
967 	mnode_t 	*out;
968 
969 	in = (void *)(mod_base + l->fileofs);
970 	if (l->filelen % sizeof(*in))
971 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
972 	count = l->filelen / sizeof(*in);
973 	out = Hunk_Alloc ( count*sizeof(*out));
974 
975 	loadmodel->nodes = out;
976 	loadmodel->numnodes = count;
977 
978 	for ( i=0 ; i<count ; i++, in++, out++)
979 	{
980 		for (j=0 ; j<3 ; j++)
981 		{
982 			out->minmaxs[j] = LittleShort (in->mins[j]);
983 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
984 		}
985 
986 		p = LittleLong(in->planenum);
987 		out->plane = loadmodel->planes + p;
988 
989 		out->firstsurface = LittleShort (in->firstface);
990 		out->numsurfaces = LittleShort (in->numfaces);
991 		out->contents = -1;	// differentiate from leafs
992 
993 		for (j=0 ; j<2 ; j++)
994 		{
995 			p = LittleLong (in->children[j]);
996 			if (p >= 0)
997 				out->children[j] = loadmodel->nodes + p;
998 			else
999 				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
1000 		}
1001 	}
1002 
1003 	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
1004 }
1005 
1006 /*
1007 =================
1008 Mod_LoadLeafs
1009 =================
1010 */
Mod_LoadLeafs(lump_t * l)1011 void Mod_LoadLeafs (lump_t *l)
1012 {
1013 	dleaf_t 	*in;
1014 	mleaf_t 	*out;
1015 	int			i, j, count, p;
1016 	glpoly_t	*poly;
1017 
1018 	in = (void *)(mod_base + l->fileofs);
1019 	if (l->filelen % sizeof(*in))
1020 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1021 	count = l->filelen / sizeof(*in);
1022 	out = Hunk_Alloc ( count*sizeof(*out));
1023 
1024 	loadmodel->leafs = out;
1025 	loadmodel->numleafs = count;
1026 
1027 	for ( i=0 ; i<count ; i++, in++, out++)
1028 	{
1029 		for (j=0 ; j<3 ; j++)
1030 		{
1031 			out->minmaxs[j] = LittleShort (in->mins[j]);
1032 			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
1033 		}
1034 
1035 		p = LittleLong(in->contents);
1036 		out->contents = p;
1037 
1038 		out->cluster = LittleShort(in->cluster);
1039 		out->area = LittleShort(in->area);
1040 
1041 		out->firstmarksurface = loadmodel->marksurfaces +
1042 			LittleShort(in->firstleafface);
1043 		out->nummarksurfaces = LittleShort(in->numleaffaces);
1044 
1045 		// gl underwater warp
1046 		if (out->contents & MASK_WATER )
1047 		{
1048 			for (j=0 ; j<out->nummarksurfaces ; j++)
1049 			{
1050 				out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
1051 				for (poly = out->firstmarksurface[j]->polys ; poly ; poly=poly->next)
1052 					poly->flags |= SURF_UNDERWATER;
1053 			}
1054 		}
1055 	}
1056 }
1057 
1058 /*
1059 =================
1060 Mod_LoadMarksurfaces
1061 =================
1062 */
Mod_LoadMarksurfaces(lump_t * l)1063 void Mod_LoadMarksurfaces (lump_t *l)
1064 {
1065 	int		i, j, count;
1066 	short		*in;
1067 	msurface_t **out;
1068 
1069 	in = (void *)(mod_base + l->fileofs);
1070 	if (l->filelen % sizeof(*in))
1071 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1072 	count = l->filelen / sizeof(*in);
1073 	out = Hunk_Alloc ( count*sizeof(*out));
1074 
1075 	loadmodel->marksurfaces = out;
1076 	loadmodel->nummarksurfaces = count;
1077 
1078 	for ( i=0 ; i<count ; i++)
1079 	{
1080 		j = LittleShort(in[i]);
1081 		if (j < 0 ||  j >= loadmodel->numsurfaces)
1082 			ri.Sys_Error (ERR_DROP, "Mod_ParseMarksurfaces: bad surface number");
1083 		out[i] = loadmodel->surfaces + j;
1084 	}
1085 }
1086 
1087 /*
1088 =================
1089 Mod_LoadSurfedges
1090 =================
1091 */
Mod_LoadSurfedges(lump_t * l)1092 void Mod_LoadSurfedges (lump_t *l)
1093 {
1094 	int		i, count;
1095 	int		*in, *out;
1096 
1097 	in = (void *)(mod_base + l->fileofs);
1098 	if (l->filelen % sizeof(*in))
1099 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1100 	count = l->filelen / sizeof(*in);
1101 	if (count < 1 || count >= MAX_MAP_SURFEDGES)
1102 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: bad surfedges count in %s: %i",
1103 		loadmodel->name, count);
1104 
1105 	out = Hunk_Alloc ( count*sizeof(*out));
1106 
1107 	loadmodel->surfedges = out;
1108 	loadmodel->numsurfedges = count;
1109 
1110 	for ( i=0 ; i<count ; i++)
1111 		out[i] = LittleLong (in[i]);
1112 }
1113 
1114 
1115 /*
1116 =================
1117 Mod_LoadPlanes
1118 =================
1119 */
Mod_LoadPlanes(lump_t * l)1120 void Mod_LoadPlanes (lump_t *l)
1121 {
1122 	int			i, j;
1123 	cplane_t	*out;
1124 	dplane_t 	*in;
1125 	int			count;
1126 	int			bits;
1127 
1128 	in = (void *)(mod_base + l->fileofs);
1129 	if (l->filelen % sizeof(*in))
1130 		ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1131 
1132 	count = l->filelen / sizeof(*in);
1133 
1134 //original bug
1135 //	out = Hunk_Alloc ( count*2*sizeof(*out));
1136 	out = Hunk_Alloc ( count*sizeof(*out));
1137 
1138 	loadmodel->planes = out;
1139 	loadmodel->numplanes = count;
1140 
1141 	for ( i=0 ; i<count ; i++, in++, out++)
1142 	{
1143 		bits = 0;
1144 		for (j=0 ; j<3 ; j++)
1145 		{
1146 			out->normal[j] = LittleFloat (in->normal[j]);
1147 			if (out->normal[j] < 0)
1148 				bits |= 1<<j;
1149 		}
1150 
1151 		out->dist = LittleFloat (in->dist);
1152 		//out->type = LittleLong (in->type);
1153 		out->type = PlaneTypeForNormal(out->normal);
1154 		out->signbits = bits;
1155 	}
1156 }
1157 
1158 /*
1159 =================
1160 Mod_LoadBrushModel
1161 =================
1162 */
1163 
Mod_LoadBrushModel(model_t * mod,void * buffer)1164 void Mod_LoadBrushModel (model_t *mod, void *buffer)
1165 {
1166 	int			i;
1167 	dheader_t	*header;
1168 	mmodel_t 	*bm;
1169 	char		rs_name[MAX_OSPATH], tmp[16];		// rscript - MrG
1170 
1171 	// end
1172 	r_numWorldLights = 0;
1173 
1174 	loadmodel->type = mod_brush;
1175 	if (loadmodel != mod_known)
1176 		ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world");
1177 
1178 	header = (dheader_t *)buffer;
1179 
1180 	i = LittleLong (header->version);
1181 	if (i != BSPVERSION)
1182 		ri.Sys_Error (ERR_DROP, "Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
1183 
1184 // swap all the lumps
1185 	mod_base = (byte *)header;
1186 
1187 	for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
1188 		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
1189 
1190 
1191 	// rscript - MrG
1192 	RS_FreeUnmarked();
1193 		strcpy(tmp,loadmodel->name+5);
1194 		tmp[strlen(tmp)-4]=0;
1195 		Com_sprintf(rs_name,MAX_OSPATH,"scripts/maps/%s.rscript",tmp);
1196 	RS_ScanPathForScripts();		// load all found scripts
1197 	RS_LoadScript(rs_name);
1198 
1199 // load into heap
1200 	Mod_LoadEntityString (&header->lumps[LUMP_ENTITIES]);
1201 	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
1202 	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
1203 	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
1204 	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
1205 	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
1206 	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
1207 	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
1208 	Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]);
1209 	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
1210 	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
1211 	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
1212 	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
1213 	mod->numframes = 2;		// regular and alternate animation
1214 
1215 	RS_ReloadImageScriptLinks();
1216 	RS_LoadSpecialScripts();
1217 
1218 //
1219 // set up the submodels
1220 //
1221 	for (i=0 ; i<mod->numsubmodels ; i++)
1222 	{
1223 		model_t	*starmod;
1224 
1225 		bm = &mod->submodels[i];
1226 		starmod = &mod_inline[i];
1227 
1228 		*starmod = *loadmodel;
1229 
1230 		starmod->firstmodelsurface = bm->firstface;
1231 		starmod->nummodelsurfaces = bm->numfaces;
1232 		starmod->firstnode = bm->headnode;
1233 		if (starmod->firstnode >= loadmodel->numnodes)
1234 			ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i);
1235 
1236 		VectorCopy (bm->maxs, starmod->maxs);
1237 		VectorCopy (bm->mins, starmod->mins);
1238 		starmod->radius = bm->radius;
1239 
1240 		if (i == 0)
1241 			*loadmodel = *starmod;
1242 
1243 		starmod->numleafs = bm->visleafs;
1244 	}
1245 
1246 	R_ParseLightEntities();
1247 }
1248 
1249 /*
1250 ==============================================================================
1251 
1252 ALIAS MODELS
1253 
1254 ==============================================================================
1255 */
1256 
1257 /*
1258 =================
1259 Mod_LoadAliasModel
1260 =================
1261 */
Mod_LoadAliasModel(model_t * mod,void * buffer)1262 void Mod_LoadAliasModel (model_t *mod, void *buffer)
1263 {
1264 	int					i, j;
1265 	dmdl_t				*pinmodel, *pheader;
1266 	dstvert_t			*pinst, *poutst;
1267 	dtriangle_t			*pintri, *pouttri;
1268 	daliasframe_t		*pinframe, *poutframe;
1269 	int					*pincmd, *poutcmd;
1270 	int					version;
1271 
1272 	pinmodel = (dmdl_t *)buffer;
1273 
1274 	version = LittleLong (pinmodel->version);
1275 	if (version != ALIAS_VERSION)
1276 		ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
1277 				 mod->name, version, ALIAS_VERSION);
1278 
1279 	pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
1280 
1281 	// byte swap the header fields and sanity check
1282 	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
1283 		((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);
1284 
1285 	if (pheader->skinheight > MAX_LBM_HEIGHT)
1286 		ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
1287 				   MAX_LBM_HEIGHT);
1288 
1289 	if (pheader->num_xyz <= 0)
1290 		ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name);
1291 
1292 	if (pheader->num_xyz > MAX_VERTS)
1293 		ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name);
1294 
1295 	if (pheader->num_st <= 0)
1296 		ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name);
1297 
1298 	if (pheader->num_tris <= 0)
1299 		ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name);
1300 
1301 	if (pheader->num_frames <= 0)
1302 		ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name);
1303 
1304 //
1305 // load base s and t vertices (not used in gl version)
1306 //
1307 	pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
1308 	poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);
1309 
1310 	for (i=0 ; i<pheader->num_st ; i++)
1311 	{
1312 		poutst[i].s = LittleShort (pinst[i].s);
1313 		poutst[i].t = LittleShort (pinst[i].t);
1314 	}
1315 
1316 //
1317 // load triangle lists
1318 //
1319 	pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
1320 	pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
1321 
1322 	for (i=0 ; i<pheader->num_tris ; i++)
1323 	{
1324 		for (j=0 ; j<3 ; j++)
1325 		{
1326 			pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
1327 			pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
1328 		}
1329 	}
1330 
1331 //
1332 // load the frames
1333 //
1334 	for (i=0 ; i<pheader->num_frames ; i++)
1335 	{
1336 		pinframe = (daliasframe_t *) ((byte *)pinmodel
1337 			+ pheader->ofs_frames + i * pheader->framesize);
1338 		poutframe = (daliasframe_t *) ((byte *)pheader
1339 			+ pheader->ofs_frames + i * pheader->framesize);
1340 
1341 		memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
1342 		for (j=0 ; j<3 ; j++)
1343 		{
1344 			poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
1345 			poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
1346 		}
1347 		// verts are all 8 bit, so no swapping needed
1348 		memcpy (poutframe->verts, pinframe->verts,
1349 			pheader->num_xyz*sizeof(dtrivertx_t));
1350 
1351 	}
1352 
1353 	mod->type = mod_alias;
1354 
1355 	//
1356 	// load the glcmds
1357 	//
1358 	pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
1359 	poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
1360 	for (i=0 ; i<pheader->num_glcmds ; i++)
1361 		poutcmd[i] = LittleLong (pincmd[i]);
1362 
1363 
1364 	// register all skins
1365 	memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
1366 		pheader->num_skins*MAX_SKINNAME);
1367 
1368 	for (i=0 ; i<pheader->num_skins ; i++)
1369 	{
1370 		char rs[MAX_OSPATH];
1371 		mod->skins[i] = GL_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME
1372 			, it_skin);
1373 
1374 		strcpy(rs,(char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME);
1375 
1376 		rs[strlen(rs)-4]=0;
1377 		mod->script[i] = RS_FindScript(rs);
1378 		if (mod->script[i])
1379 			RS_ReadyScript((rscript_t *)mod->script[i]);
1380 	}
1381 
1382 	mod->mins[0] = -32;
1383 	mod->mins[1] = -32;
1384 	mod->mins[2] = -32;
1385 	mod->maxs[0] = 32;
1386 	mod->maxs[1] = 32;
1387 	mod->maxs[2] = 32;
1388 }
1389 
1390 /*
1391 ==============================================================================
1392 
1393 SPRITE MODELS
1394 
1395 ==============================================================================
1396 */
1397 
1398 /*
1399 =================
1400 Mod_LoadSpriteModel
1401 =================
1402 */
Mod_LoadSpriteModel(model_t * mod,void * buffer)1403 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
1404 {
1405 	dsprite_t	*sprin, *sprout;
1406 	int			i;
1407 
1408 	sprin = (dsprite_t *)buffer;
1409 	sprout = Hunk_Alloc (modfilelen);
1410 
1411 	sprout->ident = LittleLong (sprin->ident);
1412 	sprout->version = LittleLong (sprin->version);
1413 	sprout->numframes = LittleLong (sprin->numframes);
1414 
1415 	if (sprout->version != SPRITE_VERSION)
1416 		ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
1417 				 mod->name, sprout->version, SPRITE_VERSION);
1418 
1419 	if (sprout->numframes > MAX_MD2SKINS)
1420 		ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)",
1421 				 mod->name, sprout->numframes, MAX_MD2SKINS);
1422 
1423 	// byte swap everything
1424 	for (i=0 ; i<sprout->numframes ; i++)
1425 	{
1426 		sprout->frames[i].width = LittleLong (sprin->frames[i].width);
1427 		sprout->frames[i].height = LittleLong (sprin->frames[i].height);
1428 		sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x);
1429 		sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y);
1430 		memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
1431 		mod->skins[i] = GL_FindImage (sprout->frames[i].name,
1432 			it_sprite);
1433 	}
1434 
1435 	mod->type = mod_sprite;
1436 }
1437 
1438 //=============================================================================
1439 
1440 /*
1441 @@@@@@@@@@@@@@@@@@@@@
1442 R_BeginRegistration
1443 
1444 Specifies the model that will be used as the world
1445 @@@@@@@@@@@@@@@@@@@@@
1446 */
R_BeginRegistration(char * model)1447 void R_BeginRegistration (char *model)
1448 {
1449 	char	fullname[MAX_QPATH];
1450 	cvar_t	*flushmap;
1451 
1452 	registration_sequence++;
1453 	r_oldviewcluster = -1;		// force markleafs
1454 
1455 	Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model);
1456 
1457 	// explicitly free the old map if different
1458 	// this guarantees that mod_known[0] is the world map
1459 	flushmap = ri.Cvar_Get ("flushmap", "0", 0);
1460 	if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
1461 		Mod_Free (&mod_known[0]);
1462 	r_worldmodel = Mod_ForName(fullname, true);
1463 
1464 	r_viewcluster = -1;
1465 }
1466 
1467 
Mod_GetTris(short p1,short p2,dtriangle_t * side1,dmdl_t * hdr)1468 signed int *Mod_GetTris(short p1, short p2, dtriangle_t *side1, dmdl_t *hdr)
1469 {
1470 	dtriangle_t *tris = (dtriangle_t *)((unsigned char*)hdr + hdr->ofs_tris);
1471 	int i;
1472 
1473 	for (i=0; i<hdr->num_tris; i++, tris++)
1474 	{
1475 		if (tris == side1)
1476 			continue;
1477 
1478 		if (tris->index_xyz[0] == p2 && tris->index_xyz[1] == p1)
1479 			return i;
1480 		if (tris->index_xyz[1] == p2 && tris->index_xyz[2] == p1)
1481 			return i;
1482 		if (tris->index_xyz[2] == p2 && tris->index_xyz[0] == p1)
1483 			return i;
1484 	}
1485 	tris--;
1486 	return -1;
1487 }
1488 
Mod_FindSharedEdges(model_t * mod)1489 void Mod_FindSharedEdges(model_t *mod)
1490 {
1491 	dmdl_t		*hdr = (dmdl_t *)mod->extradata;
1492 	dtriangle_t *tris = (dtriangle_t *)((unsigned char*)hdr + hdr->ofs_tris);
1493 	int i,o;
1494 
1495 	mod->noshadow = false;
1496 
1497 	for (i=0; i<hdr->num_tris; i++)
1498 	{
1499 		mod->edge_tri[i][0] = Mod_GetTris(tris->index_xyz[0], tris->index_xyz[1], tris, hdr);
1500 		mod->edge_tri[i][1] = Mod_GetTris(tris->index_xyz[1], tris->index_xyz[2], tris, hdr);
1501 		mod->edge_tri[i][2] = Mod_GetTris(tris->index_xyz[2], tris->index_xyz[0], tris, hdr);
1502 
1503 		for (o=0; o<3; o++)
1504 			if (mod->edge_tri[i][o] == -1)
1505 				mod->noshadow = true;
1506 
1507 		tris++;
1508 	}
1509 }
1510 
1511 /*
1512 @@@@@@@@@@@@@@@@@@@@@
1513 R_RegisterModel
1514 
1515 @@@@@@@@@@@@@@@@@@@@@
1516 */
R_RegisterModel(char * name)1517 struct model_s *R_RegisterModel (char *name)
1518 {
1519 	model_t	*mod;
1520 	int		i;
1521 	dsprite_t	*sprout;
1522 	dmdl_t		*pheader;
1523 
1524 	mod = Mod_ForName (name, false);
1525 	if (mod)
1526 	{
1527 		mod->registration_sequence = registration_sequence;
1528 
1529 		// register any images used by the models
1530 		if (mod->type == mod_sprite)
1531 		{
1532 			sprout = (dsprite_t *)mod->extradata;
1533 			for (i=0 ; i<sprout->numframes ; i++)
1534 				mod->skins[i] = GL_FindImage (sprout->frames[i].name, it_sprite);
1535 		}
1536 		else if (mod->type == mod_alias)
1537 		{
1538 			pheader = (dmdl_t *)mod->extradata;
1539 			for (i=0 ; i<pheader->num_skins ; i++)
1540 				mod->skins[i] = GL_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
1541 //PGM
1542 			mod->numframes = pheader->num_frames;
1543 //PGM
1544 			Mod_FindSharedEdges(mod);
1545 		}
1546 		else if (mod->type == mod_brush)
1547 		{
1548 			for (i=0 ; i<mod->numtexinfo ; i++)
1549 				mod->texinfo[i].image->registration_sequence = registration_sequence;
1550 		}
1551 	}
1552 	return mod;
1553 }
1554 
1555 
1556 /*
1557 @@@@@@@@@@@@@@@@@@@@@
1558 R_EndRegistration
1559 
1560 @@@@@@@@@@@@@@@@@@@@@
1561 */
R_EndRegistration(void)1562 void R_EndRegistration (void)
1563 {
1564 	int		i;
1565 	model_t	*mod;
1566 
1567 	for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
1568 	{
1569 		if (!mod->name[0])
1570 			continue;
1571 		if (mod->registration_sequence != registration_sequence)
1572 		{	// don't need this model
1573 			Mod_Free (mod);
1574 		}
1575 	}
1576 
1577 	RS_UpdateRegistration();
1578 	GL_FreeUnusedImages ();
1579 }
1580 
1581 
1582 //=============================================================================
1583 
1584 
1585 /*
1586 ================
1587 Mod_Free
1588 ================
1589 */
Mod_Free(model_t * mod)1590 void Mod_Free (model_t *mod)
1591 {
1592 	Hunk_Free (mod->extradata);
1593 	memset (mod, 0, sizeof(*mod));
1594 }
1595 
1596 /*
1597 ================
1598 Mod_FreeAll
1599 ================
1600 */
Mod_FreeAll(void)1601 void Mod_FreeAll (void)
1602 {
1603 	int		i;
1604 
1605 	for (i=0 ; i<mod_numknown ; i++)
1606 	{
1607 		if (mod_known[i].extradatasize)
1608 			Mod_Free (&mod_known[i]);
1609 	}
1610 }
1611 
1612 
1613 /*
1614  =======================================================================
1615 
1616  FRAGMENT CLIPPING
1617 
1618  =======================================================================
1619 */
1620 
1621 #define	SIDE_FRONT				0
1622 #define	SIDE_BACK				1
1623 #define	SIDE_ON					2
1624 
1625 #define ON_EPSILON				0.1
1626 
1627 #define MAX_FRAGMENT_POINTS		128
1628 #define MAX_FRAGMENT_PLANES		6
1629 
1630 static qboolean			cm_markSplash;
1631 
1632 static int				cm_numMarkPoints;
1633 static int				cm_maxMarkPoints;
1634 static vec3_t			*cm_markPoints;
1635 static vec2_t			*cm_markTCoords;
1636 
1637 msurface_t				*cm_markSurface;
1638 
1639 static int				cm_numMarkFragments;
1640 static int				cm_maxMarkFragments;
1641 static markFragment_t	*cm_markFragments;
1642 
1643 static cplane_t			cm_markPlanes[MAX_FRAGMENT_PLANES];
1644 
1645 static int				cm_markCheckCount;
1646 
PlaneTypeForNormal(const vec3_t normal)1647 int PlaneTypeForNormal (const vec3_t normal)
1648 {
1649 	if (normal[0] == 1.0)
1650 		return 0;//PLANE_X;
1651 	if (normal[1] == 1.0)
1652 		return 1;//PLANE_Y;
1653 	if (normal[2] == 1.0)
1654 		return 2;//PLANE_Z;
1655  	return 3;//PLANE_NON_AXIAL;
1656 }
1657 
1658 /*
1659  =================
1660  Mod_ClipFragment
1661  =================
1662 */
1663 
worldVert(int i,msurface_t * surf)1664 float *worldVert (int i, msurface_t *surf)
1665 {
1666 	int e = r_worldmodel->surfedges[surf->firstedge + i];
1667 	if (e >= 0)
1668 		return &r_worldmodel->vertexes[r_worldmodel->edges[e].v[0]].position[0];
1669 	else
1670 		return &r_worldmodel->vertexes[r_worldmodel->edges[-e].v[1]].position[0];
1671 
1672 }
1673 
Mod_ClipFragment(int numPoints,vec3_t points,int stage,markFragment_t * mf)1674 static void Mod_ClipFragment (int numPoints, vec3_t points, int stage, markFragment_t *mf)
1675 {
1676 	int			i;
1677 	float		*p;
1678 	qboolean	frontSide;
1679 	vec3_t		front[MAX_FRAGMENT_POINTS];
1680 	int			f;
1681 	float		dist;
1682 	float		dists[MAX_FRAGMENT_POINTS];
1683 	int			sides[MAX_FRAGMENT_POINTS];
1684 	cplane_t	*plane;
1685 
1686 	if (numPoints > MAX_FRAGMENT_POINTS-2)
1687 		ri.Sys_Error(ERR_DROP, "Mod_ClipFragment: MAX_FRAGMENT_POINTS hit");
1688 
1689 	if (stage == MAX_FRAGMENT_PLANES)
1690 	{
1691 		// Fully clipped
1692 		if (numPoints > 2)
1693 		{
1694 			mf->numPoints = numPoints;
1695 			mf->firstPoint = cm_numMarkPoints;
1696 
1697 			if (cm_numMarkPoints + numPoints > cm_maxMarkPoints)
1698 				numPoints = cm_maxMarkPoints - cm_numMarkPoints;
1699 
1700 			for (i = 0, p = points; i < numPoints; i++, p += 3)
1701 				VectorCopy(p, cm_markPoints[cm_numMarkPoints+i]);
1702 
1703 			cm_numMarkPoints += numPoints;
1704 		}
1705 
1706 		return;
1707 	}
1708 
1709 	frontSide = false;
1710 
1711 	plane = &cm_markPlanes[stage];
1712 	for (i = 0, p = points; i < numPoints; i++, p += 3)
1713 	{
1714 		if (plane->type < 3)
1715 			dists[i] = dist = p[plane->type] - plane->dist;
1716 		else
1717 			dists[i] = dist = DotProduct(p, plane->normal) - plane->dist;
1718 
1719 		if (dist > ON_EPSILON)
1720 		{
1721 			frontSide = true;
1722 			sides[i] = SIDE_FRONT;
1723 		}
1724 		else if (dist < -ON_EPSILON)
1725 			sides[i] = SIDE_BACK;
1726 		else
1727 			sides[i] = SIDE_ON;
1728 	}
1729 
1730 	if (!frontSide)
1731 		return;		// Not clipped
1732 
1733 	// Clip it
1734 	dists[i] = dists[0];
1735 	sides[i] = sides[0];
1736 	VectorCopy(points, (points + (i*3)));
1737 
1738 	f = 0;
1739 
1740 	for (i = 0, p = points; i < numPoints; i++, p += 3)
1741 	{
1742 		switch (sides[i])
1743 		{
1744 		case SIDE_FRONT:
1745 			VectorCopy(p, front[f]);
1746 			f++;
1747 			break;
1748 		case SIDE_BACK:
1749 			break;
1750 		case SIDE_ON:
1751 			VectorCopy(p, front[f]);
1752 			f++;
1753 			break;
1754 		}
1755 
1756 		if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
1757 			continue;
1758 
1759 		dist = dists[i] / (dists[i] - dists[i+1]);
1760 
1761 		front[f][0] = p[0] + (p[3] - p[0]) * dist;
1762 		front[f][1] = p[1] + (p[4] - p[1]) * dist;
1763 		front[f][2] = p[2] + (p[5] - p[2]) * dist;
1764 
1765 		f++;
1766 	}
1767 
1768 	// Continue with planes
1769 	Mod_ClipFragment(f, front[0], stage+1, mf);
1770 }
1771 
1772 /*
1773  =================
1774  Mod_SplashFragTexCoords
1775  =================
1776 */
1777 
Mod_SplashFragTexCoords(vec3_t axis[3],const vec3_t origin,float radius,markFragment_t * fr)1778 void Mod_SplashFragTexCoords (vec3_t axis[3], const vec3_t origin, float radius, markFragment_t *fr)
1779 {
1780 	int j;
1781 	vec3_t v;
1782 
1783 	if (!cm_markSplash)
1784 		return;
1785 
1786 	for ( j = 0; j < fr->numPoints; j++ )
1787 	{
1788 		VectorSubtract (cm_markPoints[fr->firstPoint+j], origin, v );
1789 		cm_markTCoords[fr->firstPoint+j][0] = DotProduct ( v, axis[0] ) + 0.5f;
1790 		cm_markTCoords[fr->firstPoint+j][1] = DotProduct ( v, axis[1] ) + 0.5f;
1791 	}
1792 }
1793 
1794 /*
1795  =================
1796  Mod_ClipFragmentToSurface
1797  =================
1798 */
Mod_ClipFragmentToSurface(const vec3_t origin,const float radius,msurface_t * surf,const vec3_t normal)1799 static void Mod_ClipFragmentToSurface (const vec3_t origin, const float radius, msurface_t *surf, const vec3_t normal)
1800 {
1801 	qboolean planeback = surf->flags & SURF_PLANEBACK;
1802 	int				i;
1803 	float			d;
1804 	vec3_t			points[MAX_FRAGMENT_POINTS];
1805 	markFragment_t	*mf;
1806 	glpoly_t *bp, *p;
1807 	vec3_t axis[3];
1808 
1809 	if (cm_numMarkPoints >= cm_maxMarkPoints || cm_numMarkFragments >= cm_maxMarkFragments)
1810 		return;		// Already reached the limit somewhere else
1811 
1812 	if (cm_markSplash)
1813 	{
1814 		float dot, dist;
1815 		int sidebit;
1816 
1817 		cm_markSurface = surf;
1818 
1819 		//First check for facing planes
1820 		if ( surf->plane->type < 3 )
1821 			dist = origin[surf->plane->type] - surf->plane->dist;
1822 		else
1823 			dist = DotProduct (origin, surf->plane->normal) - surf->plane->dist;
1824 		// cull the polygon
1825 		if (dist > ON_EPSILON && (surf->flags & SURF_PLANEBACK) )
1826 				return;
1827 		else if (dist < -ON_EPSILON && !(surf->flags & SURF_PLANEBACK) )
1828 				return;
1829 
1830 		VectorNormalize2 ( cm_markSurface->plane->normal, axis[0] );
1831 		PerpendicularVector ( axis[1], axis[0] );
1832 		RotatePointAroundVector ( axis[2], axis[0], axis[1], 0 );
1833 		CrossProduct ( axis[0], axis[2], axis[1] );
1834 
1835 		for (i = 0; i < 3; i++)
1836 		{
1837 			dot = DotProduct(origin, axis[i]);
1838 
1839 			VectorCopy(axis[i], cm_markPlanes[i*2+0].normal);
1840 			cm_markPlanes[i*2+0].dist = dot - radius;
1841 			cm_markPlanes[i*2+0].type = PlaneTypeForNormal(cm_markPlanes[i*2+0].normal);
1842 
1843 			VectorNegate(axis[i], cm_markPlanes[i*2+1].normal);
1844 			cm_markPlanes[i*2+1].dist = -dot - radius;
1845 			cm_markPlanes[i*2+1].type = PlaneTypeForNormal(cm_markPlanes[i*2+1].normal);
1846 		}
1847 
1848 		VectorScale ( axis[1], 0.5f / radius, axis[0] );
1849 		VectorScale ( axis[2], 0.5f / radius, axis[1] );
1850 	}
1851 	else
1852 	{
1853 		float d = DotProduct(normal, surf->plane->normal);
1854 		if ((planeback && d > -0.75) || (!planeback && d < 0.75))
1855 			return;		// Greater than X degrees
1856 	}
1857 
1858 	for (i = 2; i < surf->numedges; i++)
1859 	{
1860 		mf = &cm_markFragments[cm_numMarkFragments];
1861 		mf->firstPoint = mf->numPoints = 0;
1862 
1863 		VectorCopy(worldVert(0, surf), points[0]);
1864 		VectorCopy(worldVert(i-1, surf), points[1]);
1865 		VectorCopy(worldVert(i, surf), points[2]);
1866 
1867 		Mod_ClipFragment(3, points[0], 0, mf);
1868 
1869 		if (mf->numPoints)
1870 		{
1871 			Mod_SplashFragTexCoords (axis, origin, radius, mf);
1872 			cm_numMarkFragments++;
1873 
1874 			if (cm_numMarkPoints >= cm_maxMarkPoints || cm_numMarkFragments >= cm_maxMarkFragments)
1875 				return;
1876 		}
1877 	}
1878 }
1879 
1880 /*
1881  =================
1882  Mod_RecursiveMarkFragments
1883  =================
1884 */
Mod_RecursiveMarkFragments(const vec3_t origin,const vec3_t normal,float radius,mnode_t * node)1885 static void Mod_RecursiveMarkFragments (const vec3_t origin, const vec3_t normal, float radius, mnode_t *node)
1886 {
1887 
1888 	int			i;
1889 	float		dist;
1890 	cplane_t	*plane;
1891 	msurface_t	*surf;
1892 
1893 	if (cm_numMarkPoints >= cm_maxMarkPoints || cm_numMarkFragments >= cm_maxMarkFragments)
1894 		return;		// Already reached the limit somewhere else
1895 
1896 	if (node->contents != -1)
1897 		return;
1898 
1899 	// Find which side of the node we are on
1900 	plane = node->plane;
1901 	if (plane->type < 3)
1902 		dist = origin[plane->type] - plane->dist;
1903 	else
1904 		dist = DotProduct(origin, plane->normal) - plane->dist;
1905 
1906 	// Go down the appropriate sides
1907 	if (dist > radius)
1908 	{
1909 		Mod_RecursiveMarkFragments(origin, normal, radius, node->children[0]);
1910 		return;
1911 	}
1912 	if (dist < -radius)
1913 	{
1914 		Mod_RecursiveMarkFragments(origin, normal, radius, node->children[1]);
1915 		return;
1916 	}
1917 	// Clip against each surface
1918 
1919 	surf = r_worldmodel->surfaces + node->firstsurface;
1920 	for (i=0 ; i<node->numsurfaces ; i++, surf++)
1921 	{
1922 		if (surf->checkCount == cm_markCheckCount)
1923 			continue;	// Already checked this surface in another node
1924 
1925 		if (surf->texinfo->flags & (SURF_SKY|SURF_WARP))//|SURF_TRANS33|SURF_TRANS66|(0x1000000)))
1926 			continue;
1927 
1928 		surf->checkCount = cm_markCheckCount;
1929 
1930 		Mod_ClipFragmentToSurface(origin, radius, surf, normal);
1931 	}
1932 	// Recurse down the children
1933 	Mod_RecursiveMarkFragments(origin, normal, radius, node->children[0]);
1934 	Mod_RecursiveMarkFragments(origin, normal, radius, node->children[1]);
1935 }
1936 
1937 /*
1938  =================
1939  Mod_SetTexCoords
1940  =================
1941 */
1942 
Mod_SetTexCoords(const vec3_t origin,vec3_t axis[3],float radius)1943 void Mod_SetTexCoords (const vec3_t origin, vec3_t axis[3], float radius)
1944 {
1945 	int i, j;
1946 	vec3_t newaxis[2], v;
1947 	markFragment_t *fr;
1948 
1949 	VectorScale ( axis[1], 0.5f / radius, newaxis[0] );
1950 	VectorScale ( axis[2], 0.5f / radius, newaxis[1] );
1951 
1952 	for ( i = 0, fr = cm_markFragments; i < cm_numMarkFragments; i++, fr++ )
1953 		for ( j = 0; j < fr->numPoints; j++ )
1954 		{
1955 			VectorSubtract (cm_markPoints[fr->firstPoint+j], origin, v );
1956 			cm_markTCoords[fr->firstPoint+j][0] = DotProduct ( v, newaxis[0] ) + 0.5f;
1957 			cm_markTCoords[fr->firstPoint+j][1] = DotProduct ( v, newaxis[1] ) + 0.5f;
1958 		}
1959 }
1960 
1961 /*
1962  =================
1963  Mod_MarkFragments
1964  =================
1965 */
1966 
Mod_MarkFragments(const vec3_t origin,vec3_t axis[3],float radius,int maxPoints,vec3_t * points,vec2_t * tcoords,int maxFragments,markFragment_t * fragments)1967 int Mod_MarkFragments (const vec3_t origin,  vec3_t axis[3], float radius, int maxPoints, vec3_t *points, vec2_t *tcoords, int maxFragments, markFragment_t *fragments)
1968 {
1969 
1970 	int		i;
1971 	float	dot;
1972 
1973 	if (!r_worldmodel || !r_worldmodel->nodes)
1974 		return 0;			// Map not loaded
1975 
1976 	cm_markCheckCount++;	// For multi-check avoidance
1977 
1978 	// Initialize fragments
1979 	cm_numMarkPoints = 0;
1980 	cm_maxMarkPoints = maxPoints;
1981 	cm_markPoints = points;
1982 
1983 	cm_markTCoords = tcoords;
1984 
1985 	cm_numMarkFragments = 0;
1986 	cm_maxMarkFragments = maxFragments;
1987 	cm_markFragments = fragments;
1988 
1989 	if (VectorCompare(axis[0], vec3_origin))
1990 		cm_markSplash = true;
1991 	else
1992 		cm_markSplash = false;
1993 
1994 	// Calculate clipping planes
1995 	if (!cm_markSplash)
1996 		for (i = 0; i < 3; i++)
1997 		{
1998 			dot = DotProduct(origin, axis[i]);
1999 
2000 			VectorCopy(axis[i], cm_markPlanes[i*2+0].normal);
2001 			cm_markPlanes[i*2+0].dist = dot - radius;
2002 			cm_markPlanes[i*2+0].type = PlaneTypeForNormal(cm_markPlanes[i*2+0].normal);
2003 
2004 			VectorNegate(axis[i], cm_markPlanes[i*2+1].normal);
2005 			cm_markPlanes[i*2+1].dist = -dot - radius;
2006 			cm_markPlanes[i*2+1].type = PlaneTypeForNormal(cm_markPlanes[i*2+1].normal);
2007 		}
2008 
2009 	// Clip against world geometry
2010 	Mod_RecursiveMarkFragments(origin, axis[0], radius, r_worldmodel->nodes);
2011 
2012 	if (!cm_markSplash)
2013 		Mod_SetTexCoords(origin, axis, radius);
2014 
2015 	return cm_numMarkFragments;
2016 }
2017