|
|
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 "qwsvdef.h"
26:
27: model_t *loadmodel;
28: char loadname[32]; // for hunk tags
29:
30: void Mod_LoadSpriteModel (model_t *mod, void *buffer);
31: void Mod_LoadBrushModel (model_t *mod, void *buffer);
32: void Mod_LoadAliasModel (model_t *mod, void *buffer);
33: model_t *Mod_LoadModel (model_t *mod, qboolean crash);
34:
35: byte mod_novis[MAX_MAP_LEAFS/8];
36:
37: #define MAX_MOD_KNOWN 256
38: model_t mod_known[MAX_MOD_KNOWN];
39: int mod_numknown;
40:
41: texture_t r_notexture_mip;
42:
43: unsigned *model_checksum;
44:
45: /*
46: ===============
47: Mod_Init
48: ===============
49: */
50: void Mod_Init (void)
51: {
52: memset (mod_novis, 0xff, sizeof(mod_novis));
53: }
54:
55: /*
56: ===============
57: Mod_PointInLeaf
58: ===============
59: */
60: mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
61: {
62: mnode_t *node;
63: float d;
64: mplane_t *plane;
65:
66: if (!model || !model->nodes)
67: SV_Error ("Mod_PointInLeaf: bad model");
68:
69: node = model->nodes;
70: while (1)
71: {
72: if (node->contents < 0)
73: return (mleaf_t *)node;
74: plane = node->plane;
75: d = DotProduct (p,plane->normal) - plane->dist;
76: if (d > 0)
77: node = node->children[0];
78: else
79: node = node->children[1];
80: }
81:
82: return NULL; // never reached
83: }
84:
85:
86: /*
87: ===================
88: Mod_DecompressVis
89: ===================
90: */
91: byte *Mod_DecompressVis (byte *in, model_t *model)
92: {
93: static byte decompressed[MAX_MAP_LEAFS/8];
94: int c;
95: byte *out;
96: int row;
97:
98: row = (model->numleafs+7)>>3;
99: out = decompressed;
100:
101: #if 0
102: memcpy (out, in, row);
103: #else
104: if (!in)
105: { // no vis info, so make all visible
106: while (row)
107: {
108: *out++ = 0xff;
109: row--;
110: }
111: return decompressed;
112: }
113:
114: do
115: {
116: if (*in)
117: {
118: *out++ = *in++;
119: continue;
120: }
121:
122: c = in[1];
123: in += 2;
124: while (c)
125: {
126: *out++ = 0;
127: c--;
128: }
129: } while (out - decompressed < row);
130: #endif
131:
132: return decompressed;
133: }
134:
135: byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
136: {
137: if (leaf == model->leafs)
138: return mod_novis;
139: return Mod_DecompressVis (leaf->compressed_vis, model);
140: }
141:
142: /*
143: ===================
144: Mod_ClearAll
145: ===================
146: */
147: void Mod_ClearAll (void)
148: {
149: int i;
150: model_t *mod;
151:
152: for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
153: if (mod->type != mod_alias)
154: mod->needload = true;
155: }
156:
157: /*
158: ==================
159: Mod_FindName
160:
161: ==================
162: */
163: model_t *Mod_FindName (char *name)
164: {
165: int i;
166: model_t *mod;
167:
168: if (!name[0])
169: SV_Error ("Mod_ForName: NULL name");
170:
171: //
172: // search the currently loaded models
173: //
174: for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
175: if (!strcmp (mod->name, name) )
176: break;
177:
178: if (i == mod_numknown)
179: {
180: if (mod_numknown == MAX_MOD_KNOWN)
181: SV_Error ("mod_numknown == MAX_MOD_KNOWN");
182: strcpy (mod->name, name);
183: mod->needload = true;
184: mod_numknown++;
185: }
186:
187: return mod;
188: }
189:
190:
191: /*
192: ==================
193: Mod_LoadModel
194:
195: Loads a model into the cache
196: ==================
197: */
198: model_t *Mod_LoadModel (model_t *mod, qboolean crash)
199: {
200: void *d;
201: unsigned *buf;
202: byte stackbuf[1024]; // avoid dirtying the cache heap
203:
204: if (!mod->needload)
205: {
206: if (mod->type == mod_alias)
207: {
208: d = Cache_Check (&mod->cache);
209: if (d)
210: return mod;
211: }
212: else
213: return mod; // not cached at all
214: }
215:
216: //
217: // load the file
218: //
219: buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
220: if (!buf)
221: {
222: if (crash)
223: SV_Error ("Mod_NumForName: %s not found", mod->name);
224: return NULL;
225: }
226:
227: //
228: // allocate a new model
229: //
230: COM_FileBase (mod->name, loadname);
231:
232: loadmodel = mod;
233:
234: //
235: // fill it in
236: //
237:
238: // call the apropriate loader
239: mod->needload = false;
240:
241: Mod_LoadBrushModel (mod, buf);
242:
243: return mod;
244: }
245:
246: /*
247: ==================
248: Mod_ForName
249:
250: Loads in a model for the given name
251: ==================
252: */
253: model_t *Mod_ForName (char *name, qboolean crash)
254: {
255: model_t *mod;
256:
257: mod = Mod_FindName (name);
258:
259: return Mod_LoadModel (mod, crash);
260: }
261:
262:
263: /*
264: ===============================================================================
265:
266: BRUSHMODEL LOADING
267:
268: ===============================================================================
269: */
270:
271: byte *mod_base;
272:
273:
274: /*
275: =================
276: Mod_LoadTextures
277: =================
278: */
279: void Mod_LoadTextures (lump_t *l)
280: {
281: int i, j, pixels, num, max, altmax;
282: miptex_t *mt;
283: texture_t *tx, *tx2;
284: texture_t *anims[10];
285: texture_t *altanims[10];
286: dmiptexlump_t *m;
287:
288: if (!l->filelen)
289: {
290: loadmodel->textures = NULL;
291: return;
292: }
293: m = (dmiptexlump_t *)(mod_base + l->fileofs);
294:
295: m->nummiptex = LittleLong (m->nummiptex);
296:
297: loadmodel->numtextures = m->nummiptex;
298: loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
299:
300: for (i=0 ; i<m->nummiptex ; i++)
301: {
302: m->dataofs[i] = LittleLong(m->dataofs[i]);
303: if (m->dataofs[i] == -1)
304: continue;
305: mt = (miptex_t *)((byte *)m + m->dataofs[i]);
306: mt->width = LittleLong (mt->width);
307: mt->height = LittleLong (mt->height);
308: for (j=0 ; j<MIPLEVELS ; j++)
309: mt->offsets[j] = LittleLong (mt->offsets[j]);
310:
311: if ( (mt->width & 15) || (mt->height & 15) )
312: SV_Error ("Texture %s is not 16 aligned", mt->name);
313: pixels = mt->width*mt->height/64*85;
314: tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
315: loadmodel->textures[i] = tx;
316:
317: memcpy (tx->name, mt->name, sizeof(tx->name));
318: tx->width = mt->width;
319: tx->height = mt->height;
320: for (j=0 ; j<MIPLEVELS ; j++)
321: tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
322: // the pixels immediately follow the structures
323: memcpy ( tx+1, mt+1, pixels);
324: }
325:
326: //
327: // sequence the animations
328: //
329: for (i=0 ; i<m->nummiptex ; i++)
330: {
331: tx = loadmodel->textures[i];
332: if (!tx || tx->name[0] != '+')
333: continue;
334: if (tx->anim_next)
335: continue; // allready sequenced
336:
337: // find the number of frames in the animation
338: memset (anims, 0, sizeof(anims));
339: memset (altanims, 0, sizeof(altanims));
340:
341: max = tx->name[1];
342: altmax = 0;
343: if (max >= 'a' && max <= 'z')
344: max -= 'a' - 'A';
345: if (max >= '0' && max <= '9')
346: {
347: max -= '0';
348: altmax = 0;
349: anims[max] = tx;
350: max++;
351: }
352: else if (max >= 'A' && max <= 'J')
353: {
354: altmax = max - 'A';
355: max = 0;
356: altanims[altmax] = tx;
357: altmax++;
358: }
359: else
360: SV_Error ("Bad animating texture %s", tx->name);
361:
362: for (j=i+1 ; j<m->nummiptex ; j++)
363: {
364: tx2 = loadmodel->textures[j];
365: if (!tx2 || tx2->name[0] != '+')
366: continue;
367: if (strcmp (tx2->name+2, tx->name+2))
368: continue;
369:
370: num = tx2->name[1];
371: if (num >= 'a' && num <= 'z')
372: num -= 'a' - 'A';
373: if (num >= '0' && num <= '9')
374: {
375: num -= '0';
376: anims[num] = tx2;
377: if (num+1 > max)
378: max = num + 1;
379: }
380: else if (num >= 'A' && num <= 'J')
381: {
382: num = num - 'A';
383: altanims[num] = tx2;
384: if (num+1 > altmax)
385: altmax = num+1;
386: }
387: else
388: SV_Error ("Bad animating texture %s", tx->name);
389: }
390:
391: #define ANIM_CYCLE 2
392: // link them all together
393: for (j=0 ; j<max ; j++)
394: {
395: tx2 = anims[j];
396: if (!tx2)
397: SV_Error ("Missing frame %i of %s",j, tx->name);
398: tx2->anim_total = max * ANIM_CYCLE;
399: tx2->anim_min = j * ANIM_CYCLE;
400: tx2->anim_max = (j+1) * ANIM_CYCLE;
401: tx2->anim_next = anims[ (j+1)%max ];
402: if (altmax)
403: tx2->alternate_anims = altanims[0];
404: }
405: for (j=0 ; j<altmax ; j++)
406: {
407: tx2 = altanims[j];
408: if (!tx2)
409: SV_Error ("Missing frame %i of %s",j, tx->name);
410: tx2->anim_total = altmax * ANIM_CYCLE;
411: tx2->anim_min = j * ANIM_CYCLE;
412: tx2->anim_max = (j+1) * ANIM_CYCLE;
413: tx2->anim_next = altanims[ (j+1)%altmax ];
414: if (max)
415: tx2->alternate_anims = anims[0];
416: }
417: }
418: }
419:
420: /*
421: =================
422: Mod_LoadLighting
423: =================
424: */
425: void Mod_LoadLighting (lump_t *l)
426: {
427: if (!l->filelen)
428: {
429: loadmodel->lightdata = NULL;
430: return;
431: }
432: loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
433: memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
434: }
435:
436:
437: /*
438: =================
439: Mod_LoadVisibility
440: =================
441: */
442: void Mod_LoadVisibility (lump_t *l)
443: {
444: if (!l->filelen)
445: {
446: loadmodel->visdata = NULL;
447: return;
448: }
449: loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);
450: memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
451: }
452:
453:
454: /*
455: =================
456: Mod_LoadEntities
457: =================
458: */
459: void Mod_LoadEntities (lump_t *l)
460: {
461: if (!l->filelen)
462: {
463: loadmodel->entities = NULL;
464: return;
465: }
466: loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);
467: memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
468: }
469:
470:
471: /*
472: =================
473: Mod_LoadVertexes
474: =================
475: */
476: void Mod_LoadVertexes (lump_t *l)
477: {
478: dvertex_t *in;
479: mvertex_t *out;
480: int i, count;
481:
482: in = (void *)(mod_base + l->fileofs);
483: if (l->filelen % sizeof(*in))
484: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
485: count = l->filelen / sizeof(*in);
486: out = Hunk_AllocName ( count*sizeof(*out), loadname);
487:
488: loadmodel->vertexes = out;
489: loadmodel->numvertexes = count;
490:
491: for ( i=0 ; i<count ; i++, in++, out++)
492: {
493: out->position[0] = LittleFloat (in->point[0]);
494: out->position[1] = LittleFloat (in->point[1]);
495: out->position[2] = LittleFloat (in->point[2]);
496: }
497: }
498:
499: /*
500: =================
501: Mod_LoadSubmodels
502: =================
503: */
504: void Mod_LoadSubmodels (lump_t *l)
505: {
506: dmodel_t *in;
507: dmodel_t *out;
508: int i, j, count;
509:
510: in = (void *)(mod_base + l->fileofs);
511: if (l->filelen % sizeof(*in))
512: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
513: count = l->filelen / sizeof(*in);
514: out = Hunk_AllocName ( count*sizeof(*out), loadname);
515:
516: loadmodel->submodels = out;
517: loadmodel->numsubmodels = count;
518:
519: for ( i=0 ; i<count ; i++, in++, out++)
520: {
521: for (j=0 ; j<3 ; j++)
522: { // spread the mins / maxs by a pixel
523: out->mins[j] = LittleFloat (in->mins[j]) - 1;
524: out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
525: out->origin[j] = LittleFloat (in->origin[j]);
526: }
527: for (j=0 ; j<MAX_MAP_HULLS ; j++)
528: out->headnode[j] = LittleLong (in->headnode[j]);
529: out->visleafs = LittleLong (in->visleafs);
530: out->firstface = LittleLong (in->firstface);
531: out->numfaces = LittleLong (in->numfaces);
532: }
533: }
534:
535: /*
536: =================
537: Mod_LoadEdges
538: =================
539: */
540: void Mod_LoadEdges (lump_t *l)
541: {
542: dedge_t *in;
543: medge_t *out;
544: int i, count;
545:
546: in = (void *)(mod_base + l->fileofs);
547: if (l->filelen % sizeof(*in))
548: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
549: count = l->filelen / sizeof(*in);
550: out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
551:
552: loadmodel->edges = out;
553: loadmodel->numedges = count;
554:
555: for ( i=0 ; i<count ; i++, in++, out++)
556: {
557: out->v[0] = (unsigned short)LittleShort(in->v[0]);
558: out->v[1] = (unsigned short)LittleShort(in->v[1]);
559: }
560: }
561:
562: /*
563: =================
564: Mod_LoadTexinfo
565: =================
566: */
567: void Mod_LoadTexinfo (lump_t *l)
568: {
569: texinfo_t *in;
570: mtexinfo_t *out;
571: int i, j, count;
572: int miptex;
573: float len1, len2;
574:
575: in = (void *)(mod_base + l->fileofs);
576: if (l->filelen % sizeof(*in))
577: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
578: count = l->filelen / sizeof(*in);
579: out = Hunk_AllocName ( count*sizeof(*out), loadname);
580:
581: loadmodel->texinfo = out;
582: loadmodel->numtexinfo = count;
583:
584: for ( i=0 ; i<count ; i++, in++, out++)
585: {
586: #if 0
587: for (j=0 ; j<8 ; j++)
588: out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
589: len1 = Length (in->vecs[0]);
590: len2 = Length (in->vecs[1]);
591: #else
592: for (j=0 ; j<4 ; j++) {
593: out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
594: out->vecs[1][j] = LittleFloat (in->vecs[1][j]);
595: }
596: len1 = Length (out->vecs[0]);
597: len2 = Length (out->vecs[1]);
598: #endif
599: if (len1 + len2 < 2 /*0.001*/)
600: out->mipadjust = 1;
601: else
602: out->mipadjust = 1 / floor( (len1+len2)/2 );
603:
604: miptex = LittleLong (in->miptex);
605: out->flags = LittleLong (in->flags);
606:
607: if (!loadmodel->textures)
608: {
609: out->texture = &r_notexture_mip; // checkerboard texture
610: out->flags = 0;
611: }
612: else
613: {
614: if (miptex >= loadmodel->numtextures)
615: SV_Error ("miptex >= loadmodel->numtextures");
616: out->texture = loadmodel->textures[miptex];
617: if (!out->texture)
618: {
619: out->texture = &r_notexture_mip; // texture not found
620: out->flags = 0;
621: }
622: }
623: }
624: }
625:
626: /*
627: ================
628: CalcSurfaceExtents
629:
630: Fills in s->texturemins[] and s->extents[]
631: ================
632: */
633: void CalcSurfaceExtents (msurface_t *s)
634: {
635: float mins[2], maxs[2], val;
636: int i,j, e;
637: mvertex_t *v;
638: mtexinfo_t *tex;
639: int bmins[2], bmaxs[2];
640:
641: mins[0] = mins[1] = 999999;
642: maxs[0] = maxs[1] = -99999;
643:
644: tex = s->texinfo;
645:
646: for (i=0 ; i<s->numedges ; i++)
647: {
648: e = loadmodel->surfedges[s->firstedge+i];
649: if (e >= 0)
650: v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
651: else
652: v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
653:
654: for (j=0 ; j<2 ; j++)
655: {
656: val = v->position[0] * tex->vecs[j][0] +
657: v->position[1] * tex->vecs[j][1] +
658: v->position[2] * tex->vecs[j][2] +
659: tex->vecs[j][3];
660: if (val < mins[j])
661: mins[j] = val;
662: if (val > maxs[j])
663: maxs[j] = val;
664: }
665: }
666:
667: for (i=0 ; i<2 ; i++)
668: {
669: bmins[i] = floor(mins[i]/16);
670: bmaxs[i] = ceil(maxs[i]/16);
671:
672: s->texturemins[i] = bmins[i] * 16;
673: s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
674: if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
675: SV_Error ("Bad surface extents");
676: }
677: }
678:
679:
680: /*
681: =================
682: Mod_LoadFaces
683: =================
684: */
685: void Mod_LoadFaces (lump_t *l)
686: {
687: dface_t *in;
688: msurface_t *out;
689: int i, count, surfnum;
690: int planenum, side;
691:
692: in = (void *)(mod_base + l->fileofs);
693: if (l->filelen % sizeof(*in))
694: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
695: count = l->filelen / sizeof(*in);
696: out = Hunk_AllocName ( count*sizeof(*out), loadname);
697:
698: loadmodel->surfaces = out;
699: loadmodel->numsurfaces = count;
700:
701: for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
702: {
703: out->firstedge = LittleLong(in->firstedge);
704: out->numedges = LittleShort(in->numedges);
705: out->flags = 0;
706:
707: planenum = LittleShort(in->planenum);
708: side = LittleShort(in->side);
709: if (side)
710: out->flags |= SURF_PLANEBACK;
711:
712: out->plane = loadmodel->planes + planenum;
713:
714: out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
715:
716: CalcSurfaceExtents (out);
717:
718: // lighting info
719:
720: for (i=0 ; i<MAXLIGHTMAPS ; i++)
721: out->styles[i] = in->styles[i];
722: i = LittleLong(in->lightofs);
723: if (i == -1)
724: out->samples = NULL;
725: else
726: out->samples = loadmodel->lightdata + i;
727:
728: // set the drawing flags flag
729:
730: if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky
731: {
732: out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
733: continue;
734: }
735:
736: if (!Q_strncmp(out->texinfo->texture->name,"*",1)) // turbulent
737: {
738: out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
739: for (i=0 ; i<2 ; i++)
740: {
741: out->extents[i] = 16384;
742: out->texturemins[i] = -8192;
743: }
744: continue;
745: }
746: }
747: }
748:
749:
750: /*
751: =================
752: Mod_SetParent
753: =================
754: */
755: void Mod_SetParent (mnode_t *node, mnode_t *parent)
756: {
757: node->parent = parent;
758: if (node->contents < 0)
759: return;
760: Mod_SetParent (node->children[0], node);
761: Mod_SetParent (node->children[1], node);
762: }
763:
764: /*
765: =================
766: Mod_LoadNodes
767: =================
768: */
769: void Mod_LoadNodes (lump_t *l)
770: {
771: int i, j, count, p;
772: dnode_t *in;
773: mnode_t *out;
774:
775: in = (void *)(mod_base + l->fileofs);
776: if (l->filelen % sizeof(*in))
777: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
778: count = l->filelen / sizeof(*in);
779: out = Hunk_AllocName ( count*sizeof(*out), loadname);
780:
781: loadmodel->nodes = out;
782: loadmodel->numnodes = count;
783:
784: for ( i=0 ; i<count ; i++, in++, out++)
785: {
786: for (j=0 ; j<3 ; j++)
787: {
788: out->minmaxs[j] = LittleShort (in->mins[j]);
789: out->minmaxs[3+j] = LittleShort (in->maxs[j]);
790: }
791:
792: p = LittleLong(in->planenum);
793: out->plane = loadmodel->planes + p;
794:
795: out->firstsurface = LittleShort (in->firstface);
796: out->numsurfaces = LittleShort (in->numfaces);
797:
798: for (j=0 ; j<2 ; j++)
799: {
800: p = LittleShort (in->children[j]);
801: if (p >= 0)
802: out->children[j] = loadmodel->nodes + p;
803: else
804: out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
805: }
806: }
807:
808: Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
809: }
810:
811: /*
812: =================
813: Mod_LoadLeafs
814: =================
815: */
816: void Mod_LoadLeafs (lump_t *l)
817: {
818: dleaf_t *in;
819: mleaf_t *out;
820: int i, j, count, p;
821:
822: in = (void *)(mod_base + l->fileofs);
823: if (l->filelen % sizeof(*in))
824: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
825: count = l->filelen / sizeof(*in);
826: out = Hunk_AllocName ( count*sizeof(*out), loadname);
827:
828: loadmodel->leafs = out;
829: loadmodel->numleafs = count;
830:
831: for ( i=0 ; i<count ; i++, in++, out++)
832: {
833: for (j=0 ; j<3 ; j++)
834: {
835: out->minmaxs[j] = LittleShort (in->mins[j]);
836: out->minmaxs[3+j] = LittleShort (in->maxs[j]);
837: }
838:
839: p = LittleLong(in->contents);
840: out->contents = p;
841:
842: out->firstmarksurface = loadmodel->marksurfaces +
843: LittleShort(in->firstmarksurface);
844: out->nummarksurfaces = LittleShort(in->nummarksurfaces);
845:
846: p = LittleLong(in->visofs);
847: if (p == -1)
848: out->compressed_vis = NULL;
849: else
850: out->compressed_vis = loadmodel->visdata + p;
851: out->efrags = NULL;
852:
853: for (j=0 ; j<4 ; j++)
854: out->ambient_sound_level[j] = in->ambient_level[j];
855: }
856: }
857:
858: /*
859: =================
860: Mod_LoadClipnodes
861: =================
862: */
863: void Mod_LoadClipnodes (lump_t *l)
864: {
865: dclipnode_t *in, *out;
866: int i, count;
867: hull_t *hull;
868:
869: in = (void *)(mod_base + l->fileofs);
870: if (l->filelen % sizeof(*in))
871: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
872: count = l->filelen / sizeof(*in);
873: out = Hunk_AllocName ( count*sizeof(*out), loadname);
874:
875: loadmodel->clipnodes = out;
876: loadmodel->numclipnodes = count;
877:
878: hull = &loadmodel->hulls[1];
879: hull->clipnodes = out;
880: hull->firstclipnode = 0;
881: hull->lastclipnode = count-1;
882: hull->planes = loadmodel->planes;
883: hull->clip_mins[0] = -16;
884: hull->clip_mins[1] = -16;
885: hull->clip_mins[2] = -24;
886: hull->clip_maxs[0] = 16;
887: hull->clip_maxs[1] = 16;
888: hull->clip_maxs[2] = 32;
889:
890: hull = &loadmodel->hulls[2];
891: hull->clipnodes = out;
892: hull->firstclipnode = 0;
893: hull->lastclipnode = count-1;
894: hull->planes = loadmodel->planes;
895: hull->clip_mins[0] = -32;
896: hull->clip_mins[1] = -32;
897: hull->clip_mins[2] = -24;
898: hull->clip_maxs[0] = 32;
899: hull->clip_maxs[1] = 32;
900: hull->clip_maxs[2] = 64;
901:
902: for (i=0 ; i<count ; i++, out++, in++)
903: {
904: out->planenum = LittleLong(in->planenum);
905: out->children[0] = LittleShort(in->children[0]);
906: out->children[1] = LittleShort(in->children[1]);
907: }
908: }
909:
910: /*
911: =================
912: Mod_MakeHull0
913:
914: Deplicate the drawing hull structure as a clipping hull
915: =================
916: */
917: void Mod_MakeHull0 (void)
918: {
919: mnode_t *in, *child;
920: dclipnode_t *out;
921: int i, j, count;
922: hull_t *hull;
923:
924: hull = &loadmodel->hulls[0];
925:
926: in = loadmodel->nodes;
927: count = loadmodel->numnodes;
928: out = Hunk_AllocName ( count*sizeof(*out), loadname);
929:
930: hull->clipnodes = out;
931: hull->firstclipnode = 0;
932: hull->lastclipnode = count-1;
933: hull->planes = loadmodel->planes;
934:
935: for (i=0 ; i<count ; i++, out++, in++)
936: {
937: out->planenum = in->plane - loadmodel->planes;
938: for (j=0 ; j<2 ; j++)
939: {
940: child = in->children[j];
941: if (child->contents < 0)
942: out->children[j] = child->contents;
943: else
944: out->children[j] = child - loadmodel->nodes;
945: }
946: }
947: }
948:
949: /*
950: =================
951: Mod_LoadMarksurfaces
952: =================
953: */
954: void Mod_LoadMarksurfaces (lump_t *l)
955: {
956: int i, j, count;
957: short *in;
958: msurface_t **out;
959:
960: in = (void *)(mod_base + l->fileofs);
961: if (l->filelen % sizeof(*in))
962: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
963: count = l->filelen / sizeof(*in);
964: out = Hunk_AllocName ( count*sizeof(*out), loadname);
965:
966: loadmodel->marksurfaces = out;
967: loadmodel->nummarksurfaces = count;
968:
969: for ( i=0 ; i<count ; i++)
970: {
971: j = LittleShort(in[i]);
972: if (j >= loadmodel->numsurfaces)
973: SV_Error ("Mod_ParseMarksurfaces: bad surface number");
974: out[i] = loadmodel->surfaces + j;
975: }
976: }
977:
978: /*
979: =================
980: Mod_LoadSurfedges
981: =================
982: */
983: void Mod_LoadSurfedges (lump_t *l)
984: {
985: int i, count;
986: int *in, *out;
987:
988: in = (void *)(mod_base + l->fileofs);
989: if (l->filelen % sizeof(*in))
990: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
991: count = l->filelen / sizeof(*in);
992: out = Hunk_AllocName ( count*sizeof(*out), loadname);
993:
994: loadmodel->surfedges = out;
995: loadmodel->numsurfedges = count;
996:
997: for ( i=0 ; i<count ; i++)
998: out[i] = LittleLong (in[i]);
999: }
1000:
1001: /*
1002: =================
1003: Mod_LoadPlanes
1004: =================
1005: */
1006: void Mod_LoadPlanes (lump_t *l)
1007: {
1008: int i, j;
1009: mplane_t *out;
1010: dplane_t *in;
1011: int count;
1012: int bits;
1013:
1014: in = (void *)(mod_base + l->fileofs);
1015: if (l->filelen % sizeof(*in))
1016: SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1017: count = l->filelen / sizeof(*in);
1018: out = Hunk_AllocName ( count*2*sizeof(*out), loadname);
1019:
1020: loadmodel->planes = out;
1021: loadmodel->numplanes = count;
1022:
1023: for ( i=0 ; i<count ; i++, in++, out++)
1024: {
1025: bits = 0;
1026: for (j=0 ; j<3 ; j++)
1027: {
1028: out->normal[j] = LittleFloat (in->normal[j]);
1029: if (out->normal[j] < 0)
1030: bits |= 1<<j;
1031: }
1032:
1033: out->dist = LittleFloat (in->dist);
1034: out->type = LittleLong (in->type);
1035: out->signbits = bits;
1036: }
1037: }
1038:
1039:
1040: /*
1041: =================
1042: Mod_LoadBrushModel
1043: =================
1044: */
1045: void Mod_LoadBrushModel (model_t *mod, void *buffer)
1046: {
1047: int i, j;
1048: dheader_t *header;
1049: dmodel_t *bm;
1050:
1051: loadmodel->type = mod_brush;
1052:
1053: header = (dheader_t *)buffer;
1054:
1055: i = LittleLong (header->version);
1056: if (i != BSPVERSION)
1057: SV_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
1058:
1059: // swap all the lumps
1060: mod_base = (byte *)header;
1061:
1062: for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
1063: ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
1064:
1065: // load into heap
1066:
1067: mod->checksum = 0;
1068: mod->checksum2 = 0;
1069:
1070: // checksum all of the map, except for entities
1071: for (i = 0; i < HEADER_LUMPS; i++) {
1072: if (i == LUMP_ENTITIES)
1073: continue;
1074: mod->checksum ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
1075: header->lumps[i].filelen));
1076:
1077: if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
1078: continue;
1079: mod->checksum2 ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
1080: header->lumps[i].filelen));
1081: }
1082:
1083: Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
1084: Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
1085: Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
1086: Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
1087: Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
1088: Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
1089: Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
1090: Mod_LoadFaces (&header->lumps[LUMP_FACES]);
1091: Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
1092: Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
1093: Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
1094: Mod_LoadNodes (&header->lumps[LUMP_NODES]);
1095: Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
1096: Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
1097: Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
1098:
1099: Mod_MakeHull0 ();
1100:
1101: mod->numframes = 2; // regular and alternate animation
1102:
1103: //
1104: // set up the submodels (FIXME: this is confusing)
1105: //
1106: for (i=0 ; i<mod->numsubmodels ; i++)
1107: {
1108: bm = &mod->submodels[i];
1109:
1110: mod->hulls[0].firstclipnode = bm->headnode[0];
1111: for (j=1 ; j<MAX_MAP_HULLS ; j++)
1112: {
1113: mod->hulls[j].firstclipnode = bm->headnode[j];
1114: mod->hulls[j].lastclipnode = mod->numclipnodes-1;
1115: }
1116:
1117: mod->firstmodelsurface = bm->firstface;
1118: mod->nummodelsurfaces = bm->numfaces;
1119:
1120: VectorCopy (bm->maxs, mod->maxs);
1121: VectorCopy (bm->mins, mod->mins);
1122:
1123: mod->numleafs = bm->visleafs;
1124:
1125: if (i < mod->numsubmodels-1)
1126: { // duplicate the basic information
1127: char name[10];
1128:
1129: sprintf (name, "*%i", i+1);
1130: loadmodel = Mod_FindName (name);
1131: *loadmodel = *mod;
1132: strcpy (loadmodel->name, name);
1133: mod = loadmodel;
1134: }
1135: }
1136: }
1137:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.