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