1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein single player GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
8 
9 RTCW SP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 RTCW SP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with RTCW SP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 // tr_models.c -- model loading and caching
30 
31 #include "tr_local.h"
32 
33 #define LL( x ) x = LittleLong( x )
34 
35 // Ridah
36 static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modName );
37 // done.
38 static qboolean R_LoadMD3( model_t *mod, int lod, void *buffer, const char *modName );
39 static qboolean R_LoadMDS( model_t *mod, void *buffer, const char *mod_name );
40 static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char *mod_name );
41 
42 extern cvar_t *r_compressModels;
43 extern cvar_t *r_exportCompressedModels;
44 extern cvar_t *r_buildScript;
45 
46 /*
47 ====================
48 R_RegisterMD3
49 ====================
50 */
R_RegisterMD3(const char * name,model_t * mod)51 qhandle_t R_RegisterMD3(const char *name, model_t *mod)
52 {
53 	union {
54 		unsigned *u;
55 		void *v;
56 	} buf;
57 	int			lod;
58 	int			ident = 0;
59 	qboolean	loaded = qfalse;
60 	int			numLoaded;
61 	char filename[MAX_QPATH], namebuf[MAX_QPATH+20];
62 	char *fext, defex[] = "md3";
63 
64 	numLoaded = 0;
65 
66 	strcpy(filename, name);
67 
68 	fext = strchr(filename, '.');
69 	if(!fext)
70 		fext = defex;
71 	else
72 	{
73 		*fext = '\0';
74 		fext++;
75 	}
76 
77 	for (lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod--)
78 	{
79 		if(lod)
80 			Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext);
81 		else
82 			Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext);
83 
84 
85 		if ( r_compressModels->integer ) {
86 			namebuf[strlen( namebuf ) - 1] = '3';  // try MD3 first
87 		} else {
88 			namebuf[strlen( namebuf ) - 1] = 'c';  // try MDC first
89 		}
90 
91 		ri.FS_ReadFile( namebuf, &buf.v );
92 		if ( !buf.u ) {
93 			if ( r_compressModels->integer ) {
94 				namebuf[strlen( namebuf ) - 1] = 'c';  // try MDC second
95 			} else {
96 				namebuf[strlen( namebuf ) - 1] = '3';  // try MD3 second
97 			}
98 			ri.FS_ReadFile( namebuf, (void **)&buf );
99 			if ( !buf.u ) {
100 				continue;
101 			}
102 		}
103 
104 		ident = LittleLong(* (unsigned *) buf.u);
105 		// Ridah, mesh compression
106 		if ( ident != MD3_IDENT && ident != MDC_IDENT ) {
107 			ri.Printf( PRINT_WARNING,"RE_RegisterModel: unknown fileid for %s\n", name );
108 			goto fail;
109 		}
110 
111 		if (ident == MD3_IDENT) {
112 			loaded = R_LoadMD3(mod, lod, buf.u, name);
113 		} else if (ident == MDC_IDENT) {
114 			loaded = R_LoadMDC( mod, lod, buf.u, name );
115 		}
116 		// done.
117 
118 		ri.FS_FreeFile(buf.v);
119 
120 		if(loaded)
121 		{
122 			mod->numLods++;
123 			numLoaded++;
124 		}
125 		else
126 			break;
127 	}
128 
129 	if(numLoaded)
130 	{
131 		// duplicate into higher lod spots that weren't
132 		// loaded, in case the user changes r_lodbias on the fly
133 		for(lod--; lod >= 0; lod--)
134 		{
135 			mod->numLods++;
136 			mod->mdv[lod] = mod->mdv[lod + 1];
137 		}
138 
139 		return mod->index;
140 	}
141 
142 #ifdef _DEBUG
143 	ri.Printf(PRINT_WARNING,"R_RegisterMD3: couldn't load %s\n", name);
144 #endif
145 
146 fail:
147 	// we still keep the model_t around, so if the model name is asked for
148 	// again, we won't bother scanning the filesystem
149 	mod->type = MOD_BAD;
150 	return 0;
151 }
152 
153 /*
154 ====================
155 R_RegisterMDS
156 ====================
157 */
R_RegisterMDS(const char * name,model_t * mod)158 qhandle_t R_RegisterMDS(const char *name, model_t *mod)
159 {
160 	union {
161 		unsigned *u;
162 		void *v;
163 	} buf;
164 	int	ident;
165 	qboolean loaded = qfalse;
166 
167 	ri.FS_ReadFile(name, (void **) &buf.v);
168 	if(!buf.u)
169 	{
170 		mod->type = MOD_BAD;
171 		return 0;
172 	}
173 
174 	ident = LittleLong(*(unsigned *)buf.u);
175 	if(ident == MDS_IDENT)
176 		loaded = R_LoadMDS(mod, buf.u, name);
177 
178 	ri.FS_FreeFile (buf.v);
179 
180 	if(!loaded)
181 	{
182 		ri.Printf(PRINT_WARNING,"R_RegisterMDS: couldn't load mds file %s\n", name);
183 		mod->type = MOD_BAD;
184 		return 0;
185 	}
186 
187 	return mod->index;
188 }
189 
190 /*
191 ====================
192 R_RegisterMDR
193 ====================
194 */
R_RegisterMDR(const char * name,model_t * mod)195 qhandle_t R_RegisterMDR(const char *name, model_t *mod)
196 {
197 	union {
198 		unsigned *u;
199 		void *v;
200 	} buf;
201 	int	ident;
202 	qboolean loaded = qfalse;
203 	int filesize;
204 
205 	filesize = ri.FS_ReadFile(name, (void **) &buf.v);
206 	if(!buf.u)
207 	{
208 		mod->type = MOD_BAD;
209 		return 0;
210 	}
211 
212 	ident = LittleLong(*(unsigned *)buf.u);
213 	if(ident == MDR_IDENT)
214 		loaded = R_LoadMDR(mod, buf.u, filesize, name);
215 
216 	ri.FS_FreeFile (buf.v);
217 
218 	if(!loaded)
219 	{
220 		ri.Printf(PRINT_WARNING,"R_RegisterMDR: couldn't load mdr file %s\n", name);
221 		mod->type = MOD_BAD;
222 		return 0;
223 	}
224 
225 	return mod->index;
226 }
227 
228 /*
229 ====================
230 R_RegisterIQM
231 ====================
232 */
R_RegisterIQM(const char * name,model_t * mod)233 qhandle_t R_RegisterIQM(const char *name, model_t *mod)
234 {
235 	union {
236 		unsigned *u;
237 		void *v;
238 	} buf;
239 	qboolean loaded = qfalse;
240 	int filesize;
241 
242 	filesize = ri.FS_ReadFile(name, (void **) &buf.v);
243 	if(!buf.u)
244 	{
245 		mod->type = MOD_BAD;
246 		return 0;
247 	}
248 
249 	loaded = R_LoadIQM(mod, buf.u, filesize, name);
250 
251 	ri.FS_FreeFile (buf.v);
252 
253 	if(!loaded)
254 	{
255 		ri.Printf(PRINT_WARNING,"R_RegisterIQM: couldn't load iqm file %s\n", name);
256 		mod->type = MOD_BAD;
257 		return 0;
258 	}
259 
260 	return mod->index;
261 }
262 
263 
264 typedef struct
265 {
266 	char *ext;
267 	qhandle_t (*ModelLoader)( const char *, model_t * );
268 } modelExtToLoaderMap_t;
269 
270 // Note that the ordering indicates the order of preference used
271 // when there are multiple models of different formats available
272 static modelExtToLoaderMap_t modelLoaders[ ] =
273 {
274 	{ "iqm", R_RegisterIQM },
275 	{ "mdr", R_RegisterMDR },
276 	{ "mds", R_RegisterMDS },
277 	{ "md3", R_RegisterMD3 },
278 	{ "mdc", R_RegisterMD3 }
279 };
280 
281 static int numModelLoaders = ARRAY_LEN(modelLoaders);
282 
283 /*
284 ** R_GetModelByHandle
285 */
R_GetModelByHandle(qhandle_t index)286 model_t *R_GetModelByHandle( qhandle_t index ) {
287 	model_t     *mod;
288 
289 	// out of range gets the defualt model
290 	if ( index < 1 || index >= tr.numModels ) {
291 		return tr.models[0];
292 	}
293 
294 	mod = tr.models[index];
295 
296 	return mod;
297 }
298 
299 //===============================================================================
300 
301 /*
302 ** R_AllocModel
303 */
R_AllocModel(void)304 model_t *R_AllocModel( void ) {
305 	model_t     *mod;
306 
307 	if ( tr.numModels == MAX_MOD_KNOWN ) {
308 		return NULL;
309 	}
310 
311 	mod = ri.Hunk_Alloc( sizeof( *tr.models[tr.numModels] ), h_low );
312 	mod->index = tr.numModels;
313 	tr.models[tr.numModels] = mod;
314 	tr.numModels++;
315 
316 	return mod;
317 }
318 
319 /*
320 ====================
321 RE_RegisterModel
322 
323 Loads in a model for the given name
324 
325 Zero will be returned if the model fails to load.
326 An entry will be retained for failed models as an
327 optimization to prevent disk rescanning if they are
328 asked for again.
329 ====================
330 */
RE_RegisterModel(const char * name)331 qhandle_t RE_RegisterModel( const char *name ) {
332 	model_t		*mod;
333 	qhandle_t	hModel;
334 	qboolean	orgNameFailed = qfalse;
335 	int			orgLoader = -1;
336 	int			i;
337 	char		localName[ MAX_QPATH ];
338 	const char	*ext;
339 	char		altName[ MAX_QPATH ];
340 
341 	if ( !name || !name[0] ) {
342 		// Ridah, disabled this, we can see models that can't be found because they won't be there
343 		//ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" );
344 		return 0;
345 	}
346 
347 	if ( strlen( name ) >= MAX_QPATH ) {
348 		ri.Printf( PRINT_ALL, "Model name exceeds MAX_QPATH\n" );
349 		return 0;
350 	}
351 
352 	//
353 	// search the currently loaded models
354 	//
355 	for ( hModel = 1 ; hModel < tr.numModels; hModel++ ) {
356 		mod = tr.models[hModel];
357 		if ( !strcmp( mod->name, name ) ) {
358 			if( mod->type == MOD_BAD ) {
359 				return 0;
360 			}
361 			return hModel;
362 		}
363 	}
364 
365 	// allocate a new model_t
366 
367 	if ( ( mod = R_AllocModel() ) == NULL ) {
368 		ri.Printf( PRINT_WARNING, "RE_RegisterModel: R_AllocModel() failed for '%s'\n", name );
369 		return 0;
370 	}
371 
372 	// only set the name after the model has been successfully loaded
373 	Q_strncpyz( mod->name, name, sizeof( mod->name ) );
374 
375 // GR - by default models are not tessellated
376 	mod->ATI_tess = qfalse;
377 // GR - check if can be tessellated...
378 //		make sure to tessellate model heads
379 	if ( strstr( name, "head" ) ) {
380 		mod->ATI_tess = qtrue;
381 	}
382 
383 	R_IssuePendingRenderCommands();
384 
385 	mod->type = MOD_BAD;
386 	mod->numLods = 0;
387 
388 	//
389 	// load the files
390 	//
391 	Q_strncpyz( localName, name, MAX_QPATH );
392 
393 	ext = COM_GetExtension( localName );
394 	if( *ext )
395 	{
396 		// Look for the correct loader and use it
397 		for( i = 0; i < numModelLoaders; i++ )
398 		{
399 			if( !Q_stricmp( ext, modelLoaders[ i ].ext ) )
400 			{
401 				// Load
402 				hModel = modelLoaders[ i ].ModelLoader( localName, mod );
403 				break;
404 			}
405 		}
406 		// A loader was found
407 		if( i < numModelLoaders )
408 		{
409 			if( !hModel )
410 			{
411 				// Loader failed, most likely because the file isn't there;
412 				// try again without the extension
413 				orgNameFailed = qtrue;
414 				orgLoader = i;
415 				COM_StripExtension( name, localName, MAX_QPATH );
416 			}
417 			else
418 			{
419 				// Something loaded
420 				return mod->index;
421 			}
422 		}
423 	}
424 
425 	// Try and find a suitable match using all
426 	// the model formats supported
427 	for( i = 0; i < numModelLoaders; i++ )
428 	{
429 		if (i == orgLoader)
430 			continue;
431 
432 		Com_sprintf( altName, sizeof (altName), "%s.%s", localName, modelLoaders[ i ].ext );
433 
434 		// Load
435 		hModel = modelLoaders[ i ].ModelLoader( altName, mod );
436 
437 		if( hModel )
438 		{
439 			if( orgNameFailed )
440 			{
441 				ri.Printf( PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n",
442 						name, altName );
443 			}
444 
445 			break;
446 		}
447 	}
448 
449 	return hModel;
450 }
451 
452 //-------------------------------------------------------------------------------
453 // Ridah, mesh compression
454 float r_anormals[NUMMDCVERTEXNORMALS][3] = {
455 #include "anorms256.h"
456 };
457 
458 /*
459 =============
460 R_MDC_GetVec
461 =============
462 */
R_MDC_GetVec(unsigned char anorm,vec3_t dir)463 void R_MDC_GetVec( unsigned char anorm, vec3_t dir ) {
464 	VectorCopy( r_anormals[anorm], dir );
465 }
466 
467 /*
468 =============
469 R_MDC_GetAnorm
470 =============
471 */
R_MDC_GetAnorm(const vec3_t dir)472 unsigned char R_MDC_GetAnorm( const vec3_t dir ) {
473 	int i, best_start_i[3] = { 0 }, next_start, next_end, best = 0;     // TTimo: init
474 	float best_diff, group_val, this_val, diff;
475 	float   *this_norm;
476 
477 	// find best Z match
478 
479 	if ( dir[2] > 0.097545f ) {
480 		next_start = 144;
481 		next_end = NUMMDCVERTEXNORMALS;
482 	} else
483 	{
484 		next_start = 0;
485 		next_end = 144;
486 	}
487 
488 	best_diff = 999;
489 	this_val = -999;
490 
491 	for ( i = next_start ; i < next_end ; i++ )
492 	{
493 		if ( r_anormals[i][2] == this_val ) {
494 			continue;
495 		} else {
496 			this_val = r_anormals[i][2];
497 		}
498 
499 		if ( ( diff = fabs( dir[2] - r_anormals[i][2] ) ) < best_diff ) {
500 			best_diff = diff;
501 			best_start_i[2] = i;
502 
503 		}
504 
505 		if ( next_start ) {
506 			if ( r_anormals[i][2] > dir[2] ) {
507 				break;  // we've gone passed the dir[2], so we can't possibly find a better match now
508 			}
509 		} else {
510 			if ( r_anormals[i][2] < dir[2] ) {
511 				break;  // we've gone passed the dir[2], so we can't possibly find a better match now
512 			}
513 		}
514 	}
515 
516 	best_diff = -999;
517 
518 	// find best match within the Z group
519 
520 	for ( i = best_start_i[2], group_val = r_anormals[i][2]; i < NUMMDCVERTEXNORMALS; i++ )
521 	{
522 		this_norm = r_anormals[i];
523 
524 		if ( this_norm[2] != group_val ) {
525 			break; // done checking the group
526 		}
527 		diff = DotProduct( dir, this_norm );
528 
529 		if ( diff > best_diff ) {
530 			best_diff = diff;
531 			best = i;
532 		}
533 	}
534 
535 	return (unsigned char)best;
536 }
537 
538 /*
539 =================
540 R_MDC_EncodeOfsVec
541 =================
542 */
R_MDC_EncodeXyzCompressed(const vec3_t vec,const vec3_t normal,mdcXyzCompressed_t * out)543 qboolean R_MDC_EncodeXyzCompressed( const vec3_t vec, const vec3_t normal, mdcXyzCompressed_t *out ) {
544 	mdcXyzCompressed_t retval;
545 	int i;
546 	unsigned char anorm;
547 
548 	retval.ofsVec = 0;
549 	for ( i = 0; i < 3; i++ ) {
550 		if ( fabs( vec[i] ) >= MDC_MAX_DIST ) {
551 			return qfalse;
552 		}
553 		retval.ofsVec += ( ( (int)fabs( ( vec[i] + MDC_DIST_SCALE * 0.5 ) * ( 1.0 / MDC_DIST_SCALE ) + MDC_MAX_OFS ) ) << ( i * MDC_BITS_PER_AXIS ) );
554 	}
555 	anorm = R_MDC_GetAnorm( normal );
556 	retval.ofsVec |= ( (int)anorm ) << 24;
557 
558 	*out = retval;
559 	return qtrue;
560 }
561 
562 /*
563 =================
564 R_LoadMDC
565 =================
566 */
R_LoadMDC(model_t * mod,int lod,void * buffer,const char * modName)567 static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modName )
568 {
569 	int             f, i, j, k;
570 
571 	mdcHeader_t         *mdcModel;
572 	md3Frame_t          *md3Frame;
573 	mdcSurface_t        *mdcSurf;
574 	md3Shader_t         *md3Shader;
575 	md3Triangle_t       *md3Tri;
576 	md3St_t             *md3st;
577 	md3XyzNormal_t      *md3xyz;
578 	mdcXyzCompressed_t  *mdcxyzComp;
579 	short               *mdcBaseFrame, *mdcCompFrame;
580 	mdcTag_t            *mdcTag;
581 	mdcTagName_t        *mdcTagName;
582 
583 	mdvModel_t     *mdvModel;
584 	mdvFrame_t     *frame;
585 	mdvSurface_t   *surf;//, *surface;
586 	int            *shaderIndex;
587 	glIndex_t	   *tri;
588 	mdvVertex_t    *v;
589 	mdvSt_t        *st;
590 	mdvTag_t       *tag;
591 	mdvTagName_t   *tagName;
592 
593 	int             version;
594 	int             size;
595 
596 	mdcModel = (mdcHeader_t *) buffer;
597 
598 	version = LittleLong(mdcModel->version);
599 	if(version != MDC_VERSION)
600 	{
601 		ri.Printf(PRINT_WARNING, "R_LoadMDC: %s has wrong version (%i should be %i)\n", modName, version, MDC_VERSION);
602 		return qfalse;
603 	}
604 
605 	mod->type = MOD_MESH;
606 	size = LittleLong(mdcModel->ofsEnd);
607 	mod->dataSize += size;
608 	mdvModel = mod->mdv[lod] = ri.Hunk_Alloc(sizeof(mdvModel_t), h_low);
609 
610 	LL( mdcModel->ident );
611 	LL( mdcModel->version );
612 	LL( mdcModel->numFrames );
613 	LL( mdcModel->numTags );
614 	LL( mdcModel->numSurfaces );
615 	LL( mdcModel->ofsFrames );
616 	LL( mdcModel->ofsTagNames );
617 	LL( mdcModel->ofsTags );
618 	LL( mdcModel->ofsSurfaces );
619 	LL( mdcModel->ofsEnd );
620 	LL( mdcModel->flags );
621 	LL( mdcModel->numSkins );
622 
623 	if( mdcModel->numFrames < 1 )
624 	{
625 		ri.Printf(PRINT_WARNING, "R_LoadMDC: %s has no frames\n", modName);
626 		return qfalse;
627 	}
628 
629 	// swap all the frames
630 	mdvModel->numFrames = mdcModel->numFrames;
631 	mdvModel->frames = frame = ri.Hunk_Alloc(sizeof(*frame) * mdcModel->numFrames, h_low);
632 
633 	md3Frame = (md3Frame_t *) ((byte *) mdcModel + mdcModel->ofsFrames);
634 	for(i = 0; i < mdcModel->numFrames; i++, frame++, md3Frame++)
635 	{
636 		frame->radius = LittleFloat(md3Frame->radius);
637 		if ( strstr( mod->name, "sherman" ) || strstr( mod->name, "mg42" ) )
638 		{
639 			frame->radius = 256;
640 			for ( j = 0 ; j < 3 ; j++ )
641 			{
642 				frame->bounds[0][j] = 128;
643 				frame->bounds[1][j] = -128;
644 				frame->localOrigin[j] = LittleFloat( md3Frame->localOrigin[j] );
645 			}
646 		}
647 		else
648 		{
649 			for(j = 0; j < 3; j++)
650 			{
651 				frame->bounds[0][j] = LittleFloat(md3Frame->bounds[0][j]);
652 				frame->bounds[1][j] = LittleFloat(md3Frame->bounds[1][j]);
653 				frame->localOrigin[j] = LittleFloat(md3Frame->localOrigin[j]);
654 			}
655 		}
656 	}
657 
658 	// swap all the tags
659 	mdvModel->numTags = mdcModel->numTags;
660 	mdvModel->tags = tag = ri.Hunk_Alloc(sizeof(*tag) * (mdcModel->numTags * mdcModel->numFrames), h_low);
661 
662 	mdcTag = (mdcTag_t *) ((byte *) mdcModel + mdcModel->ofsTags);
663 	for(i = 0; i < mdcModel->numTags * mdcModel->numFrames; i++, tag++, mdcTag++)
664 	{
665 		vec3_t angles;
666 		for(j = 0; j < 3; j++)
667 		{
668 			tag->origin[j] = LittleShort(mdcTag->xyz[j]) * MD3_XYZ_SCALE;
669 			angles[j] = LittleShort(mdcTag->angles[j]) * MDC_TAG_ANGLE_SCALE;
670 		}
671 		AnglesToAxis(angles, tag->axis);
672 	}
673 
674 
675 	mdvModel->tagNames = tagName = ri.Hunk_Alloc(sizeof(*tagName) * (mdcModel->numTags), h_low);
676 
677 	mdcTagName = (mdcTagName_t *) ((byte *) mdcModel + mdcModel->ofsTagNames);
678 	for(i = 0; i < mdcModel->numTags; i++, tagName++, mdcTagName++)
679 	{
680 		Q_strncpyz(tagName->name, mdcTagName->name, sizeof(tagName->name));
681 	}
682 
683 	// swap all the surfaces
684 	mdvModel->numSurfaces = mdcModel->numSurfaces;
685 	mdvModel->surfaces = surf = ri.Hunk_Alloc(sizeof(*surf) * mdcModel->numSurfaces, h_low);
686 
687 	mdcSurf = (mdcSurface_t *) ((byte *) mdcModel + mdcModel->ofsSurfaces);
688 	for(i = 0; i < mdcModel->numSurfaces; i++)
689 	{
690 		LL( mdcSurf->ident );
691 		LL( mdcSurf->flags );
692 		LL( mdcSurf->numBaseFrames );
693 		LL( mdcSurf->numCompFrames );
694 		LL( mdcSurf->numShaders );
695 		LL( mdcSurf->numTriangles );
696 		LL( mdcSurf->ofsTriangles );
697 		LL( mdcSurf->numVerts );
698 		LL( mdcSurf->ofsShaders );
699 		LL( mdcSurf->ofsSt );
700 		LL( mdcSurf->ofsXyzNormals );
701 		LL( mdcSurf->ofsXyzCompressed );
702 		LL( mdcSurf->ofsFrameBaseFrames );
703 		LL( mdcSurf->ofsFrameCompFrames );
704 		LL( mdcSurf->ofsEnd );
705 
706 		if(mdcSurf->numVerts >= SHADER_MAX_VERTEXES)
707 		{
708 			ri.Printf(PRINT_WARNING, "R_LoadMDC: %s has more than %i verts on %s (%i).\n",
709 				modName, SHADER_MAX_VERTEXES - 1, mdcSurf->name[0] ? mdcSurf->name : "a surface",
710 				mdcSurf->numVerts );
711 			return qfalse;
712 		}
713 		if(mdcSurf->numTriangles * 3 >= SHADER_MAX_INDEXES)
714 		{
715 			ri.Printf(PRINT_WARNING, "R_LoadMDC: %s has more than %i triangles on %s (%i).\n",
716 				modName, ( SHADER_MAX_INDEXES / 3 ) - 1, mdcSurf->name[0] ? mdcSurf->name : "a surface",
717 				mdcSurf->numTriangles );
718 			return qfalse;
719 		}
720 
721 		// change to surface identifier
722 		surf->surfaceType = SF_MDV;
723 
724 		// give pointer to model for Tess_SurfaceMDX
725 		surf->model = mdvModel;
726 
727 		// copy surface name
728 		Q_strncpyz(surf->name, mdcSurf->name, sizeof(surf->name));
729 
730 		// lowercase the surface name so skin compares are faster
731 		Q_strlwr(surf->name);
732 
733 		// strip off a trailing _1 or _2
734 		// this is a crutch for q3data being a mess
735 		j = strlen(surf->name);
736 		if(j > 2 && surf->name[j - 2] == '_')
737 		{
738 			surf->name[j - 2] = 0;
739 		}
740 
741 		// register the shaders
742 		surf->numShaderIndexes = mdcSurf->numShaders;
743 		surf->shaderIndexes = shaderIndex = ri.Hunk_Alloc(sizeof(*shaderIndex) * mdcSurf->numShaders, h_low);
744 
745 		md3Shader = (md3Shader_t *) ((byte *) mdcSurf + mdcSurf->ofsShaders);
746 		for(j = 0; j < mdcSurf->numShaders; j++, shaderIndex++, md3Shader++)
747 		{
748 			shader_t       *sh;
749 
750 			sh = R_FindShader(md3Shader->name, LIGHTMAP_NONE, qtrue);
751 			if(sh->defaultShader)
752 			{
753 				*shaderIndex = 0;
754 			}
755 			else
756 			{
757 				*shaderIndex = sh->index;
758 			}
759 		}
760 
761 		// swap all the triangles
762 		surf->numIndexes = mdcSurf->numTriangles * 3;
763 		surf->indexes = tri = ri.Hunk_Alloc(sizeof(*tri) * 3 * mdcSurf->numTriangles, h_low);
764 
765 		md3Tri = (md3Triangle_t *) ((byte *) mdcSurf + mdcSurf->ofsTriangles);
766 		for(j = 0; j < mdcSurf->numTriangles; j++, tri += 3, md3Tri++)
767 		{
768 			tri[0] = LittleLong(md3Tri->indexes[0]);
769 			tri[1] = LittleLong(md3Tri->indexes[1]);
770 			tri[2] = LittleLong(md3Tri->indexes[2]);
771 		}
772 
773 		// swap all the ST
774 		surf->st = st = ri.Hunk_Alloc(sizeof(*st) * mdcSurf->numVerts, h_low);
775 
776 		md3st = (md3St_t *) ((byte *) mdcSurf + mdcSurf->ofsSt);
777 		for(j = 0; j < mdcSurf->numVerts; j++, md3st++, st++)
778 		{
779 			st->st[0] = LittleFloat(md3st->st[0]);
780 			st->st[1] = LittleFloat(md3st->st[1]);
781 		}
782 
783 		// swap all the XyzNormals
784 		md3xyz = ( md3XyzNormal_t * )( (byte *)mdcSurf + mdcSurf->ofsXyzNormals );
785 		for ( j = 0 ; j < mdcSurf->numVerts * mdcSurf->numBaseFrames ; j++, md3xyz++ )
786 		{
787 			md3xyz->xyz[0] = LittleShort( md3xyz->xyz[0] );
788 			md3xyz->xyz[1] = LittleShort( md3xyz->xyz[1] );
789 			md3xyz->xyz[2] = LittleShort( md3xyz->xyz[2] );
790 
791 			md3xyz->normal = LittleShort( md3xyz->normal );
792 		}
793 
794 		// swap all the XyzCompressed
795 		mdcxyzComp = ( mdcXyzCompressed_t * )( (byte *)mdcSurf + mdcSurf->ofsXyzCompressed );
796 		for ( j = 0 ; j < mdcSurf->numVerts * mdcSurf->numCompFrames ; j++, mdcxyzComp++ )
797 		{
798 			LL( mdcxyzComp->ofsVec );
799 		}
800 
801 		// swap the frameBaseFrames
802 		mdcBaseFrame = ( short * )( (byte *)mdcSurf + mdcSurf->ofsFrameBaseFrames );
803 		for ( j = 0; j < mdcModel->numFrames; j++, mdcBaseFrame++ )
804 		{
805 			*mdcBaseFrame = LittleShort( *mdcBaseFrame );
806 		}
807 
808 		// swap the frameCompFrames
809 		mdcCompFrame = ( short * )( (byte *)mdcSurf + mdcSurf->ofsFrameCompFrames );
810 		for ( j = 0; j < mdcModel->numFrames; j++, mdcCompFrame++ )
811 		{
812 			*mdcCompFrame = LittleShort( *mdcCompFrame );
813 		}
814 
815 		// expand the base frames
816 		surf->numVerts = mdcSurf->numVerts;
817 		surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (mdcSurf->numVerts * mdcModel->numFrames), h_low);
818 
819 		mdcBaseFrame = ( short * )( (byte *)mdcSurf + mdcSurf->ofsFrameBaseFrames );
820 		for(j = 0; j < mdcModel->numFrames; j++, mdcBaseFrame++)
821 		{
822 			md3xyz = ( md3XyzNormal_t * )( (byte *)mdcSurf + mdcSurf->ofsXyzNormals ) + ( *mdcBaseFrame * surf->numVerts );
823 			for(k = 0; k < mdcSurf->numVerts; k++, md3xyz++, v++)
824 			{
825 				unsigned lat, lng;
826 				unsigned short normal;
827 				vec3_t fNormal;
828 
829 				v->xyz[0] = md3xyz->xyz[0] * MD3_XYZ_SCALE;
830 				v->xyz[1] = md3xyz->xyz[1] * MD3_XYZ_SCALE;
831 				v->xyz[2] = md3xyz->xyz[2] * MD3_XYZ_SCALE;
832 
833 				normal = md3xyz->normal;
834 
835 				lat = ( normal >> 8 ) & 0xff;
836 				lng = ( normal & 0xff );
837 				lat *= (FUNCTABLE_SIZE/256);
838 				lng *= (FUNCTABLE_SIZE/256);
839 
840 				// decode X as cos( lat ) * sin( long )
841 				// decode Y as sin( lat ) * sin( long )
842 				// decode Z as cos( long )
843 
844 				fNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
845 				fNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
846 				fNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
847 
848 				R_VaoPackNormal(v->normal, fNormal);
849 			}
850 		}
851 
852 		// expand the compressed frames
853 		if (mdcSurf->numCompFrames > 0)
854 		{
855 			mdcCompFrame = ( short * )( (byte *)mdcSurf + mdcSurf->ofsFrameCompFrames );
856 			for(j = 0; j < mdcModel->numFrames; j++, mdcCompFrame++)
857 			{
858 				if (*mdcCompFrame < 0)
859 					continue;
860 
861 				v = surf->verts + j * surf->numVerts;
862 				mdcxyzComp = ( mdcXyzCompressed_t * )( (byte *)mdcSurf + mdcSurf->ofsXyzCompressed ) + ( *mdcCompFrame * surf->numVerts );
863 
864 				for(k = 0; k < mdcSurf->numVerts; k++, mdcxyzComp++, v++)
865 				{
866 					vec3_t ofsVec;
867 					vec3_t fNormal;
868 
869 					R_MDC_DecodeXyzCompressed(mdcxyzComp->ofsVec, ofsVec, fNormal);
870 					VectorAdd( v->xyz, ofsVec, v->xyz );
871 
872 					R_VaoPackNormal(v->normal, fNormal);
873 				}
874 			}
875 		}
876 
877 		// calc tangent spaces
878 		{
879 			vec3_t *sdirs = ri.Z_Malloc(sizeof(*sdirs) * surf->numVerts * mdvModel->numFrames);
880 			vec3_t *tdirs = ri.Z_Malloc(sizeof(*tdirs) * surf->numVerts * mdvModel->numFrames);
881 
882 			for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
883 			{
884 				VectorClear(sdirs[j]);
885 				VectorClear(tdirs[j]);
886 			}
887 
888 			for(f = 0; f < mdvModel->numFrames; f++)
889 			{
890 				for(j = 0, tri = surf->indexes; j < surf->numIndexes; j += 3, tri += 3)
891 				{
892 					vec3_t sdir, tdir;
893 					const float *v0, *v1, *v2, *t0, *t1, *t2;
894 					glIndex_t index0, index1, index2;
895 
896 					index0 = surf->numVerts * f + tri[0];
897 					index1 = surf->numVerts * f + tri[1];
898 					index2 = surf->numVerts * f + tri[2];
899 
900 					v0 = surf->verts[index0].xyz;
901 					v1 = surf->verts[index1].xyz;
902 					v2 = surf->verts[index2].xyz;
903 
904 					t0 = surf->st[tri[0]].st;
905 					t1 = surf->st[tri[1]].st;
906 					t2 = surf->st[tri[2]].st;
907 
908 					R_CalcTexDirs(sdir, tdir, v0, v1, v2, t0, t1, t2);
909 
910 					VectorAdd(sdir, sdirs[index0], sdirs[index0]);
911 					VectorAdd(sdir, sdirs[index1], sdirs[index1]);
912 					VectorAdd(sdir, sdirs[index2], sdirs[index2]);
913 					VectorAdd(tdir, tdirs[index0], tdirs[index0]);
914 					VectorAdd(tdir, tdirs[index1], tdirs[index1]);
915 					VectorAdd(tdir, tdirs[index2], tdirs[index2]);
916 				}
917 			}
918 
919 			for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
920 			{
921 				vec3_t normal;
922 				vec4_t tangent;
923 
924 				VectorNormalize(sdirs[j]);
925 				VectorNormalize(tdirs[j]);
926 
927 				R_VaoUnpackNormal(normal, v->normal);
928 
929 				tangent[3] = R_CalcTangentSpace(tangent, NULL, normal, sdirs[j], tdirs[j]);
930 
931 				R_VaoPackTangent(v->tangent, tangent);
932 			}
933 
934 			ri.Free(sdirs);
935 			ri.Free(tdirs);
936 		}
937 
938 		// find the next surface
939 		mdcSurf = (mdcSurface_t *) ((byte *) mdcSurf + mdcSurf->ofsEnd);
940 		surf++;
941 	}
942 
943 	{
944 		srfVaoMdvMesh_t *vaoSurf;
945 
946 		mdvModel->numVaoSurfaces = mdvModel->numSurfaces;
947 		mdvModel->vaoSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vaoSurfaces) * mdvModel->numSurfaces, h_low);
948 
949 		vaoSurf = mdvModel->vaoSurfaces;
950 		surf = mdvModel->surfaces;
951 		for (i = 0; i < mdvModel->numSurfaces; i++, vaoSurf++, surf++)
952 		{
953 			uint32_t offset_xyz, offset_st, offset_normal, offset_tangent;
954 			uint32_t stride_xyz, stride_st, stride_normal, stride_tangent;
955 			uint32_t dataSize, dataOfs;
956 			uint8_t *data;
957 
958 			if (mdvModel->numFrames > 1)
959 			{
960 				// vertex animation, store texcoords first, then position/normal/tangents
961 				offset_st      = 0;
962 				offset_xyz     = surf->numVerts * sizeof(vec2_t);
963 				offset_normal  = offset_xyz + sizeof(vec3_t);
964 				offset_tangent = offset_normal + sizeof(int16_t) * 4;
965 				stride_st  = sizeof(vec2_t);
966 				stride_xyz = sizeof(vec3_t) + sizeof(int16_t) * 4;
967 				stride_xyz += sizeof(int16_t) * 4;
968 				stride_normal = stride_tangent = stride_xyz;
969 
970 				dataSize = offset_xyz + surf->numVerts * mdvModel->numFrames * stride_xyz;
971 			}
972 			else
973 			{
974 				// no animation, interleave everything
975 				offset_xyz     = 0;
976 				offset_st      = offset_xyz + sizeof(vec3_t);
977 				offset_normal  = offset_st + sizeof(vec2_t);
978 				offset_tangent = offset_normal + sizeof(int16_t) * 4;
979 				stride_xyz = offset_tangent + sizeof(int16_t) * 4;
980 				stride_st = stride_normal = stride_tangent = stride_xyz;
981 
982 				dataSize = surf->numVerts * stride_xyz;
983 			}
984 
985 
986 			data = ri.Z_Malloc(dataSize);
987 			dataOfs = 0;
988 
989 			if (mdvModel->numFrames > 1)
990 			{
991 				st = surf->st;
992 				for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
993 					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
994 					dataOfs += sizeof(st->st);
995 				}
996 
997 				v = surf->verts;
998 				for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ )
999 				{
1000 					// xyz
1001 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
1002 					dataOfs += sizeof(vec3_t);
1003 
1004 					// normal
1005 					memcpy(data + dataOfs, &v->normal, sizeof(int16_t) * 4);
1006 					dataOfs += sizeof(int16_t) * 4;
1007 
1008 					// tangent
1009 					memcpy(data + dataOfs, &v->tangent, sizeof(int16_t) * 4);
1010 					dataOfs += sizeof(int16_t) * 4;
1011 				}
1012 			}
1013 			else
1014 			{
1015 				v = surf->verts;
1016 				st = surf->st;
1017 				for ( j = 0; j < surf->numVerts; j++, v++, st++ )
1018 				{
1019 					// xyz
1020 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
1021 					dataOfs += sizeof(v->xyz);
1022 
1023 					// st
1024 					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
1025 					dataOfs += sizeof(st->st);
1026 
1027 					// normal
1028 					memcpy(data + dataOfs, &v->normal, sizeof(int16_t) * 4);
1029 					dataOfs += sizeof(int16_t) * 4;
1030 
1031 					// tangent
1032 					memcpy(data + dataOfs, &v->tangent, sizeof(int16_t) * 4);
1033 					dataOfs += sizeof(int16_t) * 4;
1034 				}
1035 			}
1036 
1037 			vaoSurf->surfaceType = SF_VAO_MDVMESH;
1038 			vaoSurf->mdvModel = mdvModel;
1039 			vaoSurf->mdvSurface = surf;
1040 			vaoSurf->numIndexes = surf->numIndexes;
1041 			vaoSurf->numVerts = surf->numVerts;
1042 
1043 			vaoSurf->vao = R_CreateVao(va("staticMD3Mesh_VAO '%s'", surf->name), data, dataSize, (byte *)surf->indexes, surf->numIndexes * sizeof(*surf->indexes), VAO_USAGE_STATIC);
1044 
1045 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].enabled = 1;
1046 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].enabled = 1;
1047 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].enabled = 1;
1048 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
1049 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].count = 3;
1050 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].count = 2;
1051 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].count = 4;
1052 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
1053 
1054 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].type = GL_FLOAT;
1055 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].type = GL_FLOAT;
1056 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].type = GL_SHORT;
1057 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = GL_SHORT;
1058 
1059 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].normalized = GL_FALSE;
1060 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].normalized = GL_FALSE;
1061 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].normalized = GL_TRUE;
1062 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
1063 
1064 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].offset = offset_xyz;
1065 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].offset = offset_st;
1066 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].offset = offset_normal;
1067 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].offset = offset_tangent;
1068 
1069 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].stride = stride_xyz;
1070 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].stride = stride_st;
1071 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].stride = stride_normal;
1072 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].stride = stride_tangent;
1073 
1074 			if (mdvModel->numFrames > 1)
1075 			{
1076 				vaoSurf->vao->attribs[ATTR_INDEX_POSITION2] = vaoSurf->vao->attribs[ATTR_INDEX_POSITION];
1077 				vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2  ] = vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ];
1078 				vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ] = vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ];
1079 
1080 				vaoSurf->vao->frameSize = stride_xyz    * surf->numVerts;
1081 			}
1082 
1083 			Vao_SetVertexPointers(vaoSurf->vao);
1084 
1085 			ri.Free(data);
1086 		}
1087 	}
1088 
1089 	return qtrue;
1090 }
1091 // done.
1092 //-------------------------------------------------------------------------------
1093 
1094 /*
1095 =================
1096 R_LoadMD3
1097 =================
1098 */
R_LoadMD3(model_t * mod,int lod,void * buffer,const char * modName)1099 static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modName)
1100 {
1101 	int             f, i, j;
1102 
1103 	md3Header_t    *md3Model;
1104 	md3Frame_t     *md3Frame;
1105 	md3Surface_t   *md3Surf;
1106 	md3Shader_t    *md3Shader;
1107 	md3Triangle_t  *md3Tri;
1108 	md3St_t        *md3st;
1109 	md3XyzNormal_t *md3xyz;
1110 	md3Tag_t       *md3Tag;
1111 
1112 	mdvModel_t     *mdvModel;
1113 	mdvFrame_t     *frame;
1114 	mdvSurface_t   *surf;//, *surface;
1115 	int            *shaderIndex;
1116 	glIndex_t	   *tri;
1117 	mdvVertex_t    *v;
1118 	mdvSt_t        *st;
1119 	mdvTag_t       *tag;
1120 	mdvTagName_t   *tagName;
1121 
1122 	int             version;
1123 	int             size;
1124 
1125 	qboolean fixRadius = qfalse;
1126 
1127 	md3Model = (md3Header_t *) buffer;
1128 
1129 	version = LittleLong(md3Model->version);
1130 	if(version != MD3_VERSION)
1131 	{
1132 		ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", modName, version, MD3_VERSION);
1133 		return qfalse;
1134 	}
1135 
1136 	mod->type = MOD_MESH;
1137 	size = LittleLong(md3Model->ofsEnd);
1138 	mod->dataSize += size;
1139 	// Ridah, convert to compressed format
1140 	if ( !r_compressModels->integer ) {
1141 		mdvModel = mod->mdv[lod] = ri.Hunk_Alloc(sizeof(mdvModel_t), h_low);
1142 	} else {
1143 		mdvModel = mod->mdv[lod] = ri.Hunk_AllocateTempMemory( size );
1144 	}
1145 	// done.
1146 
1147 	//memcpy( mod->md3[lod], buffer, LittleLong( pinmodel->ofsEnd ) );
1148 
1149 	LL(md3Model->ident);
1150 	LL(md3Model->version);
1151 	LL(md3Model->numFrames);
1152 	LL(md3Model->numTags);
1153 	LL(md3Model->numSurfaces);
1154 	LL(md3Model->ofsFrames);
1155 	LL(md3Model->ofsTags);
1156 	LL(md3Model->ofsSurfaces);
1157 	LL(md3Model->ofsEnd);
1158 
1159 	if(md3Model->numFrames < 1)
1160 	{
1161 		ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has no frames\n", modName);
1162 		return qfalse;
1163 	}
1164 
1165 	if ( strstr( mod->name,"sherman" ) || strstr( mod->name, "mg42" ) ) {
1166 		fixRadius = qtrue;
1167 	}
1168 
1169 	// swap all the frames
1170 	mdvModel->numFrames = md3Model->numFrames;
1171 	mdvModel->frames = frame = ri.Hunk_Alloc(sizeof(*frame) * md3Model->numFrames, h_low);
1172 
1173 	md3Frame = (md3Frame_t *) ((byte *) md3Model + md3Model->ofsFrames);
1174 	for(i = 0; i < md3Model->numFrames; i++, frame++, md3Frame++)
1175 	{
1176 		frame->radius = LittleFloat( md3Frame->radius );
1177 		if ( fixRadius ) {
1178 			frame->radius = 256;
1179 			for ( j = 0 ; j < 3 ; j++ ) {
1180 				frame->bounds[0][j] = 128;
1181 				frame->bounds[1][j] = -128;
1182 				frame->localOrigin[j] = LittleFloat( md3Frame->localOrigin[j] );
1183 			}
1184 		}
1185 		// Hack for Bug using plugin generated model
1186 		else if ( frame->radius == 1 ) {
1187 			frame->radius = 256;
1188 			for ( j = 0 ; j < 3 ; j++ ) {
1189 				frame->bounds[0][j] = 128;
1190 				frame->bounds[1][j] = -128;
1191 				frame->localOrigin[j] = LittleFloat( md3Frame->localOrigin[j] );
1192 			}
1193 		} else
1194 		{
1195 			for ( j = 0 ; j < 3 ; j++ ) {
1196 				frame->bounds[0][j] = LittleFloat( md3Frame->bounds[0][j] );
1197 				frame->bounds[1][j] = LittleFloat( md3Frame->bounds[1][j] );
1198 				frame->localOrigin[j] = LittleFloat( md3Frame->localOrigin[j] );
1199 			}
1200 		}
1201 	}
1202 
1203 	// swap all the tags
1204 	mdvModel->numTags = md3Model->numTags;
1205 	mdvModel->tags = tag = ri.Hunk_Alloc(sizeof(*tag) * (md3Model->numTags * md3Model->numFrames), h_low);
1206 
1207 	md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags);
1208 	for(i = 0; i < md3Model->numTags * md3Model->numFrames; i++, tag++, md3Tag++)
1209 	{
1210 		for(j = 0; j < 3; j++)
1211 		{
1212 			tag->origin[j] = LittleFloat(md3Tag->origin[j]);
1213 			tag->axis[0][j] = LittleFloat(md3Tag->axis[0][j]);
1214 			tag->axis[1][j] = LittleFloat(md3Tag->axis[1][j]);
1215 			tag->axis[2][j] = LittleFloat(md3Tag->axis[2][j]);
1216 		}
1217 	}
1218 
1219 
1220 	mdvModel->tagNames = tagName = ri.Hunk_Alloc(sizeof(*tagName) * (md3Model->numTags), h_low);
1221 
1222 	md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags);
1223 	for(i = 0; i < md3Model->numTags; i++, tagName++, md3Tag++)
1224 	{
1225 		Q_strncpyz(tagName->name, md3Tag->name, sizeof(tagName->name));
1226 	}
1227 
1228 	// swap all the surfaces
1229 	mdvModel->numSurfaces = md3Model->numSurfaces;
1230 	mdvModel->surfaces = surf = ri.Hunk_Alloc(sizeof(*surf) * md3Model->numSurfaces, h_low);
1231 
1232 	md3Surf = (md3Surface_t *) ((byte *) md3Model + md3Model->ofsSurfaces);
1233 	for(i = 0; i < md3Model->numSurfaces; i++)
1234 	{
1235 		LL(md3Surf->ident);
1236 		LL(md3Surf->flags);
1237 		LL(md3Surf->numFrames);
1238 		LL(md3Surf->numShaders);
1239 		LL(md3Surf->numTriangles);
1240 		LL(md3Surf->ofsTriangles);
1241 		LL(md3Surf->numVerts);
1242 		LL(md3Surf->ofsShaders);
1243 		LL(md3Surf->ofsSt);
1244 		LL(md3Surf->ofsXyzNormals);
1245 		LL(md3Surf->ofsEnd);
1246 
1247 		if(md3Surf->numVerts >= SHADER_MAX_VERTEXES)
1248 		{
1249 			ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has more than %i verts on %s (%i).\n",
1250 				modName, SHADER_MAX_VERTEXES - 1, md3Surf->name[0] ? md3Surf->name : "a surface",
1251 				md3Surf->numVerts );
1252 			return qfalse;
1253 		}
1254 		if(md3Surf->numTriangles * 3 >= SHADER_MAX_INDEXES)
1255 		{
1256 			ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has more than %i triangles on %s (%i).\n",
1257 				modName, ( SHADER_MAX_INDEXES / 3 ) - 1, md3Surf->name[0] ? md3Surf->name : "a surface",
1258 				md3Surf->numTriangles );
1259 			return qfalse;
1260 		}
1261 
1262 		// change to surface identifier
1263 		surf->surfaceType = SF_MDV;
1264 
1265 		// give pointer to model for Tess_SurfaceMDX
1266 		surf->model = mdvModel;
1267 
1268 		// copy surface name
1269 		Q_strncpyz(surf->name, md3Surf->name, sizeof(surf->name));
1270 
1271 		// lowercase the surface name so skin compares are faster
1272 		Q_strlwr(surf->name);
1273 
1274 		// strip off a trailing _1 or _2
1275 		// this is a crutch for q3data being a mess
1276 		j = strlen(surf->name);
1277 		if(j > 2 && surf->name[j - 2] == '_')
1278 		{
1279 			surf->name[j - 2] = 0;
1280 		}
1281 
1282 		// register the shaders
1283 		surf->numShaderIndexes = md3Surf->numShaders;
1284 		surf->shaderIndexes = shaderIndex = ri.Hunk_Alloc(sizeof(*shaderIndex) * md3Surf->numShaders, h_low);
1285 		md3Shader = (md3Shader_t *) ((byte *) md3Surf + md3Surf->ofsShaders);
1286 		for(j = 0; j < md3Surf->numShaders; j++, shaderIndex++, md3Shader++)
1287 		{
1288 			shader_t       *sh;
1289 
1290 			sh = R_FindShader(md3Shader->name, LIGHTMAP_NONE, qtrue);
1291 			if(sh->defaultShader)
1292 			{
1293 				*shaderIndex = 0;
1294 			}
1295 
1296 			else
1297 			{
1298 				*shaderIndex = sh->index;
1299 			}
1300 		}
1301 
1302 		// swap all the triangles
1303 		surf->numIndexes = md3Surf->numTriangles * 3;
1304 		surf->indexes = tri = ri.Hunk_Alloc(sizeof(*tri) * 3 * md3Surf->numTriangles, h_low);
1305 
1306 		md3Tri = (md3Triangle_t *) ((byte *) md3Surf + md3Surf->ofsTriangles);
1307 		for(j = 0; j < md3Surf->numTriangles; j++, tri += 3, md3Tri++)
1308 		{
1309 			tri[0] = LittleLong(md3Tri->indexes[0]);
1310 			tri[1] = LittleLong(md3Tri->indexes[1]);
1311 			tri[2] = LittleLong(md3Tri->indexes[2]);
1312 		}
1313 
1314 		// swap all the XyzNormals
1315 		surf->numVerts = md3Surf->numVerts;
1316 		surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (md3Surf->numVerts * md3Surf->numFrames), h_low);
1317 
1318 		md3xyz = (md3XyzNormal_t *) ((byte *) md3Surf + md3Surf->ofsXyzNormals);
1319 		for(j = 0; j < md3Surf->numVerts * md3Surf->numFrames; j++, md3xyz++, v++)
1320 		{
1321 			unsigned lat, lng;
1322 			unsigned short normal;
1323 			vec3_t fNormal;
1324 
1325 			v->xyz[0] = LittleShort(md3xyz->xyz[0]) * MD3_XYZ_SCALE;
1326 			v->xyz[1] = LittleShort(md3xyz->xyz[1]) * MD3_XYZ_SCALE;
1327 			v->xyz[2] = LittleShort(md3xyz->xyz[2]) * MD3_XYZ_SCALE;
1328 
1329 			normal = LittleShort(md3xyz->normal);
1330 
1331 			lat = ( normal >> 8 ) & 0xff;
1332 			lng = ( normal & 0xff );
1333 			lat *= (FUNCTABLE_SIZE/256);
1334 			lng *= (FUNCTABLE_SIZE/256);
1335 
1336 			// decode X as cos( lat ) * sin( long )
1337 			// decode Y as sin( lat ) * sin( long )
1338 			// decode Z as cos( long )
1339 
1340 			fNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
1341 			fNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
1342 			fNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
1343 
1344 			R_VaoPackNormal(v->normal, fNormal);
1345 		}
1346 
1347 		// swap all the ST
1348 		surf->st = st = ri.Hunk_Alloc(sizeof(*st) * md3Surf->numVerts, h_low);
1349 
1350 		md3st = (md3St_t *) ((byte *) md3Surf + md3Surf->ofsSt);
1351 		for(j = 0; j < md3Surf->numVerts; j++, md3st++, st++)
1352 		{
1353 			st->st[0] = LittleFloat(md3st->st[0]);
1354 			st->st[1] = LittleFloat(md3st->st[1]);
1355 		}
1356 
1357 		// calc tangent spaces
1358 		{
1359 			vec3_t *sdirs = ri.Z_Malloc(sizeof(*sdirs) * surf->numVerts * mdvModel->numFrames);
1360 			vec3_t *tdirs = ri.Z_Malloc(sizeof(*tdirs) * surf->numVerts * mdvModel->numFrames);
1361 
1362 			for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
1363 			{
1364 				VectorClear(sdirs[j]);
1365 				VectorClear(tdirs[j]);
1366 			}
1367 
1368 			for(f = 0; f < mdvModel->numFrames; f++)
1369 			{
1370 				for(j = 0, tri = surf->indexes; j < surf->numIndexes; j += 3, tri += 3)
1371 				{
1372 					vec3_t sdir, tdir;
1373 					const float *v0, *v1, *v2, *t0, *t1, *t2;
1374 					glIndex_t index0, index1, index2;
1375 
1376 					index0 = surf->numVerts * f + tri[0];
1377 					index1 = surf->numVerts * f + tri[1];
1378 					index2 = surf->numVerts * f + tri[2];
1379 
1380 					v0 = surf->verts[index0].xyz;
1381 					v1 = surf->verts[index1].xyz;
1382 					v2 = surf->verts[index2].xyz;
1383 
1384 					t0 = surf->st[tri[0]].st;
1385 					t1 = surf->st[tri[1]].st;
1386 					t2 = surf->st[tri[2]].st;
1387 
1388 					R_CalcTexDirs(sdir, tdir, v0, v1, v2, t0, t1, t2);
1389 
1390 					VectorAdd(sdir, sdirs[index0], sdirs[index0]);
1391 					VectorAdd(sdir, sdirs[index1], sdirs[index1]);
1392 					VectorAdd(sdir, sdirs[index2], sdirs[index2]);
1393 					VectorAdd(tdir, tdirs[index0], tdirs[index0]);
1394 					VectorAdd(tdir, tdirs[index1], tdirs[index1]);
1395 					VectorAdd(tdir, tdirs[index2], tdirs[index2]);
1396 				}
1397 			}
1398 
1399 			for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
1400 			{
1401 				vec3_t normal;
1402 				vec4_t tangent;
1403 
1404 				VectorNormalize(sdirs[j]);
1405 				VectorNormalize(tdirs[j]);
1406 
1407 				R_VaoUnpackNormal(normal, v->normal);
1408 
1409 				tangent[3] = R_CalcTangentSpace(tangent, NULL, normal, sdirs[j], tdirs[j]);
1410 
1411 				R_VaoPackTangent(v->tangent, tangent);
1412 			}
1413 
1414 			ri.Free(sdirs);
1415 			ri.Free(tdirs);
1416 		}
1417 
1418 		// find the next surface
1419 		md3Surf = (md3Surface_t *) ((byte *) md3Surf + md3Surf->ofsEnd);
1420 		surf++;
1421 	}
1422 
1423 	{
1424 		srfVaoMdvMesh_t *vaoSurf;
1425 
1426 		mdvModel->numVaoSurfaces = mdvModel->numSurfaces;
1427 		mdvModel->vaoSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vaoSurfaces) * mdvModel->numSurfaces, h_low);
1428 
1429 		vaoSurf = mdvModel->vaoSurfaces;
1430 		surf = mdvModel->surfaces;
1431 		for (i = 0; i < mdvModel->numSurfaces; i++, vaoSurf++, surf++)
1432 		{
1433 			uint32_t offset_xyz, offset_st, offset_normal, offset_tangent;
1434 			uint32_t stride_xyz, stride_st, stride_normal, stride_tangent;
1435 			uint32_t dataSize, dataOfs;
1436 			uint8_t *data;
1437 
1438 			if (mdvModel->numFrames > 1)
1439 			{
1440 				// vertex animation, store texcoords first, then position/normal/tangents
1441 				offset_st      = 0;
1442 				offset_xyz     = surf->numVerts * sizeof(vec2_t);
1443 				offset_normal  = offset_xyz + sizeof(vec3_t);
1444 				offset_tangent = offset_normal + sizeof(int16_t) * 4;
1445 				stride_st  = sizeof(vec2_t);
1446 				stride_xyz = sizeof(vec3_t) + sizeof(int16_t) * 4;
1447 				stride_xyz += sizeof(int16_t) * 4;
1448 				stride_normal = stride_tangent = stride_xyz;
1449 
1450 				dataSize = offset_xyz + surf->numVerts * mdvModel->numFrames * stride_xyz;
1451 			}
1452 			else
1453 			{
1454 				// no animation, interleave everything
1455 				offset_xyz     = 0;
1456 				offset_st      = offset_xyz + sizeof(vec3_t);
1457 				offset_normal  = offset_st + sizeof(vec2_t);
1458 				offset_tangent = offset_normal + sizeof(int16_t) * 4;
1459 				stride_xyz = offset_tangent + sizeof(int16_t) * 4;
1460 				stride_st = stride_normal = stride_tangent = stride_xyz;
1461 
1462 				dataSize = surf->numVerts * stride_xyz;
1463 			}
1464 
1465 
1466 			data = ri.Z_Malloc(dataSize);
1467 			dataOfs = 0;
1468 
1469 			if (mdvModel->numFrames > 1)
1470 			{
1471 				st = surf->st;
1472 				for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
1473 					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
1474 					dataOfs += sizeof(st->st);
1475 				}
1476 
1477 				v = surf->verts;
1478 				for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ )
1479 				{
1480 					// xyz
1481 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
1482 					dataOfs += sizeof(vec3_t);
1483 
1484 					// normal
1485 					memcpy(data + dataOfs, &v->normal, sizeof(int16_t) * 4);
1486 					dataOfs += sizeof(int16_t) * 4;
1487 
1488 					// tangent
1489 					memcpy(data + dataOfs, &v->tangent, sizeof(int16_t) * 4);
1490 					dataOfs += sizeof(int16_t) * 4;
1491 				}
1492 			}
1493 			else
1494 			{
1495 				v = surf->verts;
1496 				st = surf->st;
1497 				for ( j = 0; j < surf->numVerts; j++, v++, st++ )
1498 				{
1499 					// xyz
1500 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
1501 					dataOfs += sizeof(v->xyz);
1502 
1503 					// st
1504 					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
1505 					dataOfs += sizeof(st->st);
1506 
1507 					// normal
1508 					memcpy(data + dataOfs, &v->normal, sizeof(int16_t) * 4);
1509 					dataOfs += sizeof(int16_t) * 4;
1510 
1511 					// tangent
1512 					memcpy(data + dataOfs, &v->tangent, sizeof(int16_t) * 4);
1513 					dataOfs += sizeof(int16_t) * 4;
1514 				}
1515 			}
1516 
1517 			vaoSurf->surfaceType = SF_VAO_MDVMESH;
1518 			vaoSurf->mdvModel = mdvModel;
1519 			vaoSurf->mdvSurface = surf;
1520 			vaoSurf->numIndexes = surf->numIndexes;
1521 			vaoSurf->numVerts = surf->numVerts;
1522 
1523 			vaoSurf->vao = R_CreateVao(va("staticMD3Mesh_VAO '%s'", surf->name), data, dataSize, (byte *)surf->indexes, surf->numIndexes * sizeof(*surf->indexes), VAO_USAGE_STATIC);
1524 
1525 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].enabled = 1;
1526 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].enabled = 1;
1527 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].enabled = 1;
1528 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
1529 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].count = 3;
1530 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].count = 2;
1531 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].count = 4;
1532 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
1533 
1534 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].type = GL_FLOAT;
1535 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].type = GL_FLOAT;
1536 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].type = GL_SHORT;
1537 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = GL_SHORT;
1538 
1539 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].normalized = GL_FALSE;
1540 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].normalized = GL_FALSE;
1541 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].normalized = GL_TRUE;
1542 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
1543 
1544 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].offset = offset_xyz;
1545 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].offset = offset_st;
1546 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].offset = offset_normal;
1547 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].offset = offset_tangent;
1548 
1549 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].stride = stride_xyz;
1550 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].stride = stride_st;
1551 			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].stride = stride_normal;
1552 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].stride = stride_tangent;
1553 
1554 			if (mdvModel->numFrames > 1)
1555 			{
1556 				vaoSurf->vao->attribs[ATTR_INDEX_POSITION2] = vaoSurf->vao->attribs[ATTR_INDEX_POSITION];
1557 				vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2  ] = vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ];
1558 				vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ] = vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ];
1559 
1560 				vaoSurf->vao->frameSize = stride_xyz    * surf->numVerts;
1561 			}
1562 
1563 			Vao_SetVertexPointers(vaoSurf->vao);
1564 
1565 			ri.Free(data);
1566 		}
1567 	}
1568 
1569 	return qtrue;
1570 }
1571 
1572 /*
1573 =================
1574 R_LoadMDR
1575 =================
1576 */
R_LoadMDR(model_t * mod,void * buffer,int filesize,const char * mod_name)1577 static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char *mod_name )
1578 {
1579 	int					i, j, k, l;
1580 	mdrHeader_t			*pinmodel, *mdr;
1581 	mdrFrame_t			*frame;
1582 	mdrLOD_t			*lod, *curlod;
1583 	mdrSurface_t			*surf, *cursurf;
1584 	mdrTriangle_t			*tri, *curtri;
1585 	mdrVertex_t			*v, *curv;
1586 	mdrWeight_t			*weight, *curweight;
1587 	mdrTag_t			*tag, *curtag;
1588 	int					size;
1589 	shader_t			*sh;
1590 
1591 	pinmodel = (mdrHeader_t *)buffer;
1592 
1593 	pinmodel->version = LittleLong(pinmodel->version);
1594 	if (pinmodel->version != MDR_VERSION)
1595 	{
1596 		ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has wrong version (%i should be %i)\n", mod_name, pinmodel->version, MDR_VERSION);
1597 		return qfalse;
1598 	}
1599 
1600 	size = LittleLong(pinmodel->ofsEnd);
1601 
1602 	if(size > filesize)
1603 	{
1604 		ri.Printf(PRINT_WARNING, "R_LoadMDR: Header of %s is broken. Wrong filesize declared!\n", mod_name);
1605 		return qfalse;
1606 	}
1607 
1608 	mod->type = MOD_MDR;
1609 
1610 	LL(pinmodel->numFrames);
1611 	LL(pinmodel->numBones);
1612 	LL(pinmodel->ofsFrames);
1613 
1614 	// This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame
1615 	// over and over again, we'll uncompress it in this function already, so we must adjust the size of the target mdr.
1616 	if(pinmodel->ofsFrames < 0)
1617 	{
1618 		// mdrFrame_t is larger than mdrCompFrame_t:
1619 		size += pinmodel->numFrames * sizeof(frame->name);
1620 		// now add enough space for the uncompressed bones.
1621 		size += pinmodel->numFrames * pinmodel->numBones * ((sizeof(mdrBone_t) - sizeof(mdrCompBone_t)));
1622 	}
1623 
1624 	// simple bounds check
1625 	if(pinmodel->numBones < 0 ||
1626 		sizeof(*mdr) + pinmodel->numFrames * (sizeof(*frame) + (pinmodel->numBones - 1) * sizeof(*frame->bones)) > size)
1627 	{
1628 		ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
1629 		return qfalse;
1630 	}
1631 
1632 	mod->dataSize += size;
1633 	mod->modelData = mdr = ri.Hunk_Alloc( size, h_low );
1634 
1635 	// Copy all the values over from the file and fix endian issues in the process, if necessary.
1636 
1637 	mdr->ident = LittleLong(pinmodel->ident);
1638 	mdr->version = pinmodel->version;	// Don't need to swap byte order on this one, we already did above.
1639 	Q_strncpyz(mdr->name, pinmodel->name, sizeof(mdr->name));
1640 	mdr->numFrames = pinmodel->numFrames;
1641 	mdr->numBones = pinmodel->numBones;
1642 	mdr->numLODs = LittleLong(pinmodel->numLODs);
1643 	mdr->numTags = LittleLong(pinmodel->numTags);
1644 	// We don't care about the other offset values, we'll generate them ourselves while loading.
1645 
1646 	mod->numLods = mdr->numLODs;
1647 
1648 	if ( mdr->numFrames < 1 )
1649 	{
1650 		ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has no frames\n", mod_name);
1651 		return qfalse;
1652 	}
1653 
1654 	/* The first frame will be put into the first free space after the header */
1655 	frame = (mdrFrame_t *)(mdr + 1);
1656 	mdr->ofsFrames = (int)((byte *) frame - (byte *) mdr);
1657 
1658 	if (pinmodel->ofsFrames < 0)
1659 	{
1660 		mdrCompFrame_t *cframe;
1661 
1662 		// compressed model...
1663 		cframe = (mdrCompFrame_t *)((byte *) pinmodel - pinmodel->ofsFrames);
1664 
1665 		for(i = 0; i < mdr->numFrames; i++)
1666 		{
1667 			for(j = 0; j < 3; j++)
1668 			{
1669 				frame->bounds[0][j] = LittleFloat(cframe->bounds[0][j]);
1670 				frame->bounds[1][j] = LittleFloat(cframe->bounds[1][j]);
1671 				frame->localOrigin[j] = LittleFloat(cframe->localOrigin[j]);
1672 			}
1673 
1674 			frame->radius = LittleFloat(cframe->radius);
1675 			frame->name[0] = '\0';	// No name supplied in the compressed version.
1676 
1677 			for(j = 0; j < mdr->numBones; j++)
1678 			{
1679 				for(k = 0; k < (sizeof(cframe->bones[j].Comp) / 2); k++)
1680 				{
1681 					// Do swapping for the uncompressing functions. They seem to use shorts
1682 					// values only, so I assume this will work. Never tested it on other
1683 					// platforms, though.
1684 
1685 					((unsigned short *)(cframe->bones[j].Comp))[k] =
1686 						LittleShort( ((unsigned short *)(cframe->bones[j].Comp))[k] );
1687 				}
1688 
1689 				/* Now do the actual uncompressing */
1690 				MC_UnCompress(frame->bones[j].matrix, cframe->bones[j].Comp);
1691 			}
1692 
1693 			// Next Frame...
1694 			cframe = (mdrCompFrame_t *) &cframe->bones[j];
1695 			frame = (mdrFrame_t *) &frame->bones[j];
1696 		}
1697 	}
1698 	else
1699 	{
1700 		mdrFrame_t *curframe;
1701 
1702 		// uncompressed model...
1703 		//
1704 
1705 		curframe = (mdrFrame_t *)((byte *) pinmodel + pinmodel->ofsFrames);
1706 
1707 		// swap all the frames
1708 		for ( i = 0 ; i < mdr->numFrames ; i++)
1709 		{
1710 			for(j = 0; j < 3; j++)
1711 			{
1712 				frame->bounds[0][j] = LittleFloat(curframe->bounds[0][j]);
1713 				frame->bounds[1][j] = LittleFloat(curframe->bounds[1][j]);
1714 				frame->localOrigin[j] = LittleFloat(curframe->localOrigin[j]);
1715 			}
1716 
1717 			frame->radius = LittleFloat(curframe->radius);
1718 			Q_strncpyz(frame->name, curframe->name, sizeof(frame->name));
1719 
1720 			for (j = 0; j < (int) (mdr->numBones * sizeof(mdrBone_t) / 4); j++)
1721 			{
1722 				((float *)frame->bones)[j] = LittleFloat( ((float *)curframe->bones)[j] );
1723 			}
1724 
1725 			curframe = (mdrFrame_t *) &curframe->bones[mdr->numBones];
1726 			frame = (mdrFrame_t *) &frame->bones[mdr->numBones];
1727 		}
1728 	}
1729 
1730 	// frame should now point to the first free address after all frames.
1731 	lod = (mdrLOD_t *) frame;
1732 	mdr->ofsLODs = (int) ((byte *) lod - (byte *)mdr);
1733 
1734 	curlod = (mdrLOD_t *)((byte *) pinmodel + LittleLong(pinmodel->ofsLODs));
1735 
1736 	// swap all the LOD's
1737 	for ( l = 0 ; l < mdr->numLODs ; l++)
1738 	{
1739 		// simple bounds check
1740 		if((byte *) (lod + 1) > (byte *) mdr + size)
1741 		{
1742 			ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
1743 			return qfalse;
1744 		}
1745 
1746 		lod->numSurfaces = LittleLong(curlod->numSurfaces);
1747 
1748 		// swap all the surfaces
1749 		surf = (mdrSurface_t *) (lod + 1);
1750 		lod->ofsSurfaces = (int)((byte *) surf - (byte *) lod);
1751 		cursurf = (mdrSurface_t *) ((byte *)curlod + LittleLong(curlod->ofsSurfaces));
1752 
1753 		for ( i = 0 ; i < lod->numSurfaces ; i++)
1754 		{
1755 			// simple bounds check
1756 			if((byte *) (surf + 1) > (byte *) mdr + size)
1757 			{
1758 				ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
1759 				return qfalse;
1760 			}
1761 
1762 			// first do some copying stuff
1763 
1764 			surf->ident = SF_MDR;
1765 			Q_strncpyz(surf->name, cursurf->name, sizeof(surf->name));
1766 			Q_strncpyz(surf->shader, cursurf->shader, sizeof(surf->shader));
1767 
1768 			surf->ofsHeader = (byte *) mdr - (byte *) surf;
1769 
1770 			surf->numVerts = LittleLong(cursurf->numVerts);
1771 			surf->numTriangles = LittleLong(cursurf->numTriangles);
1772 			// numBoneReferences and BoneReferences generally seem to be unused
1773 
1774 			// now do the checks that may fail.
1775 			if ( surf->numVerts >= SHADER_MAX_VERTEXES )
1776 			{
1777 				ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i verts on %s (%i).\n",
1778 					  mod_name, SHADER_MAX_VERTEXES - 1, surf->name[0] ? surf->name : "a surface",
1779 					  surf->numVerts );
1780 				return qfalse;
1781 			}
1782 			if ( surf->numTriangles*3 >= SHADER_MAX_INDEXES )
1783 			{
1784 				ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i triangles on %s (%i).\n",
1785 					  mod_name, ( SHADER_MAX_INDEXES / 3 ) - 1, surf->name[0] ? surf->name : "a surface",
1786 					  surf->numTriangles );
1787 				return qfalse;
1788 			}
1789 			// lowercase the surface name so skin compares are faster
1790 			Q_strlwr( surf->name );
1791 
1792 			// register the shaders
1793 			sh = R_FindShader(surf->shader, LIGHTMAP_NONE, qtrue);
1794 			if ( sh->defaultShader ) {
1795 				surf->shaderIndex = 0;
1796 			} else {
1797 				surf->shaderIndex = sh->index;
1798 			}
1799 
1800 			// now copy the vertexes.
1801 			v = (mdrVertex_t *) (surf + 1);
1802 			surf->ofsVerts = (int)((byte *) v - (byte *) surf);
1803 			curv = (mdrVertex_t *) ((byte *)cursurf + LittleLong(cursurf->ofsVerts));
1804 
1805 			for(j = 0; j < surf->numVerts; j++)
1806 			{
1807 				LL(curv->numWeights);
1808 
1809 				// simple bounds check
1810 				if(curv->numWeights < 0 || (byte *) (v + 1) + (curv->numWeights - 1) * sizeof(*weight) > (byte *) mdr + size)
1811 				{
1812 					ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
1813 					return qfalse;
1814 				}
1815 
1816 				v->normal[0] = LittleFloat(curv->normal[0]);
1817 				v->normal[1] = LittleFloat(curv->normal[1]);
1818 				v->normal[2] = LittleFloat(curv->normal[2]);
1819 
1820 				v->texCoords[0] = LittleFloat(curv->texCoords[0]);
1821 				v->texCoords[1] = LittleFloat(curv->texCoords[1]);
1822 
1823 				v->numWeights = curv->numWeights;
1824 				weight = &v->weights[0];
1825 				curweight = &curv->weights[0];
1826 
1827 				// Now copy all the weights
1828 				for(k = 0; k < v->numWeights; k++)
1829 				{
1830 					weight->boneIndex = LittleLong(curweight->boneIndex);
1831 					weight->boneWeight = LittleFloat(curweight->boneWeight);
1832 
1833 					weight->offset[0] = LittleFloat(curweight->offset[0]);
1834 					weight->offset[1] = LittleFloat(curweight->offset[1]);
1835 					weight->offset[2] = LittleFloat(curweight->offset[2]);
1836 
1837 					weight++;
1838 					curweight++;
1839 				}
1840 
1841 				v = (mdrVertex_t *) weight;
1842 				curv = (mdrVertex_t *) curweight;
1843 			}
1844 
1845 			// we know the offset to the triangles now:
1846 			tri = (mdrTriangle_t *) v;
1847 			surf->ofsTriangles = (int)((byte *) tri - (byte *) surf);
1848 			curtri = (mdrTriangle_t *)((byte *) cursurf + LittleLong(cursurf->ofsTriangles));
1849 
1850 			// simple bounds check
1851 			if(surf->numTriangles < 0 || (byte *) (tri + surf->numTriangles) > (byte *) mdr + size)
1852 			{
1853 				ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
1854 				return qfalse;
1855 			}
1856 
1857 			for(j = 0; j < surf->numTriangles; j++)
1858 			{
1859 				tri->indexes[0] = LittleLong(curtri->indexes[0]);
1860 				tri->indexes[1] = LittleLong(curtri->indexes[1]);
1861 				tri->indexes[2] = LittleLong(curtri->indexes[2]);
1862 
1863 				tri++;
1864 				curtri++;
1865 			}
1866 
1867 			// tri now points to the end of the surface.
1868 			surf->ofsEnd = (byte *) tri - (byte *) surf;
1869 			surf = (mdrSurface_t *) tri;
1870 
1871 			// find the next surface.
1872 			cursurf = (mdrSurface_t *) ((byte *) cursurf + LittleLong(cursurf->ofsEnd));
1873 		}
1874 
1875 		// surf points to the next lod now.
1876 		lod->ofsEnd = (int)((byte *) surf - (byte *) lod);
1877 		lod = (mdrLOD_t *) surf;
1878 
1879 		// find the next LOD.
1880 		curlod = (mdrLOD_t *)((byte *) curlod + LittleLong(curlod->ofsEnd));
1881 	}
1882 
1883 	// lod points to the first tag now, so update the offset too.
1884 	tag = (mdrTag_t *) lod;
1885 	mdr->ofsTags = (int)((byte *) tag - (byte *) mdr);
1886 	curtag = (mdrTag_t *) ((byte *)pinmodel + LittleLong(pinmodel->ofsTags));
1887 
1888 	// simple bounds check
1889 	if(mdr->numTags < 0 || (byte *) (tag + mdr->numTags) > (byte *) mdr + size)
1890 	{
1891 		ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
1892 		return qfalse;
1893 	}
1894 
1895 	for (i = 0 ; i < mdr->numTags ; i++)
1896 	{
1897 		tag->boneIndex = LittleLong(curtag->boneIndex);
1898 		Q_strncpyz(tag->name, curtag->name, sizeof(tag->name));
1899 
1900 		tag++;
1901 		curtag++;
1902 	}
1903 
1904 	// And finally we know the real offset to the end.
1905 	mdr->ofsEnd = (int)((byte *) tag - (byte *) mdr);
1906 
1907 	// phew! we're done.
1908 
1909 	return qtrue;
1910 }
1911 
1912 
1913 /*
1914 =================
1915 R_LoadMDS
1916 =================
1917 */
R_LoadMDS(model_t * mod,void * buffer,const char * mod_name)1918 static qboolean R_LoadMDS( model_t *mod, void *buffer, const char *mod_name ) {
1919 	int i, j, k;
1920 	mdsHeader_t         *pinmodel, *mds;
1921 	mdsFrame_t          *frame;
1922 	mdsSurface_t        *surf;
1923 	mdsTriangle_t       *tri;
1924 	mdsVertex_t         *v;
1925 	mdsBoneInfo_t       *bi;
1926 	mdsTag_t            *tag;
1927 	int version;
1928 	int size;
1929 	shader_t            *sh;
1930 	int frameSize;
1931 	int                 *collapseMap, *boneref;
1932 
1933 	pinmodel = (mdsHeader_t *)buffer;
1934 
1935 	version = LittleLong( pinmodel->version );
1936 	if ( version != MDS_VERSION ) {
1937 		ri.Printf( PRINT_WARNING, "R_LoadMDS: %s has wrong version (%i should be %i)\n",
1938 				   mod_name, version, MDS_VERSION );
1939 		return qfalse;
1940 	}
1941 
1942 	mod->type = MOD_MDS;
1943 	size = LittleLong( pinmodel->ofsEnd );
1944 	mod->dataSize += size;
1945 	mds = mod->mds = ri.Hunk_Alloc( size, h_low );
1946 
1947 	memcpy( mds, buffer, LittleLong( pinmodel->ofsEnd ) );
1948 
1949 	LL( mds->ident );
1950 	LL( mds->version );
1951 	LL( mds->numFrames );
1952 	LL( mds->numBones );
1953 	LL( mds->numTags );
1954 	LL( mds->numSurfaces );
1955 	LL( mds->ofsFrames );
1956 	LL( mds->ofsBones );
1957 	LL( mds->ofsTags );
1958 	LL( mds->ofsEnd );
1959 	LL( mds->ofsSurfaces );
1960 	mds->lodBias = LittleFloat( mds->lodBias );
1961 	mds->lodScale = LittleFloat( mds->lodScale );
1962 	LL( mds->torsoParent );
1963 
1964 	if ( mds->numFrames < 1 ) {
1965 		ri.Printf( PRINT_WARNING, "R_LoadMDS: %s has no frames\n", mod_name );
1966 		return qfalse;
1967 	}
1968 
1969 	if ( LittleLong( 1 ) != 1 ) {
1970 		// swap all the frames
1971 		//frameSize = (int)( &((mdsFrame_t *)0)->bones[ mds->numBones ] );
1972 		frameSize = (int) ( sizeof( mdsFrame_t ) - sizeof( mdsBoneFrameCompressed_t ) + mds->numBones * sizeof( mdsBoneFrameCompressed_t ) );
1973 		for ( i = 0 ; i < mds->numFrames ; i++, frame++ ) {
1974 			frame = ( mdsFrame_t * )( (byte *)mds + mds->ofsFrames + i * frameSize );
1975 			frame->radius = LittleFloat( frame->radius );
1976 			for ( j = 0 ; j < 3 ; j++ ) {
1977 				frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
1978 				frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
1979 				frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
1980 				frame->parentOffset[j] = LittleFloat( frame->parentOffset[j] );
1981 			}
1982 			for ( j = 0 ; j < mds->numBones * sizeof( mdsBoneFrameCompressed_t ) / sizeof( short ) ; j++ ) {
1983 				( (short *)frame->bones )[j] = LittleShort( ( (short *)frame->bones )[j] );
1984 			}
1985 		}
1986 
1987 		// swap all the tags
1988 		tag = ( mdsTag_t * )( (byte *)mds + mds->ofsTags );
1989 		for ( i = 0 ; i < mds->numTags ; i++, tag++ ) {
1990 			LL( tag->boneIndex );
1991 			tag->torsoWeight = LittleFloat( tag->torsoWeight );
1992 		}
1993 
1994 		// swap all the bones
1995 		for ( i = 0 ; i < mds->numBones ; i++, bi++ ) {
1996 			bi = ( mdsBoneInfo_t * )( (byte *)mds + mds->ofsBones + i * sizeof( mdsBoneInfo_t ) );
1997 			LL( bi->parent );
1998 			bi->torsoWeight = LittleFloat( bi->torsoWeight );
1999 			bi->parentDist = LittleFloat( bi->parentDist );
2000 			LL( bi->flags );
2001 		}
2002 	}
2003 
2004 	// swap all the surfaces
2005 	surf = ( mdsSurface_t * )( (byte *)mds + mds->ofsSurfaces );
2006 	for ( i = 0 ; i < mds->numSurfaces ; i++ ) {
2007 		if ( LittleLong( 1 ) != 1 ) {
2008 			LL( surf->ident );
2009 			LL( surf->shaderIndex );
2010 			LL( surf->minLod );
2011 			LL( surf->ofsHeader );
2012 			LL( surf->ofsCollapseMap );
2013 			LL( surf->numTriangles );
2014 			LL( surf->ofsTriangles );
2015 			LL( surf->numVerts );
2016 			LL( surf->ofsVerts );
2017 			LL( surf->numBoneReferences );
2018 			LL( surf->ofsBoneReferences );
2019 			LL( surf->ofsEnd );
2020 		}
2021 
2022 		// change to surface identifier
2023 		surf->ident = SF_MDS;
2024 
2025 		if ( surf->numVerts >= SHADER_MAX_VERTEXES ) {
2026 			ri.Printf(PRINT_WARNING, "R_LoadMDS: %s has more than %i verts on %s (%i).\n",
2027 				mod_name, SHADER_MAX_VERTEXES - 1, surf->name[0] ? surf->name : "a surface",
2028 				surf->numVerts );
2029 			return qfalse;
2030 		}
2031 		if ( surf->numTriangles*3 >= SHADER_MAX_INDEXES ) {
2032 			ri.Printf(PRINT_WARNING, "R_LoadMDS: %s has more than %i triangles on %s (%i).\n",
2033 				mod_name, ( SHADER_MAX_INDEXES / 3 ) - 1, surf->name[0] ? surf->name : "a surface",
2034 				surf->numTriangles );
2035 			return qfalse;
2036 		}
2037 
2038 		// register the shaders
2039 		if ( surf->shader[0] ) {
2040 			sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue );
2041 			if ( sh->defaultShader ) {
2042 				surf->shaderIndex = 0;
2043 			} else {
2044 				surf->shaderIndex = sh->index;
2045 			}
2046 		} else {
2047 			surf->shaderIndex = 0;
2048 		}
2049 
2050 		if ( LittleLong( 1 ) != 1 ) {
2051 			// swap all the triangles
2052 			tri = ( mdsTriangle_t * )( (byte *)surf + surf->ofsTriangles );
2053 			for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
2054 				LL( tri->indexes[0] );
2055 				LL( tri->indexes[1] );
2056 				LL( tri->indexes[2] );
2057 			}
2058 
2059 			// swap all the vertexes
2060 			v = ( mdsVertex_t * )( (byte *)surf + surf->ofsVerts );
2061 			for ( j = 0 ; j < surf->numVerts ; j++ ) {
2062 				v->normal[0] = LittleFloat( v->normal[0] );
2063 				v->normal[1] = LittleFloat( v->normal[1] );
2064 				v->normal[2] = LittleFloat( v->normal[2] );
2065 
2066 				v->texCoords[0] = LittleFloat( v->texCoords[0] );
2067 				v->texCoords[1] = LittleFloat( v->texCoords[1] );
2068 
2069 				v->numWeights = LittleLong( v->numWeights );
2070 
2071 				for ( k = 0 ; k < v->numWeights ; k++ ) {
2072 					v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex );
2073 					v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight );
2074 					v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] );
2075 					v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] );
2076 					v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] );
2077 				}
2078 
2079 				v = (mdsVertex_t *)&v->weights[v->numWeights];
2080 			}
2081 
2082 			// swap the collapse map
2083 			collapseMap = ( int * )( (byte *)surf + surf->ofsCollapseMap );
2084 			for ( j = 0; j < surf->numVerts; j++, collapseMap++ ) {
2085 				*collapseMap = LittleLong( *collapseMap );
2086 			}
2087 
2088 			// swap the bone references
2089 			boneref = ( int * )( ( byte *)surf + surf->ofsBoneReferences );
2090 			for ( j = 0; j < surf->numBoneReferences; j++, boneref++ ) {
2091 				*boneref = LittleLong( *boneref );
2092 			}
2093 		}
2094 
2095 		// find the next surface
2096 		surf = ( mdsSurface_t * )( (byte *)surf + surf->ofsEnd );
2097 	}
2098 
2099 	return qtrue;
2100 }
2101 
2102 
2103 
2104 
2105 //=============================================================================
2106 
2107 /*
2108 ** RE_BeginRegistration
2109 */
RE_BeginRegistration(glconfig_t * glconfigOut)2110 void RE_BeginRegistration( glconfig_t *glconfigOut ) {
2111 	int	i;
2112 
2113 	ri.Hunk_Clear();    // (SA) MEM NOTE: not in missionpack
2114 
2115 	R_Init();
2116 	*glconfigOut = glConfig;
2117 
2118 	R_IssuePendingRenderCommands();
2119 
2120 	tr.visIndex = 0;
2121 	// force markleafs to regenerate
2122 	for(i = 0; i < MAX_VISCOUNTS; i++) {
2123 		tr.visClusters[i] = -2;
2124 	}
2125 
2126 	R_ClearFlares();
2127 	RE_ClearScene();
2128 
2129 	tr.registered = qtrue;
2130 }
2131 
2132 /*
2133 ===============
2134 R_ModelInit
2135 ===============
2136 */
R_ModelInit(void)2137 void R_ModelInit( void ) {
2138 	model_t     *mod;
2139 
2140 	// leave a space for NULL model
2141 	tr.numModels = 0;
2142 
2143 	mod = R_AllocModel();
2144 	mod->type = MOD_BAD;
2145 }
2146 
2147 
2148 /*
2149 ================
2150 R_Modellist_f
2151 ================
2152 */
2153 
R_Modellist_f(void)2154 void R_Modellist_f( void ) {
2155 	int i, j;
2156 	model_t *mod;
2157 	int total;
2158 	int lods;
2159 
2160 	total = 0;
2161 	for ( i = 1 ; i < tr.numModels; i++ ) {
2162 		mod = tr.models[i];
2163 		lods = 1;
2164 		for ( j = 1 ; j < MD3_MAX_LODS ; j++ ) {
2165 			if ( mod->mdv[j] && mod->mdv[j] != mod->mdv[j - 1] ) {
2166 				lods++;
2167 			}
2168 		}
2169 		ri.Printf( PRINT_ALL, "%8i : (%i) %s\n",mod->dataSize, lods, mod->name );
2170 		total += mod->dataSize;
2171 	}
2172 	ri.Printf( PRINT_ALL, "%8i : Total models\n", total );
2173 }
2174 
2175 
2176 //=============================================================================
2177 
2178 
2179 /*
2180 ================
2181 R_GetTag
2182 ================
2183 */
R_GetTag(mdvModel_t * model,int frame,const char * _tagName,int startTagIndex,mdvTag_t ** outTag)2184 static int R_GetTag(mdvModel_t * model, int frame, const char *_tagName, int startTagIndex, mdvTag_t ** outTag)
2185 {
2186 	int             i;
2187 	mdvTag_t       *tag;
2188 	mdvTagName_t   *tagName;
2189 
2190 	if ( frame >= model->numFrames ) {
2191 		// it is possible to have a bad frame while changing models, so don't error
2192 		frame = model->numFrames - 1;
2193 	}
2194 
2195 	if(startTagIndex > model->numTags)
2196 	{
2197 		*outTag = NULL;
2198 		return -1;
2199 	}
2200 
2201 #if 1
2202 	tag = model->tags + frame * model->numTags;
2203 	tagName = model->tagNames;
2204 	for(i = 0; i < model->numTags; i++, tag++, tagName++)
2205 	{
2206 		if((i >= startTagIndex) && !strcmp(tagName->name, _tagName))
2207 		{
2208 			*outTag = tag;
2209 			return i;
2210 		}
2211 	}
2212 #endif
2213 
2214 	*outTag = NULL;
2215 	return -1;
2216 }
2217 
R_GetAnimTag(mdrHeader_t * mod,int framenum,const char * tagName,int startTagIndex,mdvTag_t ** outTag)2218 static int R_GetAnimTag( mdrHeader_t *mod, int framenum, const char *tagName, int startTagIndex, mdvTag_t **outTag)
2219 {
2220 	int				i, j, k;
2221 	int				frameSize;
2222 	mdrFrame_t		*frame;
2223 	mdrTag_t		*tag;
2224 	mdvTag_t		*dest = *outTag;
2225 
2226 	if ( framenum >= mod->numFrames )
2227 	{
2228 		// it is possible to have a bad frame while changing models, so don't error
2229 		framenum = mod->numFrames - 1;
2230 	}
2231 
2232 	if ( startTagIndex > mod->numTags )
2233 	{
2234 		*outTag = NULL;
2235 		return -1;
2236 	}
2237 
2238 	tag = (mdrTag_t *)((byte *)mod + mod->ofsTags);
2239 	for ( i = 0 ; i < mod->numTags ; i++, tag++ )
2240 	{
2241 		if ( ( i >= startTagIndex ) && !strcmp( tag->name, tagName ) )
2242 		{
2243 			// uncompressed model...
2244 			//
2245 			frameSize = (intptr_t)( &((mdrFrame_t *)0)->bones[ mod->numBones ] );
2246 			frame = (mdrFrame_t *)((byte *)mod + mod->ofsFrames + framenum * frameSize );
2247 
2248 			for (j = 0; j < 3; j++)
2249 			{
2250 				for (k = 0; k < 3; k++)
2251 					dest->axis[j][k]=frame->bones[tag->boneIndex].matrix[k][j];
2252 			}
2253 
2254 			dest->origin[0]=frame->bones[tag->boneIndex].matrix[0][3];
2255 			dest->origin[1]=frame->bones[tag->boneIndex].matrix[1][3];
2256 			dest->origin[2]=frame->bones[tag->boneIndex].matrix[2][3];
2257 
2258 			return i;
2259 		}
2260 	}
2261 
2262 	*outTag = NULL;
2263 	return -1;
2264 }
2265 
2266 
2267 /*
2268 ================
2269 R_LerpTag
2270 
2271   returns the index of the tag it found, for cycling through tags with the same name
2272 ================
2273 */
R_LerpTag(orientation_t * tag,const refEntity_t * refent,const char * tagNameIn,int startIndex)2274 int R_LerpTag( orientation_t *tag, const refEntity_t *refent, const char *tagNameIn, int startIndex ) {
2275 	mdvTag_t    *start, *end;
2276 	mdvTag_t	start_space, end_space;
2277 	int i;
2278 	float frontLerp, backLerp;
2279 	model_t     *model;
2280 	char tagName[MAX_QPATH];       //, *ch;
2281 	int retval = 0;
2282 	qhandle_t handle;
2283 	int startFrame, endFrame;
2284 	float frac;
2285 
2286 	handle = refent->hModel;
2287 	startFrame = refent->oldframe;
2288 	endFrame = refent->frame;
2289 	frac = 1.0 - refent->backlerp;
2290 
2291 	Q_strncpyz( tagName, tagNameIn, MAX_QPATH );
2292 
2293 	model = R_GetModelByHandle( handle );
2294 	if ( !model->mdv[0] /*&& !model->mdc[0]*/ && !model->mds ) {
2295 		if(model->type == MOD_MDR)
2296 		{
2297 			start = &start_space;
2298 			end = &end_space;
2299 			retval = R_GetAnimTag((mdrHeader_t *) model->modelData, startFrame, tagName, startIndex, &start);
2300 			R_GetAnimTag((mdrHeader_t *) model->modelData, endFrame, tagName, startIndex, &end);
2301 		}
2302 		else if ( model->type == MOD_IQM ) {
2303 			return R_IQMLerpTag( tag, model->modelData,
2304 					startFrame, endFrame,
2305 					frac, tagName, startIndex );
2306 		} else {
2307 			start = end = NULL;
2308 		}
2309 	} else if ( model->type == MOD_MESH ) {
2310 		// old MD3 style
2311 		retval = R_GetTag(model->mdv[0], startFrame, tagName, startIndex, &start);
2312 		R_GetTag(model->mdv[0], endFrame, tagName, startIndex, &end);
2313 	} else if ( model->type == MOD_MDS ) {    // use bone lerping
2314 
2315 		retval = R_GetBoneTag( tag, model->mds, startIndex, refent, tagNameIn );
2316 
2317 		if ( retval >= 0 ) {
2318 			return retval;
2319 		}
2320 
2321 		// failed
2322 		return -1;
2323 	} else {
2324 		// failed
2325 		return -1;
2326 	}
2327 
2328 	if ( !start || !end ) {
2329 		AxisClear( tag->axis );
2330 		VectorClear( tag->origin );
2331 		return -1;
2332 	}
2333 
2334 	frontLerp = frac;
2335 	backLerp = 1.0f - frac;
2336 
2337 	for ( i = 0 ; i < 3 ; i++ ) {
2338 		tag->origin[i] = start->origin[i] * backLerp +  end->origin[i] * frontLerp;
2339 		tag->axis[0][i] = start->axis[0][i] * backLerp +  end->axis[0][i] * frontLerp;
2340 		tag->axis[1][i] = start->axis[1][i] * backLerp +  end->axis[1][i] * frontLerp;
2341 		tag->axis[2][i] = start->axis[2][i] * backLerp +  end->axis[2][i] * frontLerp;
2342 	}
2343 
2344 	VectorNormalize( tag->axis[0] );
2345 	VectorNormalize( tag->axis[1] );
2346 	VectorNormalize( tag->axis[2] );
2347 
2348 	return retval;
2349 }
2350 
2351 /*
2352 ===============
2353 R_TagInfo_f
2354 ===============
2355 */
R_TagInfo_f(void)2356 void R_TagInfo_f( void ) {
2357 	Com_Printf( "command not functional\n" );
2358 }
2359 
2360 
2361 /*
2362 ====================
2363 R_ModelBounds
2364 ====================
2365 */
R_ModelBounds(qhandle_t handle,vec3_t mins,vec3_t maxs)2366 void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
2367 	model_t     *model;
2368 
2369 	model = R_GetModelByHandle( handle );
2370 
2371 	if ( model->bmodel ) {
2372 		VectorCopy( model->bmodel->bounds[0], mins );
2373 		VectorCopy( model->bmodel->bounds[1], maxs );
2374 		return;
2375 	}
2376 
2377 	// Ridah
2378 	if ( model->mdv[0] ) {
2379 		mdvModel_t     *header;
2380 		mdvFrame_t     *frame;
2381 
2382 		header = model->mdv[0];
2383 		frame = header->frames;
2384 
2385 		VectorCopy( frame->bounds[0], mins );
2386 		VectorCopy( frame->bounds[1], maxs );
2387 		return;
2388 	} else if (model->type == MOD_MDR) {
2389 		mdrHeader_t	*header;
2390 		mdrFrame_t	*frame;
2391 
2392 		header = (mdrHeader_t *)model->modelData;
2393 		frame = (mdrFrame_t *) ((byte *)header + header->ofsFrames);
2394 
2395 		VectorCopy( frame->bounds[0], mins );
2396 		VectorCopy( frame->bounds[1], maxs );
2397 
2398 		return;
2399 	} else if(model->type == MOD_IQM) {
2400 		iqmData_t *iqmData;
2401 
2402 		iqmData = model->modelData;
2403 
2404 		if(iqmData->bounds)
2405 		{
2406 			VectorCopy(iqmData->bounds, mins);
2407 			VectorCopy(iqmData->bounds + 3, maxs);
2408 			return;
2409 		}
2410 	}
2411 
2412 	VectorClear( mins );
2413 	VectorClear( maxs );
2414 	// done.
2415 }
2416 
2417 
R_Hunk_Begin(void)2418 void *R_Hunk_Begin( void ) {
2419 	return NULL;
2420 }
2421 
R_Hunk_Alloc(int size)2422 void *R_Hunk_Alloc( int size ) {
2423 	return NULL;
2424 }
2425 
2426 // this is only called when we shutdown GL
R_Hunk_End(void)2427 void R_Hunk_End( void ) {
2428 	return;
2429 }
2430 
R_Hunk_Reset(void)2431 void R_Hunk_Reset( void ) {
2432 	return;
2433 }
2434 
2435