1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 Copyright (C) 2000-2006 Tim Angus
5
6 This file is part of Tremulous.
7
8 Tremulous is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12
13 Tremulous is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Tremulous; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 ===========================================================================
22 */
23 // tr_models.c -- model loading and caching
24
25 #include "tr_local.h"
26
27 #define LL(x) x=LittleLong(x)
28
29 static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *name );
30 static qboolean R_LoadMD4 (model_t *mod, void *buffer, const char *name );
31 #ifdef RAVENMD4
32 static qboolean R_LoadMDR (model_t *mod, void *buffer, int filesize, const char *name );
33 #endif
34
35 model_t *loadmodel;
36
37 /*
38 ** R_GetModelByHandle
39 */
R_GetModelByHandle(qhandle_t index)40 model_t *R_GetModelByHandle( qhandle_t index ) {
41 model_t *mod;
42
43 // out of range gets the defualt model
44 if ( index < 1 || index >= tr.numModels ) {
45 return tr.models[0];
46 }
47
48 mod = tr.models[index];
49
50 return mod;
51 }
52
53 //===============================================================================
54
55 /*
56 ** R_AllocModel
57 */
R_AllocModel(void)58 model_t *R_AllocModel( void ) {
59 model_t *mod;
60
61 if ( tr.numModels == MAX_MOD_KNOWN ) {
62 return NULL;
63 }
64
65 mod = ri.Hunk_Alloc( sizeof( *tr.models[tr.numModels] ), h_low );
66 mod->index = tr.numModels;
67 tr.models[tr.numModels] = mod;
68 tr.numModels++;
69
70 return mod;
71 }
72
73 /*
74 ====================
75 RE_RegisterModel
76
77 Loads in a model for the given name
78
79 Zero will be returned if the model fails to load.
80 An entry will be retained for failed models as an
81 optimization to prevent disk rescanning if they are
82 asked for again.
83 ====================
84 */
RE_RegisterModel(const char * name)85 qhandle_t RE_RegisterModel( const char *name ) {
86 model_t *mod;
87 unsigned *buf;
88 int lod;
89 int ident;
90 qboolean loaded = qfalse;
91 qhandle_t hModel;
92 int numLoaded;
93 char *fext, defex[] = "md3", filename[MAX_QPATH], namebuf[MAX_QPATH+20];
94
95 if ( !name || !name[0] ) {
96 ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" );
97 return 0;
98 }
99
100 if ( strlen( name ) >= MAX_QPATH ) {
101 Com_Printf( "Model name exceeds MAX_QPATH\n" );
102 return 0;
103 }
104
105 //
106 // search the currently loaded models
107 //
108 for ( hModel = 1 ; hModel < tr.numModels; hModel++ ) {
109 mod = tr.models[hModel];
110 if ( !strcmp( mod->name, name ) ) {
111 if( mod->type == MOD_BAD ) {
112 return 0;
113 }
114 return hModel;
115 }
116 }
117
118 // allocate a new model_t
119
120 if ( ( mod = R_AllocModel() ) == NULL ) {
121 ri.Printf( PRINT_WARNING, "RE_RegisterModel: R_AllocModel() failed for '%s'\n", name);
122 return 0;
123 }
124
125 // only set the name after the model has been successfully loaded
126 Q_strncpyz( mod->name, name, sizeof( mod->name ) );
127
128
129 // make sure the render thread is stopped
130 R_SyncRenderThread();
131
132 mod->numLods = 0;
133
134 //
135 // load the files
136 //
137 numLoaded = 0;
138
139 strcpy(filename, name);
140
141 fext = strchr(filename, '.');
142 if(!fext)
143 fext = defex;
144 else
145 {
146 *fext = '\0';
147 fext++;
148 }
149
150 #ifdef RAVENMD4
151 if(!Q_stricmp(fext, "mdr"))
152 {
153 int filesize;
154
155 filesize = ri.FS_ReadFile(name, (void **) &buf);
156 if(!buf)
157 {
158 ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name);
159 mod->type = MOD_BAD;
160 return 0;
161 }
162
163 ident = LittleLong(*(unsigned *)buf);
164 if(ident == MDR_IDENT)
165 loaded = R_LoadMDR(mod, buf, filesize, name);
166
167 ri.FS_FreeFile (buf);
168
169 if(!loaded)
170 {
171 ri.Printf(PRINT_WARNING,"RE_RegisterModel: couldn't load mdr file %s\n", name);
172 mod->type = MOD_BAD;
173 return 0;
174 }
175
176 return mod->index;
177 }
178 #endif
179
180 fext = defex;
181
182 for ( lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod-- ) {
183 if ( lod )
184 Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext);
185 else
186 Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext);
187
188 ri.FS_ReadFile( namebuf, (void **)&buf );
189 if ( !buf ) {
190 continue;
191 }
192
193 loadmodel = mod;
194
195 ident = LittleLong(*(unsigned *)buf);
196 if ( ident == MD4_IDENT ) {
197 loaded = R_LoadMD4( mod, buf, name );
198 } else {
199 if ( ident != MD3_IDENT ) {
200 ri.Printf (PRINT_WARNING,"RE_RegisterModel: unknown fileid for %s\n", name);
201 goto fail;
202 }
203
204 loaded = R_LoadMD3( mod, lod, buf, name );
205 }
206
207 ri.FS_FreeFile (buf);
208
209 if ( !loaded ) {
210 if ( lod == 0 ) {
211 goto fail;
212 } else {
213 break;
214 }
215 } else {
216 mod->numLods++;
217 numLoaded++;
218 // if we have a valid model and are biased
219 // so that we won't see any higher detail ones,
220 // stop loading them
221 // if ( lod <= r_lodbias->integer ) {
222 // break;
223 // }
224 }
225 }
226
227 if ( numLoaded ) {
228 // duplicate into higher lod spots that weren't
229 // loaded, in case the user changes r_lodbias on the fly
230 for ( lod-- ; lod >= 0 ; lod-- ) {
231 mod->numLods++;
232 mod->md3[lod] = mod->md3[lod+1];
233 }
234
235 return mod->index;
236 }
237 #ifdef _DEBUG
238 else {
239 ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name);
240 }
241 #endif
242
243 fail:
244 // we still keep the model_t around, so if the model name is asked for
245 // again, we won't bother scanning the filesystem
246 mod->type = MOD_BAD;
247 return 0;
248 }
249
250
251 /*
252 =================
253 R_LoadMD3
254 =================
255 */
R_LoadMD3(model_t * mod,int lod,void * buffer,const char * mod_name)256 static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name ) {
257 int i, j;
258 md3Header_t *pinmodel;
259 md3Frame_t *frame;
260 md3Surface_t *surf;
261 md3Shader_t *shader;
262 md3Triangle_t *tri;
263 md3St_t *st;
264 md3XyzNormal_t *xyz;
265 md3Tag_t *tag;
266 int version;
267 int size;
268
269 pinmodel = (md3Header_t *)buffer;
270
271 version = LittleLong (pinmodel->version);
272 if (version != MD3_VERSION) {
273 ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n",
274 mod_name, version, MD3_VERSION);
275 return qfalse;
276 }
277
278 mod->type = MOD_MESH;
279 size = LittleLong(pinmodel->ofsEnd);
280 mod->dataSize += size;
281 mod->md3[lod] = ri.Hunk_Alloc( size, h_low );
282
283 Com_Memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) );
284
285 LL(mod->md3[lod]->ident);
286 LL(mod->md3[lod]->version);
287 LL(mod->md3[lod]->numFrames);
288 LL(mod->md3[lod]->numTags);
289 LL(mod->md3[lod]->numSurfaces);
290 LL(mod->md3[lod]->ofsFrames);
291 LL(mod->md3[lod]->ofsTags);
292 LL(mod->md3[lod]->ofsSurfaces);
293 LL(mod->md3[lod]->ofsEnd);
294
295 if ( mod->md3[lod]->numFrames < 1 ) {
296 ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name );
297 return qfalse;
298 }
299
300 // swap all the frames
301 frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames );
302 for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) {
303 frame->radius = LittleFloat( frame->radius );
304 for ( j = 0 ; j < 3 ; j++ ) {
305 frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
306 frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
307 frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
308 }
309 }
310
311 // swap all the tags
312 tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags );
313 for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) {
314 for ( j = 0 ; j < 3 ; j++ ) {
315 tag->origin[j] = LittleFloat( tag->origin[j] );
316 tag->axis[0][j] = LittleFloat( tag->axis[0][j] );
317 tag->axis[1][j] = LittleFloat( tag->axis[1][j] );
318 tag->axis[2][j] = LittleFloat( tag->axis[2][j] );
319 }
320 }
321
322 // swap all the surfaces
323 surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces );
324 for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) {
325
326 LL(surf->ident);
327 LL(surf->flags);
328 LL(surf->numFrames);
329 LL(surf->numShaders);
330 LL(surf->numTriangles);
331 LL(surf->ofsTriangles);
332 LL(surf->numVerts);
333 LL(surf->ofsShaders);
334 LL(surf->ofsSt);
335 LL(surf->ofsXyzNormals);
336 LL(surf->ofsEnd);
337
338 if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
339 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
340 mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
341 }
342 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
343 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
344 mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
345 }
346
347 // change to surface identifier
348 surf->ident = SF_MD3;
349
350 // lowercase the surface name so skin compares are faster
351 Q_strlwr( surf->name );
352
353 // strip off a trailing _1 or _2
354 // this is a crutch for q3data being a mess
355 j = strlen( surf->name );
356 if ( j > 2 && surf->name[j-2] == '_' ) {
357 surf->name[j-2] = 0;
358 }
359
360 // register the shaders
361 shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
362 for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) {
363 shader_t *sh;
364
365 sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue );
366 if ( sh->defaultShader ) {
367 shader->shaderIndex = 0;
368 } else {
369 shader->shaderIndex = sh->index;
370 }
371 }
372
373 // swap all the triangles
374 tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
375 for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
376 LL(tri->indexes[0]);
377 LL(tri->indexes[1]);
378 LL(tri->indexes[2]);
379 }
380
381 // swap all the ST
382 st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
383 for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
384 st->st[0] = LittleFloat( st->st[0] );
385 st->st[1] = LittleFloat( st->st[1] );
386 }
387
388 // swap all the XyzNormals
389 xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
390 for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ )
391 {
392 xyz->xyz[0] = LittleShort( xyz->xyz[0] );
393 xyz->xyz[1] = LittleShort( xyz->xyz[1] );
394 xyz->xyz[2] = LittleShort( xyz->xyz[2] );
395
396 xyz->normal = LittleShort( xyz->normal );
397 }
398
399
400 // find the next surface
401 surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
402 }
403
404 return qtrue;
405 }
406
407
408
409 /*
410 =================
411 R_LoadMDR
412 =================
413 */
414 #ifdef RAVENMD4
R_LoadMDR(model_t * mod,void * buffer,int filesize,const char * mod_name)415 static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char *mod_name )
416 {
417 int i, j, k, l;
418 mdrHeader_t *pinmodel, *mdr;
419 mdrFrame_t *frame;
420 mdrLOD_t *lod, *curlod;
421 mdrSurface_t *surf, *cursurf;
422 mdrTriangle_t *tri, *curtri;
423 mdrVertex_t *v, *curv;
424 mdrWeight_t *weight, *curweight;
425 mdrTag_t *tag, *curtag;
426 int size;
427 shader_t *sh;
428
429 pinmodel = (mdrHeader_t *)buffer;
430
431 pinmodel->version = LittleLong(pinmodel->version);
432 if (pinmodel->version != MDR_VERSION)
433 {
434 ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has wrong version (%i should be %i)\n", mod_name, pinmodel->version, MDR_VERSION);
435 return qfalse;
436 }
437
438 size = LittleLong(pinmodel->ofsEnd);
439
440 if(size > filesize)
441 {
442 ri.Printf(PRINT_WARNING, "R_LoadMDR: Header of %s is broken. Wrong filesize declared!\n", mod_name);
443 return qfalse;
444 }
445
446 mod->type = MOD_MDR;
447
448 pinmodel->numFrames = LittleLong(pinmodel->numFrames);
449 pinmodel->numBones = LittleLong(pinmodel->numBones);
450 pinmodel->ofsFrames = LittleLong(pinmodel->ofsFrames);
451
452 // This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame
453 // over and over again, we'll uncompress it in this function already, so we must adjust the size of the target md4.
454 if(pinmodel->ofsFrames < 0)
455 {
456 // mdrFrame_t is larger than mdrCompFrame_t:
457 size += pinmodel->numFrames * sizeof(frame->name);
458 // now add enough space for the uncompressed bones.
459 size += pinmodel->numFrames * pinmodel->numBones * ((sizeof(mdrBone_t) - sizeof(mdrCompBone_t)));
460 }
461
462 mod->dataSize += size;
463 mod->md4 = mdr = ri.Hunk_Alloc( size, h_low );
464
465 // Copy all the values over from the file and fix endian issues in the process, if necessary.
466
467 mdr->ident = LittleLong(pinmodel->ident);
468 mdr->version = pinmodel->version; // Don't need to swap byte order on this one, we already did above.
469 Q_strncpyz(mdr->name, pinmodel->name, sizeof(mdr->name));
470 mdr->numFrames = pinmodel->numFrames;
471 mdr->numBones = pinmodel->numBones;
472 mdr->numLODs = LittleLong(pinmodel->numLODs);
473 mdr->numTags = LittleLong(pinmodel->numTags);
474 // We don't care about offset values, we'll generate them ourselves while loading.
475
476 mod->numLods = mdr->numLODs;
477
478 if ( mdr->numFrames < 1 )
479 {
480 ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has no frames\n", mod_name);
481 return qfalse;
482 }
483
484 /* The first frame will be put into the first free space after the header */
485 frame = (mdrFrame_t *)(mdr + 1);
486 mdr->ofsFrames = (int)((byte *) frame - (byte *) mdr);
487
488 if (pinmodel->ofsFrames < 0)
489 {
490 mdrCompFrame_t *cframe;
491
492 // compressed model...
493 cframe = (mdrCompFrame_t *)((byte *) pinmodel - pinmodel->ofsFrames);
494
495 for(i = 0; i < mdr->numFrames; i++)
496 {
497 for(j = 0; j < 3; j++)
498 {
499 frame->bounds[0][j] = LittleFloat(cframe->bounds[0][j]);
500 frame->bounds[1][j] = LittleFloat(cframe->bounds[1][j]);
501 frame->localOrigin[j] = LittleFloat(cframe->localOrigin[j]);
502 }
503
504 frame->radius = LittleFloat(cframe->radius);
505 frame->name[0] = '\0'; // No name supplied in the compressed version.
506
507 for(j = 0; j < mdr->numBones; j++)
508 {
509 for(k = 0; k < (sizeof(cframe->bones[j].Comp) / 2); k++)
510 {
511 // Do swapping for the uncompressing functions. They seem to use shorts
512 // values only, so I assume this will work. Never tested it on other
513 // platforms, though.
514
515 ((unsigned short *)(cframe->bones[j].Comp))[k] =
516 LittleShort( ((unsigned short *)(cframe->bones[j].Comp))[k] );
517 }
518
519 /* Now do the actual uncompressing */
520 MC_UnCompress(frame->bones[j].matrix, cframe->bones[j].Comp);
521 }
522
523 // Next Frame...
524 cframe = (mdrCompFrame_t *) &cframe->bones[j];
525 frame = (mdrFrame_t *) &frame->bones[j];
526 }
527 }
528 else
529 {
530 mdrFrame_t *curframe;
531
532 // uncompressed model...
533 //
534
535 curframe = (mdrFrame_t *)((byte *) pinmodel + pinmodel->ofsFrames);
536
537 // swap all the frames
538 for ( i = 0 ; i < mdr->numFrames ; i++)
539 {
540 for(j = 0; j < 3; j++)
541 {
542 frame->bounds[0][j] = LittleFloat(curframe->bounds[0][j]);
543 frame->bounds[1][j] = LittleFloat(curframe->bounds[1][j]);
544 frame->localOrigin[j] = LittleFloat(curframe->localOrigin[j]);
545 }
546
547 frame->radius = LittleFloat(curframe->radius);
548 Q_strncpyz(frame->name, curframe->name, sizeof(frame->name));
549
550 for (j = 0; j < (int) (mdr->numBones * sizeof(mdrBone_t) / 4); j++)
551 {
552 ((float *)frame->bones)[j] = LittleFloat( ((float *)curframe->bones)[j] );
553 }
554
555 curframe++;
556 frame++;
557 }
558 }
559
560 // frame should now point to the first free address after all frames.
561 lod = (mdrLOD_t *) frame;
562 mdr->ofsLODs = (int) ((byte *) lod - (byte *)mdr);
563
564 curlod = (mdrLOD_t *)((byte *) pinmodel + LittleLong(pinmodel->ofsLODs));
565
566 // swap all the LOD's
567 for ( l = 0 ; l < mdr->numLODs ; l++)
568 {
569 lod->numSurfaces = LittleLong(curlod->numSurfaces);
570
571 // swap all the surfaces
572 surf = (mdrSurface_t *) (lod + 1);
573 lod->ofsSurfaces = (int)((byte *) surf - (byte *) lod);
574 cursurf = (mdrSurface_t *) ((byte *)curlod + LittleLong(curlod->ofsSurfaces));
575
576 for ( i = 0 ; i < lod->numSurfaces ; i++) {
577 // first do some copying stuff
578
579 surf->ident = SF_MDR;
580 Q_strncpyz(surf->name, cursurf->name, sizeof(surf->name));
581 Q_strncpyz(surf->shader, cursurf->shader, sizeof(surf->shader));
582
583 surf->ofsHeader = (byte *) mdr - (byte *) surf;
584
585 surf->numVerts = LittleLong(cursurf->numVerts);
586 surf->numTriangles = LittleLong(cursurf->numTriangles);
587 // numBoneReferences and BoneReferences generally seem to be unused
588
589 // now do the checks that may fail.
590 if ( surf->numVerts > SHADER_MAX_VERTEXES )
591 {
592 ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i verts on a surface (%i)",
593 mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
594 return qfalse;
595 }
596 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES )
597 {
598 ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i triangles on a surface (%i)",
599 mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
600 return qfalse;
601 }
602 // lowercase the surface name so skin compares are faster
603 Q_strlwr( surf->name );
604
605 // register the shaders
606 sh = R_FindShader(surf->shader, LIGHTMAP_NONE, qtrue);
607 if ( sh->defaultShader ) {
608 surf->shaderIndex = 0;
609 } else {
610 surf->shaderIndex = sh->index;
611 }
612
613 // now copy the vertexes.
614 v = (mdrVertex_t *) (surf + 1);
615 surf->ofsVerts = (int)((byte *) v - (byte *) surf);
616 curv = (mdrVertex_t *) ((byte *)cursurf + LittleLong(cursurf->ofsVerts));
617
618 for(j = 0; j < surf->numVerts; j++)
619 {
620 v->normal[0] = LittleFloat(curv->normal[0]);
621 v->normal[1] = LittleFloat(curv->normal[1]);
622 v->normal[2] = LittleFloat(curv->normal[2]);
623
624 v->texCoords[0] = LittleFloat(curv->texCoords[0]);
625 v->texCoords[1] = LittleFloat(curv->texCoords[1]);
626
627 v->numWeights = LittleLong(curv->numWeights);
628 weight = &v->weights[0];
629 curweight = &curv->weights[0];
630
631 // Now copy all the weights
632 for(k = 0; k < v->numWeights; k++)
633 {
634 weight->boneIndex = LittleLong(curweight->boneIndex);
635 weight->boneWeight = LittleFloat(curweight->boneWeight);
636
637 weight->offset[0] = LittleFloat(curweight->offset[0]);
638 weight->offset[1] = LittleFloat(curweight->offset[1]);
639 weight->offset[2] = LittleFloat(curweight->offset[2]);
640
641 weight++;
642 curweight++;
643 }
644
645 v = (mdrVertex_t *) weight;
646 curv = (mdrVertex_t *) curweight;
647 }
648
649 // we know the offset to the triangles now:
650 tri = (mdrTriangle_t *) v;
651 surf->ofsTriangles = (int)((byte *) tri - (byte *) surf);
652 curtri = (mdrTriangle_t *)((byte *) cursurf + LittleLong(cursurf->ofsTriangles));
653
654 for(j = 0; j < surf->numTriangles; j++)
655 {
656 tri->indexes[0] = curtri->indexes[0];
657 tri->indexes[1] = curtri->indexes[1];
658 tri->indexes[2] = curtri->indexes[2];
659
660 tri++;
661 curtri++;
662 }
663
664 // tri and curtri now point to the end of their surfaces.
665 surf->ofsEnd = (byte *) tri - (byte *) surf;
666
667 // find the next surface
668 surf = (mdrSurface_t *) tri;
669 cursurf = (mdrSurface_t *) curtri;
670 }
671
672 // surf points to the next lod now.
673 lod->ofsEnd = (int)((byte *) surf - (byte *) lod);
674
675 lod = (mdrLOD_t *) surf;
676 curlod = (mdrLOD_t *) cursurf;
677 }
678
679 // lod points to the first tag now, so update the offset too.
680 tag = (mdrTag_t *) lod;
681 mdr->ofsTags = (int)((byte *) tag - (byte *) mdr);
682 curtag = (mdrTag_t *) ((byte *)pinmodel + LittleLong(pinmodel->ofsTags));
683
684 for (i = 0 ; i < mdr->numTags ; i++)
685 {
686 tag->boneIndex = LittleLong(curtag->boneIndex);
687 Q_strncpyz(tag->name, curtag->name, sizeof(tag->name));
688
689 tag++;
690 curtag++;
691 }
692
693 // And finally we know the offset to the end.
694 mdr->ofsEnd = (int)((byte *) tag - (byte *) mdr);
695
696 // phew! we're done.
697
698 return qtrue;
699 }
700 #endif
701
702 /*
703 =================
704 R_LoadMD4
705 =================
706 */
707
R_LoadMD4(model_t * mod,void * buffer,const char * mod_name)708 static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) {
709 int i, j, k, lodindex;
710 md4Header_t *pinmodel, *md4;
711 md4Frame_t *frame;
712 md4LOD_t *lod;
713 md4Surface_t *surf;
714 md4Triangle_t *tri;
715 md4Vertex_t *v;
716 int version;
717 int size;
718 shader_t *sh;
719 int frameSize;
720
721 pinmodel = (md4Header_t *)buffer;
722
723 version = LittleLong (pinmodel->version);
724 if (version != MD4_VERSION) {
725 ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has wrong version (%i should be %i)\n",
726 mod_name, version, MD4_VERSION);
727 return qfalse;
728 }
729
730 mod->type = MOD_MD4;
731 size = LittleLong(pinmodel->ofsEnd);
732 mod->dataSize += size;
733 md4 = mod->md4 = ri.Hunk_Alloc( size, h_low );
734
735 Com_Memcpy(md4, buffer, size);
736
737 LL(md4->ident);
738 LL(md4->version);
739 LL(md4->numFrames);
740 LL(md4->numBones);
741 LL(md4->numLODs);
742 LL(md4->ofsFrames);
743 LL(md4->ofsLODs);
744 md4->ofsEnd = size;
745
746 if ( md4->numFrames < 1 ) {
747 ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has no frames\n", mod_name );
748 return qfalse;
749 }
750
751 // we don't need to swap tags in the renderer, they aren't used
752
753 // swap all the frames
754 frameSize = (size_t)( &((md4Frame_t *)0)->bones[ md4->numBones ] );
755 for ( i = 0 ; i < md4->numFrames ; i++, frame++) {
756 frame = (md4Frame_t *) ( (byte *)md4 + md4->ofsFrames + i * frameSize );
757 frame->radius = LittleFloat( frame->radius );
758 for ( j = 0 ; j < 3 ; j++ ) {
759 frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
760 frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
761 frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
762 }
763 for ( j = 0 ; j < md4->numBones * sizeof( md4Bone_t ) / 4 ; j++ ) {
764 ((float *)frame->bones)[j] = LittleFloat( ((float *)frame->bones)[j] );
765 }
766 }
767
768 // swap all the LOD's
769 lod = (md4LOD_t *) ( (byte *)md4 + md4->ofsLODs );
770 for ( lodindex = 0 ; lodindex < md4->numLODs ; lodindex++ ) {
771
772 // swap all the surfaces
773 surf = (md4Surface_t *) ( (byte *)lod + lod->ofsSurfaces );
774 for ( i = 0 ; i < lod->numSurfaces ; i++) {
775 LL(surf->ident);
776 LL(surf->numTriangles);
777 LL(surf->ofsTriangles);
778 LL(surf->numVerts);
779 LL(surf->ofsVerts);
780 LL(surf->ofsEnd);
781
782 if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
783 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
784 mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
785 }
786 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
787 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
788 mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
789 }
790
791 // change to surface identifier
792 surf->ident = SF_MD4;
793
794 // lowercase the surface name so skin compares are faster
795 Q_strlwr( surf->name );
796
797 // register the shaders
798 sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue );
799 if ( sh->defaultShader ) {
800 surf->shaderIndex = 0;
801 } else {
802 surf->shaderIndex = sh->index;
803 }
804
805 // swap all the triangles
806 tri = (md4Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
807 for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
808 LL(tri->indexes[0]);
809 LL(tri->indexes[1]);
810 LL(tri->indexes[2]);
811 }
812
813 // swap all the vertexes
814 // FIXME
815 // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
816 // in for reference.
817 //v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts + 12);
818 v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts);
819 for ( j = 0 ; j < surf->numVerts ; j++ ) {
820 v->normal[0] = LittleFloat( v->normal[0] );
821 v->normal[1] = LittleFloat( v->normal[1] );
822 v->normal[2] = LittleFloat( v->normal[2] );
823
824 v->texCoords[0] = LittleFloat( v->texCoords[0] );
825 v->texCoords[1] = LittleFloat( v->texCoords[1] );
826
827 v->numWeights = LittleLong( v->numWeights );
828
829 for ( k = 0 ; k < v->numWeights ; k++ ) {
830 v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex );
831 v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight );
832 v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] );
833 v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] );
834 v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] );
835 }
836 // FIXME
837 // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
838 // in for reference.
839 //v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
840 v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights]);
841 }
842
843 // find the next surface
844 surf = (md4Surface_t *)( (byte *)surf + surf->ofsEnd );
845 }
846
847 // find the next LOD
848 lod = (md4LOD_t *)( (byte *)lod + lod->ofsEnd );
849 }
850
851 return qtrue;
852 }
853
854
855
856 //=============================================================================
857
858 /*
859 ** RE_BeginRegistration
860 */
RE_BeginRegistration(glconfig_t * glconfigOut)861 void RE_BeginRegistration( glconfig_t *glconfigOut ) {
862
863 R_Init();
864
865 *glconfigOut = glConfig;
866
867 R_SyncRenderThread();
868
869 tr.viewCluster = -1; // force markleafs to regenerate
870 R_ClearFlares();
871 RE_ClearScene();
872
873 tr.registered = qtrue;
874
875 // NOTE: this sucks, for some reason the first stretch pic is never drawn
876 // without this we'd see a white flash on a level load because the very
877 // first time the level shot would not be drawn
878 RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0);
879 }
880
881 //=============================================================================
882
883 /*
884 ===============
885 R_ModelInit
886 ===============
887 */
R_ModelInit(void)888 void R_ModelInit( void ) {
889 model_t *mod;
890
891 // leave a space for NULL model
892 tr.numModels = 0;
893
894 mod = R_AllocModel();
895 mod->type = MOD_BAD;
896 }
897
898
899 /*
900 ================
901 R_Modellist_f
902 ================
903 */
R_Modellist_f(void)904 void R_Modellist_f( void ) {
905 int i, j;
906 model_t *mod;
907 int total;
908 int lods;
909
910 total = 0;
911 for ( i = 1 ; i < tr.numModels; i++ ) {
912 mod = tr.models[i];
913 lods = 1;
914 for ( j = 1 ; j < MD3_MAX_LODS ; j++ ) {
915 if ( mod->md3[j] && mod->md3[j] != mod->md3[j-1] ) {
916 lods++;
917 }
918 }
919 ri.Printf( PRINT_ALL, "%8i : (%i) %s\n",mod->dataSize, lods, mod->name );
920 total += mod->dataSize;
921 }
922 ri.Printf( PRINT_ALL, "%8i : Total models\n", total );
923
924 #if 0 // not working right with new hunk
925 if ( tr.world ) {
926 ri.Printf( PRINT_ALL, "\n%8i : %s\n", tr.world->dataSize, tr.world->name );
927 }
928 #endif
929 }
930
931
932 //=============================================================================
933
934
935 /*
936 ================
937 R_GetTag
938 ================
939 */
R_GetTag(md3Header_t * mod,int frame,const char * tagName)940 static md3Tag_t *R_GetTag( md3Header_t *mod, int frame, const char *tagName ) {
941 md3Tag_t *tag;
942 int i;
943
944 if ( frame >= mod->numFrames ) {
945 // it is possible to have a bad frame while changing models, so don't error
946 frame = mod->numFrames - 1;
947 }
948
949 tag = (md3Tag_t *)((byte *)mod + mod->ofsTags) + frame * mod->numTags;
950 for ( i = 0 ; i < mod->numTags ; i++, tag++ ) {
951 if ( !strcmp( tag->name, tagName ) ) {
952 return tag; // found it
953 }
954 }
955
956 return NULL;
957 }
958
959 #ifdef RAVENMD4
R_GetAnimTag(mdrHeader_t * mod,int framenum,const char * tagName,md3Tag_t * dest)960 void R_GetAnimTag( mdrHeader_t *mod, int framenum, const char *tagName, md3Tag_t * dest)
961 {
962 int i;
963 int frameSize;
964 mdrFrame_t *frame;
965 mdrTag_t *tag;
966
967 if ( framenum >= mod->numFrames )
968 {
969 // it is possible to have a bad frame while changing models, so don't error
970 framenum = mod->numFrames - 1;
971 }
972
973 tag = (mdrTag_t *)((byte *)mod + mod->ofsTags);
974 for ( i = 0 ; i < mod->numTags ; i++, tag++ )
975 {
976 if ( !strcmp( tag->name, tagName ) )
977 {
978 Q_strncpyz(dest->name, tag->name, sizeof(dest->name));
979
980 // uncompressed model...
981 //
982 frameSize = (long)( &((mdrFrame_t *)0)->bones[ mod->numBones ] );
983 frame = (mdrFrame_t *)((byte *)mod + mod->ofsFrames + framenum * frameSize );
984 #if 1
985 VectorCopy(&frame->bones[tag->boneIndex].matrix[0][0], dest->axis[0] );
986 VectorCopy(&frame->bones[tag->boneIndex].matrix[1][0], dest->axis[1] );
987 VectorCopy(&frame->bones[tag->boneIndex].matrix[2][0], dest->axis[2] );
988 #else
989 {
990 int j,k;
991 for (j=0;j<3;j++)
992 {
993 for (k=0;k<3;k++)
994 dest->axis[j][k]=frame->bones[tag->boneIndex].matrix[k][j];
995 }
996 }
997 #endif
998 dest->origin[0]=frame->bones[tag->boneIndex].matrix[0][3];
999 dest->origin[1]=frame->bones[tag->boneIndex].matrix[1][3];
1000 dest->origin[2]=frame->bones[tag->boneIndex].matrix[2][3];
1001
1002 return;
1003 }
1004 }
1005
1006 AxisClear( dest->axis );
1007 VectorClear( dest->origin );
1008 strcpy(dest->name,"");
1009 }
1010 #endif
1011
1012 /*
1013 ================
1014 R_LerpTag
1015 ================
1016 */
R_LerpTag(orientation_t * tag,qhandle_t handle,int startFrame,int endFrame,float frac,const char * tagName)1017 int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame,
1018 float frac, const char *tagName ) {
1019 md3Tag_t *start, *end;
1020 #ifdef RAVENMD4
1021 md3Tag_t start_space, end_space;
1022 #endif
1023 int i;
1024 float frontLerp, backLerp;
1025 model_t *model;
1026
1027 model = R_GetModelByHandle( handle );
1028 if ( !model->md3[0] )
1029 {
1030 #ifdef RAVENMD4
1031 if(model->md4)
1032 {
1033 start = &start_space;
1034 end = &end_space;
1035 R_GetAnimTag((mdrHeader_t *) model->md4, startFrame, tagName, start);
1036 R_GetAnimTag((mdrHeader_t *) model->md4, endFrame, tagName, end);
1037 }
1038 else
1039 #endif
1040 {
1041
1042 AxisClear( tag->axis );
1043 VectorClear( tag->origin );
1044 return qfalse;
1045
1046 }
1047 }
1048 else
1049 {
1050 start = R_GetTag( model->md3[0], startFrame, tagName );
1051 end = R_GetTag( model->md3[0], endFrame, tagName );
1052 if ( !start || !end ) {
1053 AxisClear( tag->axis );
1054 VectorClear( tag->origin );
1055 return qfalse;
1056 }
1057 }
1058
1059 frontLerp = frac;
1060 backLerp = 1.0f - frac;
1061
1062 for ( i = 0 ; i < 3 ; i++ ) {
1063 tag->origin[i] = start->origin[i] * backLerp + end->origin[i] * frontLerp;
1064 tag->axis[0][i] = start->axis[0][i] * backLerp + end->axis[0][i] * frontLerp;
1065 tag->axis[1][i] = start->axis[1][i] * backLerp + end->axis[1][i] * frontLerp;
1066 tag->axis[2][i] = start->axis[2][i] * backLerp + end->axis[2][i] * frontLerp;
1067 }
1068 VectorNormalize( tag->axis[0] );
1069 VectorNormalize( tag->axis[1] );
1070 VectorNormalize( tag->axis[2] );
1071 return qtrue;
1072 }
1073
1074
1075 /*
1076 ====================
1077 R_ModelBounds
1078 ====================
1079 */
R_ModelBounds(qhandle_t handle,vec3_t mins,vec3_t maxs)1080 void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
1081 model_t *model;
1082 md3Header_t *header;
1083 md3Frame_t *frame;
1084
1085 model = R_GetModelByHandle( handle );
1086
1087 if ( model->bmodel ) {
1088 VectorCopy( model->bmodel->bounds[0], mins );
1089 VectorCopy( model->bmodel->bounds[1], maxs );
1090 return;
1091 }
1092
1093 if ( !model->md3[0] ) {
1094 VectorClear( mins );
1095 VectorClear( maxs );
1096 return;
1097 }
1098
1099 header = model->md3[0];
1100
1101 frame = (md3Frame_t *)( (byte *)header + header->ofsFrames );
1102
1103 VectorCopy( frame->bounds[0], mins );
1104 VectorCopy( frame->bounds[1], maxs );
1105 }
1106
1107