|
|
1.1 root 1: // models.c -- model loading and caching
2:
3: // models are the only shared resource between a client and server running
4: // on the same machine.
5:
6: #include "quakedef.h"
7: #include "r_local.h"
8:
9: model_t *loadmodel;
10: char loadname[32]; // for hunk tags
11:
12: void Mod_LoadSpriteModel (model_t *mod, void *buffer);
13: void Mod_LoadBrushModel (model_t *mod, void *buffer);
14: void Mod_LoadAliasModel (model_t *mod, void *buffer);
15: model_t *Mod_LoadModel (model_t *mod, qboolean crash);
16:
17: byte mod_novis[MAX_MAP_LEAFS/8];
18:
19: #define MAX_MOD_KNOWN 256
20: model_t mod_known[MAX_MOD_KNOWN];
21: int mod_numknown;
22:
23: /*
24: ===============
25: Mod_Init
26: ===============
27: */
28: void Mod_Init (void)
29: {
30: memset (mod_novis, 0xff, sizeof(mod_novis));
31: }
32:
33: /*
34: ===============
35: Mod_Init
36:
37: Caches the data if needed
38: ===============
39: */
40: void *Mod_Extradata (model_t *mod)
41: {
42: void *r;
43:
44: r = Cache_Check (&mod->cache);
45: if (r)
46: return r;
47:
48: Mod_LoadModel (mod, true);
49:
50: if (!mod->cache.data)
51: Sys_Error ("Mod_Extradata: caching failed");
52: return mod->cache.data;
53: }
54:
55: /*
56: ===============
57: Mod_PointInLeaf
58: ===============
59: */
60: mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
61: {
62: mnode_t *node;
63: float d;
64: mplane_t *plane;
65:
66: if (!model || !model->nodes)
67: Sys_Error ("Mod_PointInLeaf: bad model");
68:
69: node = model->nodes;
70: while (1)
71: {
72: if (node->contents < 0)
73: return (mleaf_t *)node;
74: plane = node->plane;
75: d = DotProduct (p,plane->normal) - plane->dist;
76: if (d > 0)
77: node = node->children[0];
78: else
79: node = node->children[1];
80: }
81:
82: return NULL; // never reached
83: }
84:
85:
86: /*
87: ===================
88: Mod_DecompressVis
89: ===================
90: */
91: byte *Mod_DecompressVis (byte *in, model_t *model)
92: {
93: static byte decompressed[MAX_MAP_LEAFS/8];
94: int c;
95: byte *out;
96: int row;
97:
98: row = (model->numleafs+7)>>3;
99: out = decompressed;
100:
101: #if 0
102: memcpy (out, in, row);
103: #else
104: if (!in)
105: { // no vis info, so make all visible
106: while (row)
107: {
108: *out++ = 0xff;
109: row--;
110: }
111: return decompressed;
112: }
113:
114: do
115: {
116: if (*in)
117: {
118: *out++ = *in++;
119: continue;
120: }
121:
122: c = in[1];
123: in += 2;
124: while (c)
125: {
126: *out++ = 0;
127: c--;
128: }
129: } while (out - decompressed < row);
130: #endif
131:
132: return decompressed;
133: }
134:
135: byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
136: {
137: if (leaf == model->leafs)
138: return mod_novis;
139: return Mod_DecompressVis (leaf->compressed_vis, model);
140: }
141:
142: /*
143: ===================
144: Mod_ClearAll
145: ===================
146: */
147: void Mod_ClearAll (void)
148: {
149: int i;
150: model_t *mod;
151:
152: for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
153: if (mod->type != mod_alias)
154: mod->needload = true;
155: }
156:
157: /*
158: ==================
159: Mod_FindName
160:
161: ==================
162: */
163: model_t *Mod_FindName (char *name)
164: {
165: int i;
166: model_t *mod;
167:
168: if (!name[0])
169: Sys_Error ("Mod_ForName: NULL name");
170:
171: //
172: // search the currently loaded models
173: //
174: for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
175: if (!strcmp (mod->name, name) )
176: break;
177:
178: if (i == mod_numknown)
179: {
180: if (mod_numknown == MAX_MOD_KNOWN)
181: Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
182: strcpy (mod->name, name);
183: mod->needload = true;
184: mod_numknown++;
185: }
186:
187: return mod;
188: }
189:
190: /*
191: ==================
192: Mod_TouchModel
193:
194: ==================
195: */
196: void Mod_TouchModel (char *name)
197: {
198: model_t *mod;
199:
200: mod = Mod_FindName (name);
201:
202: if (!mod->needload)
203: {
204: if (mod->type == mod_alias)
205: Cache_Check (&mod->cache);
206: }
207: }
208:
209: /*
210: ==================
211: Mod_LoadModel
212:
213: Loads a model into the cache
214: ==================
215: */
216: model_t *Mod_LoadModel (model_t *mod, qboolean crash)
217: {
218: void *d;
219: unsigned *buf;
220: byte stackbuf[1024]; // avoid dirtying the cache heap
221:
222: if (!mod->needload)
223: {
224: if (mod->type == mod_alias)
225: {
226: d = Cache_Check (&mod->cache);
227: if (d)
228: return mod;
229: }
230: else
231: return mod; // not cached at all
232: }
233:
234: //
235: // because the world is so huge, load it one piece at a time
236: //
237: if (!crash)
238: {
239:
240: }
241:
242: //
243: // load the file
244: //
245: buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
246: if (!buf)
247: {
248: if (crash)
249: Sys_Error ("Mod_NumForName: %s not found", mod->name);
250: return NULL;
251: }
252:
253: //
254: // allocate a new model
255: //
256: COM_FileBase (mod->name, loadname);
257:
258: loadmodel = mod;
259:
260: //
261: // fill it in
262: //
263:
264: // call the apropriate loader
265: mod->needload = false;
266:
267: switch (LittleLong(*(unsigned *)buf))
268: {
269: case IDPOLYHEADER:
270: Mod_LoadAliasModel (mod, buf);
271: break;
272:
273: case IDSPRITEHEADER:
274: Mod_LoadSpriteModel (mod, buf);
275: break;
276:
277: default:
278: Mod_LoadBrushModel (mod, buf);
279: break;
280: }
281:
282: return mod;
283: }
284:
285: /*
286: ==================
287: Mod_ForName
288:
289: Loads in a model for the given name
290: ==================
291: */
292: model_t *Mod_ForName (char *name, qboolean crash)
293: {
294: model_t *mod;
295:
296: mod = Mod_FindName (name);
297:
298: return Mod_LoadModel (mod, crash);
299: }
300:
301:
302: /*
303: ===============================================================================
304:
305: BRUSHMODEL LOADING
306:
307: ===============================================================================
308: */
309:
310: byte *mod_base;
311:
312:
313: /*
314: =================
315: Mod_LoadTextures
316: =================
317: */
318: void Mod_LoadTextures (lump_t *l)
319: {
320: int i, j, pixels, num, max, altmax;
321: miptex_t *mt;
322: texture_t *tx, *tx2;
323: texture_t *anims[10];
324: texture_t *altanims[10];
325: dmiptexlump_t *m;
326:
327: if (!l->filelen)
328: {
329: loadmodel->textures = NULL;
330: return;
331: }
332: m = (dmiptexlump_t *)(mod_base + l->fileofs);
333:
334: m->nummiptex = LittleLong (m->nummiptex);
335:
336: loadmodel->numtextures = m->nummiptex;
337: loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
338:
339: for (i=0 ; i<m->nummiptex ; i++)
340: {
341: m->dataofs[i] = LittleLong(m->dataofs[i]);
342: if (m->dataofs[i] == -1)
343: continue;
344: mt = (miptex_t *)((byte *)m + m->dataofs[i]);
345: mt->width = LittleLong (mt->width);
346: mt->height = LittleLong (mt->height);
347: for (j=0 ; j<MIPLEVELS ; j++)
348: mt->offsets[j] = LittleLong (mt->offsets[j]);
349:
350: if ( (mt->width & 15) || (mt->height & 15) )
351: Sys_Error ("Texture %s is not 16 aligned", mt->name);
352: pixels = mt->width*mt->height/64*85;
353: tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
354: loadmodel->textures[i] = tx;
355:
356: memcpy (tx->name, mt->name, sizeof(tx->name));
357: tx->width = mt->width;
358: tx->height = mt->height;
359: for (j=0 ; j<MIPLEVELS ; j++)
360: tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
361: // the pixels immediately follow the structures
362: memcpy ( tx+1, mt+1, pixels);
363:
364: if (!Q_strncmp(mt->name,"sky",3))
365: R_InitSky (tx);
366: }
367:
368: //
369: // sequence the animations
370: //
371: for (i=0 ; i<m->nummiptex ; i++)
372: {
373: tx = loadmodel->textures[i];
374: if (!tx || tx->name[0] != '+')
375: continue;
376: if (tx->anim_next)
377: continue; // allready sequenced
378:
379: // find the number of frames in the animation
380: memset (anims, 0, sizeof(anims));
381: memset (altanims, 0, sizeof(altanims));
382:
383: max = tx->name[1];
384: altmax = 0;
385: if (max >= 'a' && max <= 'z')
386: max -= 'a' - 'A';
387: if (max >= '0' && max <= '9')
388: {
389: max -= '0';
390: altmax = 0;
391: anims[max] = tx;
392: max++;
393: }
394: else if (max >= 'A' && max <= 'J')
395: {
396: altmax = max - 'A';
397: max = 0;
398: altanims[altmax] = tx;
399: altmax++;
400: }
401: else
402: Sys_Error ("Bad animating texture %s", tx->name);
403:
404: for (j=i+1 ; j<m->nummiptex ; j++)
405: {
406: tx2 = loadmodel->textures[j];
407: if (!tx2 || tx2->name[0] != '+')
408: continue;
409: if (strcmp (tx2->name+2, tx->name+2))
410: continue;
411:
412: num = tx2->name[1];
413: if (num >= 'a' && num <= 'z')
414: num -= 'a' - 'A';
415: if (num >= '0' && num <= '9')
416: {
417: num -= '0';
418: anims[num] = tx2;
419: if (num+1 > max)
420: max = num + 1;
421: }
422: else if (num >= 'A' && num <= 'J')
423: {
424: num = num - 'A';
425: altanims[num] = tx2;
426: if (num+1 > altmax)
427: altmax = num+1;
428: }
429: else
430: Sys_Error ("Bad animating texture %s", tx->name);
431: }
432:
433: #define ANIM_CYCLE 2
434: // link them all together
435: for (j=0 ; j<max ; j++)
436: {
437: tx2 = anims[j];
438: if (!tx2)
439: Sys_Error ("Missing frame %i of %s",j, tx->name);
440: tx2->anim_total = max * ANIM_CYCLE;
441: tx2->anim_min = j * ANIM_CYCLE;
442: tx2->anim_max = (j+1) * ANIM_CYCLE;
443: tx2->anim_next = anims[ (j+1)%max ];
444: if (altmax)
445: tx2->alternate_anims = altanims[0];
446: }
447: for (j=0 ; j<altmax ; j++)
448: {
449: tx2 = altanims[j];
450: if (!tx2)
451: Sys_Error ("Missing frame %i of %s",j, tx->name);
452: tx2->anim_total = altmax * ANIM_CYCLE;
453: tx2->anim_min = j * ANIM_CYCLE;
454: tx2->anim_max = (j+1) * ANIM_CYCLE;
455: tx2->anim_next = altanims[ (j+1)%altmax ];
456: if (max)
457: tx2->alternate_anims = anims[0];
458: }
459: }
460: }
461:
462: /*
463: =================
464: Mod_LoadLighting
465: =================
466: */
467: void Mod_LoadLighting (lump_t *l)
468: {
469: if (!l->filelen)
470: {
471: loadmodel->lightdata = NULL;
472: return;
473: }
474: loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
475: memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
476: }
477:
478:
479: /*
480: =================
481: Mod_LoadVisibility
482: =================
483: */
484: void Mod_LoadVisibility (lump_t *l)
485: {
486: if (!l->filelen)
487: {
488: loadmodel->visdata = NULL;
489: return;
490: }
491: loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);
492: memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
493: }
494:
495:
496: /*
497: =================
498: Mod_LoadEntities
499: =================
500: */
501: void Mod_LoadEntities (lump_t *l)
502: {
503: if (!l->filelen)
504: {
505: loadmodel->entities = NULL;
506: return;
507: }
508: loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);
509: memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
510: }
511:
512:
513: /*
514: =================
515: Mod_LoadVertexes
516: =================
517: */
518: void Mod_LoadVertexes (lump_t *l)
519: {
520: dvertex_t *in;
521: mvertex_t *out;
522: int i, count;
523:
524: in = (void *)(mod_base + l->fileofs);
525: if (l->filelen % sizeof(*in))
526: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
527: count = l->filelen / sizeof(*in);
528: out = Hunk_AllocName ( count*sizeof(*out), loadname);
529:
530: loadmodel->vertexes = out;
531: loadmodel->numvertexes = count;
532:
533: for ( i=0 ; i<count ; i++, in++, out++)
534: {
535: out->position[0] = LittleFloat (in->point[0]);
536: out->position[1] = LittleFloat (in->point[1]);
537: out->position[2] = LittleFloat (in->point[2]);
538: }
539: }
540:
541: /*
542: =================
543: Mod_LoadSubmodels
544: =================
545: */
546: void Mod_LoadSubmodels (lump_t *l)
547: {
548: dmodel_t *in;
549: dmodel_t *out;
550: int i, j, count;
551:
552: in = (void *)(mod_base + l->fileofs);
553: if (l->filelen % sizeof(*in))
554: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
555: count = l->filelen / sizeof(*in);
556: out = Hunk_AllocName ( count*sizeof(*out), loadname);
557:
558: loadmodel->submodels = out;
559: loadmodel->numsubmodels = count;
560:
561: for ( i=0 ; i<count ; i++, in++, out++)
562: {
563: for (j=0 ; j<3 ; j++)
564: { // spread the mins / maxs by a pixel
565: out->mins[j] = LittleFloat (in->mins[j]) - 1;
566: out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
567: out->origin[j] = LittleFloat (in->origin[j]);
568: }
569: for (j=0 ; j<MAX_MAP_HULLS ; j++)
570: out->headnode[j] = LittleLong (in->headnode[j]);
571: out->visleafs = LittleLong (in->visleafs);
572: out->firstface = LittleLong (in->firstface);
573: out->numfaces = LittleLong (in->numfaces);
574: }
575: }
576:
577: /*
578: =================
579: Mod_LoadEdges
580: =================
581: */
582: void Mod_LoadEdges (lump_t *l)
583: {
584: dedge_t *in;
585: medge_t *out;
586: int i, count;
587:
588: in = (void *)(mod_base + l->fileofs);
589: if (l->filelen % sizeof(*in))
590: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
591: count = l->filelen / sizeof(*in);
592: out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
593:
594: loadmodel->edges = out;
595: loadmodel->numedges = count;
596:
597: for ( i=0 ; i<count ; i++, in++, out++)
598: {
599: out->v[0] = (unsigned short)LittleShort(in->v[0]);
600: out->v[1] = (unsigned short)LittleShort(in->v[1]);
601: }
602: }
603:
604: /*
605: =================
606: Mod_LoadTexinfo
607: =================
608: */
609: void Mod_LoadTexinfo (lump_t *l)
610: {
611: texinfo_t *in;
612: mtexinfo_t *out;
613: int i, j, count;
614: int miptex;
615: float len1, len2;
616:
617: in = (void *)(mod_base + l->fileofs);
618: if (l->filelen % sizeof(*in))
619: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
620: count = l->filelen / sizeof(*in);
621: out = Hunk_AllocName ( count*sizeof(*out), loadname);
622:
623: loadmodel->texinfo = out;
624: loadmodel->numtexinfo = count;
625:
626: for ( i=0 ; i<count ; i++, in++, out++)
627: {
628: for (j=0 ; j<8 ; j++)
629: out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
630: len1 = Length (out->vecs[0]);
631: len2 = Length (out->vecs[1]);
632: len1 = (len1 + len2)/2;
633: if (len1 < 0.32)
634: out->mipadjust = 4;
635: else if (len1 < 0.49)
636: out->mipadjust = 3;
637: else if (len1 < 0.99)
638: out->mipadjust = 2;
639: else
640: out->mipadjust = 1;
641: #if 0
642: if (len1 + len2 < 0.001)
643: out->mipadjust = 1; // don't crash
644: else
645: out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
646: #endif
647:
648: miptex = LittleLong (in->miptex);
649: out->flags = LittleLong (in->flags);
650:
651: if (!loadmodel->textures)
652: {
653: out->texture = r_notexture_mip; // checkerboard texture
654: out->flags = 0;
655: }
656: else
657: {
658: if (miptex >= loadmodel->numtextures)
659: Sys_Error ("miptex >= loadmodel->numtextures");
660: out->texture = loadmodel->textures[miptex];
661: if (!out->texture)
662: {
663: out->texture = r_notexture_mip; // texture not found
664: out->flags = 0;
665: }
666: }
667: }
668: }
669:
670: /*
671: ================
672: CalcSurfaceExtents
673:
674: Fills in s->texturemins[] and s->extents[]
675: ================
676: */
677: void CalcSurfaceExtents (msurface_t *s)
678: {
679: float mins[2], maxs[2], val;
680: int i,j, e;
681: mvertex_t *v;
682: mtexinfo_t *tex;
683: int bmins[2], bmaxs[2];
684:
685: mins[0] = mins[1] = 999999;
686: maxs[0] = maxs[1] = -99999;
687:
688: tex = s->texinfo;
689:
690: for (i=0 ; i<s->numedges ; i++)
691: {
692: e = loadmodel->surfedges[s->firstedge+i];
693: if (e >= 0)
694: v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
695: else
696: v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
697:
698: for (j=0 ; j<2 ; j++)
699: {
700: val = v->position[0] * tex->vecs[j][0] +
701: v->position[1] * tex->vecs[j][1] +
702: v->position[2] * tex->vecs[j][2] +
703: tex->vecs[j][3];
704: if (val < mins[j])
705: mins[j] = val;
706: if (val > maxs[j])
707: maxs[j] = val;
708: }
709: }
710:
711: for (i=0 ; i<2 ; i++)
712: {
713: bmins[i] = floor(mins[i]/16);
714: bmaxs[i] = ceil(maxs[i]/16);
715:
716: s->texturemins[i] = bmins[i] * 16;
717: s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
718: if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
719: Sys_Error ("Bad surface extents");
720: }
721: }
722:
723:
724: /*
725: =================
726: Mod_LoadFaces
727: =================
728: */
729: void Mod_LoadFaces (lump_t *l)
730: {
731: dface_t *in;
732: msurface_t *out;
733: int i, count, surfnum;
734: int planenum, side;
735:
736: in = (void *)(mod_base + l->fileofs);
737: if (l->filelen % sizeof(*in))
738: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
739: count = l->filelen / sizeof(*in);
740: out = Hunk_AllocName ( count*sizeof(*out), loadname);
741:
742: loadmodel->surfaces = out;
743: loadmodel->numsurfaces = count;
744:
745: for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
746: {
747: out->firstedge = LittleLong(in->firstedge);
748: out->numedges = LittleShort(in->numedges);
749: out->flags = 0;
750:
751: planenum = LittleShort(in->planenum);
752: side = LittleShort(in->side);
753: if (side)
754: out->flags |= SURF_PLANEBACK;
755:
756: out->plane = loadmodel->planes + planenum;
757:
758: out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
759:
760: CalcSurfaceExtents (out);
761:
762: // lighting info
763:
764: for (i=0 ; i<MAXLIGHTMAPS ; i++)
765: out->styles[i] = in->styles[i];
766: i = LittleLong(in->lightofs);
767: if (i == -1)
768: out->samples = NULL;
769: else
770: out->samples = loadmodel->lightdata + i;
771:
772: // set the drawing flags flag
773:
774: if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky
775: {
776: out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
777: continue;
778: }
779:
780: if (!Q_strncmp(out->texinfo->texture->name,"*",1)) // turbulent
781: {
782: out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
783: for (i=0 ; i<2 ; i++)
784: {
785: out->extents[i] = 16384;
786: out->texturemins[i] = -8192;
787: }
788: continue;
789: }
790: }
791: }
792:
793:
794: /*
795: =================
796: Mod_SetParent
797: =================
798: */
799: void Mod_SetParent (mnode_t *node, mnode_t *parent)
800: {
801: node->parent = parent;
802: if (node->contents < 0)
803: return;
804: Mod_SetParent (node->children[0], node);
805: Mod_SetParent (node->children[1], node);
806: }
807:
808: /*
809: =================
810: Mod_LoadNodes
811: =================
812: */
813: void Mod_LoadNodes (lump_t *l)
814: {
815: int i, j, count, p;
816: dnode_t *in;
817: mnode_t *out;
818:
819: in = (void *)(mod_base + l->fileofs);
820: if (l->filelen % sizeof(*in))
821: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
822: count = l->filelen / sizeof(*in);
823: out = Hunk_AllocName ( count*sizeof(*out), loadname);
824:
825: loadmodel->nodes = out;
826: loadmodel->numnodes = count;
827:
828: for ( i=0 ; i<count ; i++, in++, out++)
829: {
830: for (j=0 ; j<3 ; j++)
831: {
832: out->minmaxs[j] = LittleShort (in->mins[j]);
833: out->minmaxs[3+j] = LittleShort (in->maxs[j]);
834: }
835:
836: p = LittleLong(in->planenum);
837: out->plane = loadmodel->planes + p;
838:
839: out->firstsurface = LittleShort (in->firstface);
840: out->numsurfaces = LittleShort (in->numfaces);
841:
842: for (j=0 ; j<2 ; j++)
843: {
844: p = LittleShort (in->children[j]);
845: if (p >= 0)
846: out->children[j] = loadmodel->nodes + p;
847: else
848: out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
849: }
850: }
851:
852: Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
853: }
854:
855: /*
856: =================
857: Mod_LoadLeafs
858: =================
859: */
860: void Mod_LoadLeafs (lump_t *l)
861: {
862: dleaf_t *in;
863: mleaf_t *out;
864: int i, j, count, p;
865:
866: in = (void *)(mod_base + l->fileofs);
867: if (l->filelen % sizeof(*in))
868: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
869: count = l->filelen / sizeof(*in);
870: out = Hunk_AllocName ( count*sizeof(*out), loadname);
871:
872: loadmodel->leafs = out;
873: loadmodel->numleafs = count;
874:
875: for ( i=0 ; i<count ; i++, in++, out++)
876: {
877: for (j=0 ; j<3 ; j++)
878: {
879: out->minmaxs[j] = LittleShort (in->mins[j]);
880: out->minmaxs[3+j] = LittleShort (in->maxs[j]);
881: }
882:
883: p = LittleLong(in->contents);
884: out->contents = p;
885:
886: out->firstmarksurface = loadmodel->marksurfaces +
887: LittleShort(in->firstmarksurface);
888: out->nummarksurfaces = LittleShort(in->nummarksurfaces);
889:
890: p = LittleLong(in->visofs);
891: if (p == -1)
892: out->compressed_vis = NULL;
893: else
894: out->compressed_vis = loadmodel->visdata + p;
895: out->efrags = NULL;
896:
897: for (j=0 ; j<4 ; j++)
898: out->ambient_sound_level[j] = in->ambient_level[j];
899: }
900: }
901:
902: /*
903: =================
904: Mod_LoadClipnodes
905: =================
906: */
907: void Mod_LoadClipnodes (lump_t *l)
908: {
909: dclipnode_t *in, *out;
910: int i, count;
911: hull_t *hull;
912:
913: in = (void *)(mod_base + l->fileofs);
914: if (l->filelen % sizeof(*in))
915: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
916: count = l->filelen / sizeof(*in);
917: out = Hunk_AllocName ( count*sizeof(*out), loadname);
918:
919: loadmodel->clipnodes = out;
920: loadmodel->numclipnodes = count;
921:
922: hull = &loadmodel->hulls[1];
923: hull->clipnodes = out;
924: hull->firstclipnode = 0;
925: hull->lastclipnode = count-1;
926: hull->planes = loadmodel->planes;
927: hull->clip_mins[0] = -16;
928: hull->clip_mins[1] = -16;
929: hull->clip_mins[2] = -24;
930: hull->clip_maxs[0] = 16;
931: hull->clip_maxs[1] = 16;
932: hull->clip_maxs[2] = 32;
933:
934: hull = &loadmodel->hulls[2];
935: hull->clipnodes = out;
936: hull->firstclipnode = 0;
937: hull->lastclipnode = count-1;
938: hull->planes = loadmodel->planes;
939: hull->clip_mins[0] = -32;
940: hull->clip_mins[1] = -32;
941: hull->clip_mins[2] = -24;
942: hull->clip_maxs[0] = 32;
943: hull->clip_maxs[1] = 32;
944: hull->clip_maxs[2] = 64;
945:
946: for (i=0 ; i<count ; i++, out++, in++)
947: {
948: out->planenum = LittleLong(in->planenum);
949: out->children[0] = LittleShort(in->children[0]);
950: out->children[1] = LittleShort(in->children[1]);
951: }
952: }
953:
954: /*
955: =================
956: Mod_MakeHull0
957:
958: Deplicate the drawing hull structure as a clipping hull
959: =================
960: */
961: void Mod_MakeHull0 (void)
962: {
963: mnode_t *in, *child;
964: dclipnode_t *out;
965: int i, j, count;
966: hull_t *hull;
967:
968: hull = &loadmodel->hulls[0];
969:
970: in = loadmodel->nodes;
971: count = loadmodel->numnodes;
972: out = Hunk_AllocName ( count*sizeof(*out), loadname);
973:
974: hull->clipnodes = out;
975: hull->firstclipnode = 0;
976: hull->lastclipnode = count-1;
977: hull->planes = loadmodel->planes;
978:
979: for (i=0 ; i<count ; i++, out++, in++)
980: {
981: out->planenum = in->plane - loadmodel->planes;
982: for (j=0 ; j<2 ; j++)
983: {
984: child = in->children[j];
985: if (child->contents < 0)
986: out->children[j] = child->contents;
987: else
988: out->children[j] = child - loadmodel->nodes;
989: }
990: }
991: }
992:
993: /*
994: =================
995: Mod_LoadMarksurfaces
996: =================
997: */
998: void Mod_LoadMarksurfaces (lump_t *l)
999: {
1000: int i, j, count;
1001: short *in;
1002: msurface_t **out;
1003:
1004: in = (void *)(mod_base + l->fileofs);
1005: if (l->filelen % sizeof(*in))
1006: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1007: count = l->filelen / sizeof(*in);
1008: out = Hunk_AllocName ( count*sizeof(*out), loadname);
1009:
1010: loadmodel->marksurfaces = out;
1011: loadmodel->nummarksurfaces = count;
1012:
1013: for ( i=0 ; i<count ; i++)
1014: {
1015: j = LittleShort(in[i]);
1016: if (j >= loadmodel->numsurfaces)
1017: Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
1018: out[i] = loadmodel->surfaces + j;
1019: }
1020: }
1021:
1022: /*
1023: =================
1024: Mod_LoadSurfedges
1025: =================
1026: */
1027: void Mod_LoadSurfedges (lump_t *l)
1028: {
1029: int i, count;
1030: int *in, *out;
1031:
1032: in = (void *)(mod_base + l->fileofs);
1033: if (l->filelen % sizeof(*in))
1034: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1035: count = l->filelen / sizeof(*in);
1036: out = Hunk_AllocName ( count*sizeof(*out), loadname);
1037:
1038: loadmodel->surfedges = out;
1039: loadmodel->numsurfedges = count;
1040:
1041: for ( i=0 ; i<count ; i++)
1042: out[i] = LittleLong (in[i]);
1043: }
1044:
1045: /*
1046: =================
1047: Mod_LoadPlanes
1048: =================
1049: */
1050: void Mod_LoadPlanes (lump_t *l)
1051: {
1052: int i, j;
1053: mplane_t *out;
1054: dplane_t *in;
1055: int count;
1056: int bits;
1057:
1058: in = (void *)(mod_base + l->fileofs);
1059: if (l->filelen % sizeof(*in))
1060: Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1061: count = l->filelen / sizeof(*in);
1062: out = Hunk_AllocName ( count*2*sizeof(*out), loadname);
1063:
1064: loadmodel->planes = out;
1065: loadmodel->numplanes = count;
1066:
1067: for ( i=0 ; i<count ; i++, in++, out++)
1068: {
1069: bits = 0;
1070: for (j=0 ; j<3 ; j++)
1071: {
1072: out->normal[j] = LittleFloat (in->normal[j]);
1073: if (out->normal[j] < 0)
1074: bits |= 1<<j;
1075: }
1076:
1077: out->dist = LittleFloat (in->dist);
1078: out->type = LittleLong (in->type);
1079: out->signbits = bits;
1080: }
1081: }
1082:
1083:
1084: /*
1085: =================
1086: Mod_LoadBrushModel
1087: =================
1088: */
1089: void Mod_LoadBrushModel (model_t *mod, void *buffer)
1090: {
1091: int i, j;
1092: dheader_t *header;
1093: dmodel_t *bm;
1094:
1095: loadmodel->type = mod_brush;
1096:
1097: header = (dheader_t *)buffer;
1098:
1099: i = LittleLong (header->version);
1100: if (i != BSPVERSION)
1101: Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
1102:
1103: // swap all the lumps
1104: mod_base = (byte *)header;
1105:
1106: for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
1107: ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
1108:
1109: // load into heap
1110:
1111: Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
1112: Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
1113: Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
1114: Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
1115: Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
1116: Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
1117: Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
1118: Mod_LoadFaces (&header->lumps[LUMP_FACES]);
1119: Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
1120: Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
1121: Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
1122: Mod_LoadNodes (&header->lumps[LUMP_NODES]);
1123: Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
1124: Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
1125: Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
1126:
1127: Mod_MakeHull0 ();
1128:
1129: mod->numframes = 2; // regular and alternate animation
1130:
1131: //
1132: // set up the submodels (FIXME: this is confusing)
1133: //
1134: for (i=0 ; i<mod->numsubmodels ; i++)
1135: {
1136: bm = &mod->submodels[i];
1137:
1138: mod->hulls[0].firstclipnode = bm->headnode[0];
1139: for (j=1 ; j<MAX_MAP_HULLS ; j++)
1140: {
1141: mod->hulls[j].firstclipnode = bm->headnode[j];
1142: mod->hulls[j].lastclipnode = mod->numclipnodes-1;
1143: }
1144:
1145: mod->firstmodelsurface = bm->firstface;
1146: mod->nummodelsurfaces = bm->numfaces;
1147:
1148: VectorCopy (bm->maxs, mod->maxs);
1149: VectorCopy (bm->mins, mod->mins);
1150:
1151: mod->numleafs = bm->visleafs;
1152:
1153: if (i < mod->numsubmodels-1)
1154: { // duplicate the basic information
1155: char name[10];
1156:
1157: sprintf (name, "*%i", i+1);
1158: loadmodel = Mod_FindName (name);
1159: *loadmodel = *mod;
1160: strcpy (loadmodel->name, name);
1161: mod = loadmodel;
1162: }
1163: }
1164: }
1165:
1166: /*
1167: ==============================================================================
1168:
1169: ALIAS MODELS
1170:
1171: ==============================================================================
1172: */
1173:
1174: /*
1175: =================
1176: Mod_LoadAliasFrame
1177: =================
1178: */
1179: void * Mod_LoadAliasFrame (void * pin, int *pframeindex, int numv,
1180: trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
1181: {
1182: trivertx_t *pframe, *pinframe;
1183: int i, j;
1184: daliasframe_t *pdaliasframe;
1185:
1186: pdaliasframe = (daliasframe_t *)pin;
1187:
1188: strcpy (name, pdaliasframe->name);
1189:
1190: for (i=0 ; i<3 ; i++)
1191: {
1192: // these are byte values, so we don't have to worry about
1193: // endianness
1194: pbboxmin->v[i] = pdaliasframe->bboxmin.v[i];
1195: pbboxmax->v[i] = pdaliasframe->bboxmax.v[i];
1196: }
1197:
1198: pinframe = (trivertx_t *)(pdaliasframe + 1);
1199: pframe = Hunk_AllocName (numv * sizeof(*pframe), loadname);
1200:
1201: *pframeindex = (byte *)pframe - (byte *)pheader;
1202:
1203: for (j=0 ; j<numv ; j++)
1204: {
1205: int k;
1206:
1207: // these are all byte values, so no need to deal with endianness
1208: pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
1209:
1210: for (k=0 ; k<3 ; k++)
1211: {
1212: pframe[j].v[k] = pinframe[j].v[k];
1213: }
1214: }
1215:
1216: pinframe += numv;
1217:
1218: return (void *)pinframe;
1219: }
1220:
1221:
1222: /*
1223: =================
1224: Mod_LoadAliasGroup
1225: =================
1226: */
1227: void * Mod_LoadAliasGroup (void * pin, int *pframeindex, int numv,
1228: trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
1229: {
1230: daliasgroup_t *pingroup;
1231: maliasgroup_t *paliasgroup;
1232: int i, numframes;
1233: daliasinterval_t *pin_intervals;
1234: float *poutintervals;
1235: void *ptemp;
1236:
1237: pingroup = (daliasgroup_t *)pin;
1238:
1239: numframes = LittleLong (pingroup->numframes);
1240:
1241: paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) +
1242: (numframes - 1) * sizeof (paliasgroup->frames[0]), loadname);
1243:
1244: paliasgroup->numframes = numframes;
1245:
1246: for (i=0 ; i<3 ; i++)
1247: {
1248: // these are byte values, so we don't have to worry about endianness
1249: pbboxmin->v[i] = pingroup->bboxmin.v[i];
1250: pbboxmax->v[i] = pingroup->bboxmax.v[i];
1251: }
1252:
1253: *pframeindex = (byte *)paliasgroup - (byte *)pheader;
1254:
1255: pin_intervals = (daliasinterval_t *)(pingroup + 1);
1256:
1257: poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
1258:
1259: paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
1260:
1261: for (i=0 ; i<numframes ; i++)
1262: {
1263: *poutintervals = LittleFloat (pin_intervals->interval);
1264: if (*poutintervals <= 0.0)
1265: Sys_Error ("Mod_LoadAliasGroup: interval<=0");
1266:
1267: poutintervals++;
1268: pin_intervals++;
1269: }
1270:
1271: ptemp = (void *)pin_intervals;
1272:
1273: for (i=0 ; i<numframes ; i++)
1274: {
1275: ptemp = Mod_LoadAliasFrame (ptemp,
1276: &paliasgroup->frames[i].frame,
1277: numv,
1278: &paliasgroup->frames[i].bboxmin,
1279: &paliasgroup->frames[i].bboxmax,
1280: pheader, name);
1281: }
1282:
1283: return ptemp;
1284: }
1285:
1286:
1287: /*
1288: =================
1289: Mod_LoadAliasSkin
1290: =================
1291: */
1292: void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinsize,
1293: aliashdr_t *pheader)
1294: {
1295: int i;
1296: byte *pskin, *pinskin;
1297: unsigned short *pusskin;
1298:
1299: pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname);
1300: pinskin = (byte *)pin;
1301: *pskinindex = (byte *)pskin - (byte *)pheader;
1302:
1303: if (r_pixbytes == 1)
1304: {
1305: Q_memcpy (pskin, pinskin, skinsize);
1306: }
1307: else if (r_pixbytes == 2)
1308: {
1309: pusskin = (unsigned short *)pskin;
1310:
1311: for (i=0 ; i<skinsize ; i++)
1312: pusskin[i] = d_8to16table[pinskin[i]];
1313: }
1314: else
1315: {
1316: Sys_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: %d\n",
1317: r_pixbytes);
1318: }
1319:
1320: pinskin += skinsize;
1321:
1322: return ((void *)pinskin);
1323: }
1324:
1325:
1326: /*
1327: =================
1328: Mod_LoadAliasSkinGroup
1329: =================
1330: */
1331: void * Mod_LoadAliasSkinGroup (void * pin, int *pskinindex, int skinsize,
1332: aliashdr_t *pheader)
1333: {
1334: daliasskingroup_t *pinskingroup;
1335: maliasskingroup_t *paliasskingroup;
1336: int i, numskins;
1337: daliasskininterval_t *pinskinintervals;
1338: float *poutskinintervals;
1339: void *ptemp;
1340:
1341: pinskingroup = (daliasskingroup_t *)pin;
1342:
1343: numskins = LittleLong (pinskingroup->numskins);
1344:
1345: paliasskingroup = Hunk_AllocName (sizeof (maliasskingroup_t) +
1346: (numskins - 1) * sizeof (paliasskingroup->skindescs[0]),
1347: loadname);
1348:
1349: paliasskingroup->numskins = numskins;
1350:
1351: *pskinindex = (byte *)paliasskingroup - (byte *)pheader;
1352:
1353: pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
1354:
1355: poutskinintervals = Hunk_AllocName (numskins * sizeof (float),loadname);
1356:
1357: paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
1358:
1359: for (i=0 ; i<numskins ; i++)
1360: {
1361: *poutskinintervals = LittleFloat (pinskinintervals->interval);
1362: if (*poutskinintervals <= 0)
1363: Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0");
1364:
1365: poutskinintervals++;
1366: pinskinintervals++;
1367: }
1368:
1369: ptemp = (void *)pinskinintervals;
1370:
1371: for (i=0 ; i<numskins ; i++)
1372: {
1373: ptemp = Mod_LoadAliasSkin (ptemp,
1374: &paliasskingroup->skindescs[i].skin, skinsize, pheader);
1375: }
1376:
1377: return ptemp;
1378: }
1379:
1380:
1381: /*
1382: =================
1383: Mod_LoadAliasModel
1384: =================
1385: */
1386: void Mod_LoadAliasModel (model_t *mod, void *buffer)
1387: {
1388: int i;
1389: mdl_t *pmodel, *pinmodel;
1390: stvert_t *pstverts, *pinstverts;
1391: aliashdr_t *pheader;
1392: mtriangle_t *ptri;
1393: dtriangle_t *pintriangles;
1394: int version, numframes, numskins;
1395: int size;
1396: daliasframetype_t *pframetype;
1397: daliasskintype_t *pskintype;
1398: maliasskindesc_t *pskindesc;
1399: int skinsize;
1400: int start, end, total;
1401:
1402: start = Hunk_LowMark ();
1403:
1404: pinmodel = (mdl_t *)buffer;
1405:
1406: version = LittleLong (pinmodel->version);
1407: if (version != ALIAS_VERSION)
1408: Sys_Error ("%s has wrong version number (%i should be %i)",
1409: mod->name, version, ALIAS_VERSION);
1410:
1411: //
1412: // allocate space for a working header, plus all the data except the frames,
1413: // skin and group info
1414: //
1415: size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) *
1416: sizeof (pheader->frames[0]) +
1417: sizeof (mdl_t) +
1418: LittleLong (pinmodel->numverts) * sizeof (stvert_t) +
1419: LittleLong (pinmodel->numtris) * sizeof (mtriangle_t);
1420:
1421: pheader = Hunk_AllocName (size, loadname);
1422: pmodel = (mdl_t *) ((byte *)&pheader[1] +
1423: (LittleLong (pinmodel->numframes) - 1) *
1424: sizeof (pheader->frames[0]));
1425:
1426: // mod->cache.data = pheader;
1427: mod->flags = LittleLong (pinmodel->flags);
1428:
1429: //
1430: // endian-adjust and copy the data, starting with the alias model header
1431: //
1432: pmodel->boundingradius = LittleFloat (pinmodel->boundingradius);
1433: pmodel->numskins = LittleLong (pinmodel->numskins);
1434: pmodel->skinwidth = LittleLong (pinmodel->skinwidth);
1435: pmodel->skinheight = LittleLong (pinmodel->skinheight);
1436:
1437: if (pmodel->skinheight > MAX_LBM_HEIGHT)
1438: Sys_Error ("model %s has a skin taller than %d", mod->name,
1439: MAX_LBM_HEIGHT);
1440:
1441: pmodel->numverts = LittleLong (pinmodel->numverts);
1442:
1443: if (pmodel->numverts <= 0)
1444: Sys_Error ("model %s has no vertices", mod->name);
1445:
1446: if (pmodel->numverts > MAXALIASVERTS)
1447: Sys_Error ("model %s has too many vertices", mod->name);
1448:
1449: pmodel->numtris = LittleLong (pinmodel->numtris);
1450:
1451: if (pmodel->numtris <= 0)
1452: Sys_Error ("model %s has no triangles", mod->name);
1453:
1454: pmodel->numframes = LittleLong (pinmodel->numframes);
1455: pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
1456: mod->synctype = LittleLong (pinmodel->synctype);
1457: mod->numframes = pmodel->numframes;
1458:
1459: for (i=0 ; i<3 ; i++)
1460: {
1461: pmodel->scale[i] = LittleFloat (pinmodel->scale[i]);
1462: pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
1463: pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
1464: }
1465:
1466: numskins = pmodel->numskins;
1467: numframes = pmodel->numframes;
1468:
1469: if (pmodel->skinwidth & 0x03)
1470: Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4");
1471:
1472: pheader->model = (byte *)pmodel - (byte *)pheader;
1473:
1474: //
1475: // load the skins
1476: //
1477: skinsize = pmodel->skinheight * pmodel->skinwidth;
1478:
1479: if (numskins < 1)
1480: Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
1481:
1482: pskintype = (daliasskintype_t *)&pinmodel[1];
1483:
1484: pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t),
1485: loadname);
1486:
1487: pheader->skindesc = (byte *)pskindesc - (byte *)pheader;
1488:
1489: for (i=0 ; i<numskins ; i++)
1490: {
1491: aliasskintype_t skintype;
1492:
1493: skintype = LittleLong (pskintype->type);
1494: pskindesc[i].type = skintype;
1495:
1496: if (skintype == ALIAS_SKIN_SINGLE)
1497: {
1498: pskintype = (daliasskintype_t *)
1499: Mod_LoadAliasSkin (pskintype + 1,
1500: &pskindesc[i].skin,
1501: skinsize, pheader);
1502: }
1503: else
1504: {
1505: pskintype = (daliasskintype_t *)
1506: Mod_LoadAliasSkinGroup (pskintype + 1,
1507: &pskindesc[i].skin,
1508: skinsize, pheader);
1509: }
1510: }
1511:
1512: //
1513: // set base s and t vertices
1514: //
1515: pstverts = (stvert_t *)&pmodel[1];
1516: pinstverts = (stvert_t *)pskintype;
1517:
1518: pheader->stverts = (byte *)pstverts - (byte *)pheader;
1519:
1520: for (i=0 ; i<pmodel->numverts ; i++)
1521: {
1522: pstverts[i].onseam = LittleLong (pinstverts[i].onseam);
1523: // put s and t in 16.16 format
1524: pstverts[i].s = LittleLong (pinstverts[i].s) << 16;
1525: pstverts[i].t = LittleLong (pinstverts[i].t) << 16;
1526: }
1527:
1528: //
1529: // set up the triangles
1530: //
1531: ptri = (mtriangle_t *)&pstverts[pmodel->numverts];
1532: pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts];
1533:
1534: pheader->triangles = (byte *)ptri - (byte *)pheader;
1535:
1536: for (i=0 ; i<pmodel->numtris ; i++)
1537: {
1538: int j;
1539:
1540: ptri[i].facesfront = LittleLong (pintriangles[i].facesfront);
1541:
1542: for (j=0 ; j<3 ; j++)
1543: {
1544: ptri[i].vertindex[j] =
1545: LittleLong (pintriangles[i].vertindex[j]);
1546: }
1547: }
1548:
1549: //
1550: // load the frames
1551: //
1552: if (numframes < 1)
1553: Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
1554:
1555: pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
1556:
1557: for (i=0 ; i<numframes ; i++)
1558: {
1559: aliasframetype_t frametype;
1560:
1561: frametype = LittleLong (pframetype->type);
1562: pheader->frames[i].type = frametype;
1563:
1564:
1565: if (frametype == ALIAS_SINGLE)
1566: {
1567: pframetype = (daliasframetype_t *)
1568: Mod_LoadAliasFrame (pframetype + 1,
1569: &pheader->frames[i].frame,
1570: pmodel->numverts,
1571: &pheader->frames[i].bboxmin,
1572: &pheader->frames[i].bboxmax,
1573: pheader, pheader->frames[i].name);
1574: }
1575: else
1576: {
1577: pframetype = (daliasframetype_t *)
1578: Mod_LoadAliasGroup (pframetype + 1,
1579: &pheader->frames[i].frame,
1580: pmodel->numverts,
1581: &pheader->frames[i].bboxmin,
1582: &pheader->frames[i].bboxmax,
1583: pheader, pheader->frames[i].name);
1584: }
1585: }
1586:
1587: mod->type = mod_alias;
1588:
1589: // FIXME: do this right
1590: mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
1591: mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
1592:
1593: //
1594: // move the complete, relocatable alias model to the cache
1595: //
1596: end = Hunk_LowMark ();
1597: total = end - start;
1598:
1599: Cache_Alloc (&mod->cache, total, loadname);
1600: if (!mod->cache.data)
1601: return;
1602: memcpy (mod->cache.data, pheader, total);
1603:
1604: Hunk_FreeToLowMark (start);
1605: }
1606:
1607: //=============================================================================
1608:
1609: /*
1610: =================
1611: Mod_LoadSpriteFrame
1612: =================
1613: */
1614: void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe)
1615: {
1616: dspriteframe_t *pinframe;
1617: mspriteframe_t *pspriteframe;
1618: int i, width, height, size, origin[2];
1619: unsigned short *ppixout;
1620: byte *ppixin;
1621:
1622: pinframe = (dspriteframe_t *)pin;
1623:
1624: width = LittleLong (pinframe->width);
1625: height = LittleLong (pinframe->height);
1626: size = width * height;
1627:
1628: pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes,
1629: loadname);
1630:
1631: Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size);
1632: *ppframe = pspriteframe;
1633:
1634: pspriteframe->width = width;
1635: pspriteframe->height = height;
1636: origin[0] = LittleLong (pinframe->origin[0]);
1637: origin[1] = LittleLong (pinframe->origin[1]);
1638:
1639: pspriteframe->up = origin[1];
1640: pspriteframe->down = origin[1] - height;
1641: pspriteframe->left = origin[0];
1642: pspriteframe->right = width + origin[0];
1643:
1644: if (r_pixbytes == 1)
1645: {
1646: Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size);
1647: }
1648: else if (r_pixbytes == 2)
1649: {
1650: ppixin = (byte *)(pinframe + 1);
1651: ppixout = (unsigned short *)&pspriteframe->pixels[0];
1652:
1653: for (i=0 ; i<size ; i++)
1654: ppixout[i] = d_8to16table[ppixin[i]];
1655: }
1656: else
1657: {
1658: Sys_Error ("Mod_LoadSpriteFrame: driver set invalid r_pixbytes: %d\n",
1659: r_pixbytes);
1660: }
1661:
1662: return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
1663: }
1664:
1665:
1666: /*
1667: =================
1668: Mod_LoadSpriteGroup
1669: =================
1670: */
1671: void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe)
1672: {
1673: dspritegroup_t *pingroup;
1674: mspritegroup_t *pspritegroup;
1675: int i, numframes;
1676: dspriteinterval_t *pin_intervals;
1677: float *poutintervals;
1678: void *ptemp;
1679:
1680: pingroup = (dspritegroup_t *)pin;
1681:
1682: numframes = LittleLong (pingroup->numframes);
1683:
1684: pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
1685: (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
1686:
1687: pspritegroup->numframes = numframes;
1688:
1689: *ppframe = (mspriteframe_t *)pspritegroup;
1690:
1691: pin_intervals = (dspriteinterval_t *)(pingroup + 1);
1692:
1693: poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
1694:
1695: pspritegroup->intervals = poutintervals;
1696:
1697: for (i=0 ; i<numframes ; i++)
1698: {
1699: *poutintervals = LittleFloat (pin_intervals->interval);
1700: if (*poutintervals <= 0.0)
1701: Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
1702:
1703: poutintervals++;
1704: pin_intervals++;
1705: }
1706:
1707: ptemp = (void *)pin_intervals;
1708:
1709: for (i=0 ; i<numframes ; i++)
1710: {
1711: ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i]);
1712: }
1713:
1714: return ptemp;
1715: }
1716:
1717:
1718: /*
1719: =================
1720: Mod_LoadSpriteModel
1721: =================
1722: */
1723: void Mod_LoadSpriteModel (model_t *mod, void *buffer)
1724: {
1725: int i;
1726: int version;
1727: dsprite_t *pin;
1728: msprite_t *psprite;
1729: int numframes;
1730: int size;
1731: dspriteframetype_t *pframetype;
1732:
1733: pin = (dsprite_t *)buffer;
1734:
1735: version = LittleLong (pin->version);
1736: if (version != SPRITE_VERSION)
1737: Sys_Error ("%s has wrong version number "
1738: "(%i should be %i)", mod->name, version, SPRITE_VERSION);
1739:
1740: numframes = LittleLong (pin->numframes);
1741:
1742: size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames);
1743:
1744: psprite = Hunk_AllocName (size, loadname);
1745:
1746: mod->cache.data = psprite;
1747:
1748: psprite->type = LittleLong (pin->type);
1749: psprite->maxwidth = LittleLong (pin->width);
1750: psprite->maxheight = LittleLong (pin->height);
1751: psprite->beamlength = LittleFloat (pin->beamlength);
1752: mod->synctype = LittleLong (pin->synctype);
1753: psprite->numframes = numframes;
1754:
1755: mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
1756: mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
1757: mod->mins[2] = -psprite->maxheight/2;
1758: mod->maxs[2] = psprite->maxheight/2;
1759:
1760: //
1761: // load the frames
1762: //
1763: if (numframes < 1)
1764: Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
1765:
1766: mod->numframes = numframes;
1767:
1768: pframetype = (dspriteframetype_t *)(pin + 1);
1769:
1770: for (i=0 ; i<numframes ; i++)
1771: {
1772: spriteframetype_t frametype;
1773:
1774: frametype = LittleLong (pframetype->type);
1775: psprite->frames[i].type = frametype;
1776:
1777: if (frametype == SPR_SINGLE)
1778: {
1779: pframetype = (dspriteframetype_t *)
1780: Mod_LoadSpriteFrame (pframetype + 1,
1781: &psprite->frames[i].frameptr);
1782: }
1783: else
1784: {
1785: pframetype = (dspriteframetype_t *)
1786: Mod_LoadSpriteGroup (pframetype + 1,
1787: &psprite->frames[i].frameptr);
1788: }
1789: }
1790:
1791: mod->type = mod_sprite;
1792: }
1793:
1794: //=============================================================================
1795:
1796: /*
1797: ================
1798: Mod_Print
1799: ================
1800: */
1801: void Mod_Print (void)
1802: {
1803: int i;
1804: model_t *mod;
1805:
1806: Con_Printf ("Cached models:\n");
1807: for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
1808: {
1809: Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
1810: }
1811: }
1812:
1813:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.