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