|
|
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 "r_local.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 256
19: model_t mod_known[MAX_MOD_KNOWN];
20: int mod_numknown;
21:
22: // the inline * models from the current map are kept seperate
23: model_t mod_inline[MAX_MOD_KNOWN];
24:
25: int registration_sequence;
26: int modfilelen;
27:
28: //===============================================================================
29:
30:
31: /*
32: ================
33: Mod_Modellist_f
34: ================
35: */
36: void Mod_Modellist_f (void)
37: {
38: int i;
39: model_t *mod;
40: int total;
41:
42: total = 0;
43: ri.Con_Printf (PRINT_ALL,"Loaded models:\n");
44: for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
45: {
46: if (!mod->name[0])
47: continue;
48: ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name);
49: total += mod->extradatasize;
50: }
51: ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total);
52: }
53:
54: /*
55: ===============
56: Mod_Init
57: ===============
58: */
59: void Mod_Init (void)
60: {
61: memset (mod_novis, 0xff, sizeof(mod_novis));
62: }
63:
64: /*
65: ==================
66: Mod_ForName
67:
68: Loads in a model for the given name
69: ==================
70: */
71: model_t *Mod_ForName (char *name, qboolean crash)
72: {
73: model_t *mod;
74: unsigned *buf;
75: int i;
76:
77: if (!name[0])
78: ri.Sys_Error (ERR_DROP,"Mod_ForName: NULL name");
79:
80: //
81: // inline models are grabbed only from worldmodel
82: //
83: if (name[0] == '*')
84: {
85: i = atoi(name+1);
86: if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
87: ri.Sys_Error (ERR_DROP, "bad inline model number");
88: return &mod_inline[i];
89: }
90:
91: //
92: // search the currently loaded models
93: //
94: for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
95: if (!strcmp (mod->name, name) )
96: return mod;
97:
98: //
99: // find a free model slot spot
100: //
101: for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
102: {
103: if (!mod->name[0])
104: break; // free spot
105: }
106: if (i == mod_numknown)
107: {
108: if (mod_numknown == MAX_MOD_KNOWN)
109: ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
110: mod_numknown++;
111: }
112: strcpy (mod->name, name);
113:
114: //
115: // load the file
116: //
117: modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf);
118: if (!buf)
119: {
120: if (crash)
121: ri.Sys_Error (ERR_DROP,"Mod_NumForName: %s not found", mod->name);
122: memset (mod->name, 0, sizeof(mod->name));
123: return NULL;
124: }
125:
126: loadmodel = mod;
127:
128: //
129: // fill it in
130: //
131:
132: // call the apropriate loader
133:
134: switch (LittleLong(*(unsigned *)buf))
135: {
136: case IDALIASHEADER:
137: loadmodel->extradata = Hunk_Begin (0x200000);
138: Mod_LoadAliasModel (mod, buf);
139: break;
140:
141: case IDSPRITEHEADER:
142: loadmodel->extradata = Hunk_Begin (0x10000);
143: Mod_LoadSpriteModel (mod, buf);
144: break;
145:
146: case IDBSPHEADER:
147: loadmodel->extradata = Hunk_Begin (0x1000000);
148: Mod_LoadBrushModel (mod, buf);
149: break;
150:
151: default:
152: ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name);
153: break;
154: }
155:
156: loadmodel->extradatasize = Hunk_End ();
157:
158: ri.FS_FreeFile (buf);
159:
160: return mod;
161: }
162:
163:
164: /*
165: ===============
166: Mod_PointInLeaf
167: ===============
168: */
169: mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
170: {
171: mnode_t *node;
172: float d;
173: mplane_t *plane;
174:
175: if (!model || !model->nodes)
176: ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model");
177:
178: node = model->nodes;
179: while (1)
180: {
181: if (node->contents != -1)
182: return (mleaf_t *)node;
183: plane = node->plane;
184: d = DotProduct (p,plane->normal) - plane->dist;
185: if (d > 0)
186: node = node->children[0];
187: else
188: node = node->children[1];
189: }
190:
191: return NULL; // never reached
192: }
193:
194:
195: /*
196: ===================
197: Mod_DecompressVis
198: ===================
199: */
200: byte *Mod_DecompressVis (byte *in, model_t *model)
201: {
202: static byte decompressed[MAX_MAP_LEAFS/8];
203: int c;
204: byte *out;
205: int row;
206:
207: row = (model->vis->numclusters+7)>>3;
208: out = decompressed;
209:
210: #if 0
211: memcpy (out, in, row);
212: #else
213: if (!in)
214: { // no vis info, so make all visible
215: while (row)
216: {
217: *out++ = 0xff;
218: row--;
219: }
220: return decompressed;
221: }
222:
223: do
224: {
225: if (*in)
226: {
227: *out++ = *in++;
228: continue;
229: }
230:
231: c = in[1];
232: in += 2;
233: while (c)
234: {
235: *out++ = 0;
236: c--;
237: }
238: } while (out - decompressed < row);
239: #endif
240:
241: return decompressed;
242: }
243:
244: /*
245: ==============
246: Mod_ClusterPVS
247: ==============
248: */
249: byte *Mod_ClusterPVS (int cluster, model_t *model)
250: {
251: if (cluster == -1 || !model->vis)
252: return mod_novis;
253: return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS],
254: model);
255: }
256:
257: /*
258: ===============================================================================
259:
260: BRUSHMODEL LOADING
261:
262: ===============================================================================
263: */
264:
265: byte *mod_base;
266:
267:
268: /*
269: =================
270: Mod_LoadLighting
271:
272: Converts the 24 bit lighting down to 8 bit
273: by taking the brightest component
274: =================
275: */
276: void Mod_LoadLighting (lump_t *l)
277: {
278: int i, size;
279: byte *in;
280:
281: if (!l->filelen)
282: {
283: loadmodel->lightdata = NULL;
284: return;
285: }
286: size = l->filelen/3;
287: loadmodel->lightdata = Hunk_Alloc (size);
288: in = (void *)(mod_base + l->fileofs);
289: for (i=0 ; i<size ; i++, in+=3)
290: {
291: if (in[0] > in[1] && in[0] > in[2])
292: loadmodel->lightdata[i] = in[0];
293: else if (in[1] > in[0] && in[1] > in[2])
294: loadmodel->lightdata[i] = in[1];
295: else
296: loadmodel->lightdata[i] = in[2];
297: }
298: }
299:
300:
301: int r_leaftovis[MAX_MAP_LEAFS];
302: int r_vistoleaf[MAX_MAP_LEAFS];
303: int r_numvisleafs;
304:
305: void R_NumberLeafs (mnode_t *node)
306: {
307: mleaf_t *leaf;
308: int leafnum;
309:
310: if (node->contents != -1)
311: {
312: leaf = (mleaf_t *)node;
313: leafnum = leaf - loadmodel->leafs;
314: if (leaf->contents & CONTENTS_SOLID)
315: return;
316: r_leaftovis[leafnum] = r_numvisleafs;
317: r_vistoleaf[r_numvisleafs] = leafnum;
318: r_numvisleafs++;
319: return;
320: }
321:
322: R_NumberLeafs (node->children[0]);
323: R_NumberLeafs (node->children[1]);
324: }
325:
326:
327: /*
328: =================
329: Mod_LoadVisibility
330: =================
331: */
332: void Mod_LoadVisibility (lump_t *l)
333: {
334: int i;
335:
336: if (!l->filelen)
337: {
338: loadmodel->vis = NULL;
339: return;
340: }
341: loadmodel->vis = Hunk_Alloc ( l->filelen);
342: memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen);
343:
344: loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters);
345: for (i=0 ; i<loadmodel->vis->numclusters ; i++)
346: {
347: loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]);
348: loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]);
349: }
350: }
351:
352:
353: /*
354: =================
355: Mod_LoadVertexes
356: =================
357: */
358: void Mod_LoadVertexes (lump_t *l)
359: {
360: dvertex_t *in;
361: mvertex_t *out;
362: int i, count;
363:
364: in = (void *)(mod_base + l->fileofs);
365: if (l->filelen % sizeof(*in))
366: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
367: count = l->filelen / sizeof(*in);
368: out = Hunk_Alloc ( (count+8)*sizeof(*out)); // extra for skybox
369:
370: loadmodel->vertexes = out;
371: loadmodel->numvertexes = count;
372:
373: for ( i=0 ; i<count ; i++, in++, out++)
374: {
375: out->position[0] = LittleFloat (in->point[0]);
376: out->position[1] = LittleFloat (in->point[1]);
377: out->position[2] = LittleFloat (in->point[2]);
378: }
379: }
380:
381: /*
382: =================
383: Mod_LoadSubmodels
384: =================
385: */
386: void Mod_LoadSubmodels (lump_t *l)
387: {
388: dmodel_t *in;
389: dmodel_t *out;
390: int i, j, count;
391:
392: in = (void *)(mod_base + l->fileofs);
393: if (l->filelen % sizeof(*in))
394: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
395: count = l->filelen / sizeof(*in);
396: out = Hunk_Alloc ( count*sizeof(*out));
397:
398: loadmodel->submodels = out;
399: loadmodel->numsubmodels = count;
400:
401: for ( i=0 ; i<count ; i++, in++, out++)
402: {
403: for (j=0 ; j<3 ; j++)
404: { // spread the mins / maxs by a pixel
405: out->mins[j] = LittleFloat (in->mins[j]) - 1;
406: out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
407: out->origin[j] = LittleFloat (in->origin[j]);
408: }
409: out->headnode = LittleLong (in->headnode);
410: out->firstface = LittleLong (in->firstface);
411: out->numfaces = LittleLong (in->numfaces);
412: }
413: }
414:
415: /*
416: =================
417: Mod_LoadEdges
418: =================
419: */
420: void Mod_LoadEdges (lump_t *l)
421: {
422: dedge_t *in;
423: medge_t *out;
424: int i, count;
425:
426: in = (void *)(mod_base + l->fileofs);
427: if (l->filelen % sizeof(*in))
428: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
429: count = l->filelen / sizeof(*in);
430: out = Hunk_Alloc ( (count + 13) * sizeof(*out)); // extra for skybox
431:
432: loadmodel->edges = out;
433: loadmodel->numedges = count;
434:
435: for ( i=0 ; i<count ; i++, in++, out++)
436: {
437: out->v[0] = (unsigned short)LittleShort(in->v[0]);
438: out->v[1] = (unsigned short)LittleShort(in->v[1]);
439: }
440: }
441:
442: /*
443: =================
444: Mod_LoadTexinfo
445: =================
446: */
447: void Mod_LoadTexinfo (lump_t *l)
448: {
449: texinfo_t *in;
450: mtexinfo_t *out, *step;
451: int i, j, count;
452: float len1, len2;
453: char name[MAX_QPATH];
454: int next;
455:
456: in = (void *)(mod_base + l->fileofs);
457: if (l->filelen % sizeof(*in))
458: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
459: count = l->filelen / sizeof(*in);
460: out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
461:
462: loadmodel->texinfo = out;
463: loadmodel->numtexinfo = count;
464:
465: for ( i=0 ; i<count ; i++, in++, out++)
466: {
467: for (j=0 ; j<8 ; j++)
468: out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
469: len1 = VectorLength (out->vecs[0]);
470: len2 = VectorLength (out->vecs[1]);
471: len1 = (len1 + len2)/2;
472: if (len1 < 0.32)
473: out->mipadjust = 4;
474: else if (len1 < 0.49)
475: out->mipadjust = 3;
476: else if (len1 < 0.99)
477: out->mipadjust = 2;
478: else
479: out->mipadjust = 1;
480: #if 0
481: if (len1 + len2 < 0.001)
482: out->mipadjust = 1; // don't crash
483: else
484: out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
485: #endif
486:
487: out->flags = LittleLong (in->flags);
488:
489: next = LittleLong (in->nexttexinfo);
490: if (next > 0)
491: out->next = loadmodel->texinfo + next;
492:
493: Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
494: out->image = R_FindImage (name, it_wall);
495: if (!out->image)
496: {
497: out->image = r_notexture_mip; // texture not found
498: out->flags = 0;
499: }
500: }
501:
502: // count animation frames
503: for (i=0 ; i<count ; i++)
504: {
505: out = &loadmodel->texinfo[i];
506: out->numframes = 1;
507: for (step = out->next ; step && step != out ; step=step->next)
508: out->numframes++;
509: }
510: }
511:
512: /*
513: ================
514: CalcSurfaceExtents
515:
516: Fills in s->texturemins[] and s->extents[]
517: ================
518: */
519: void CalcSurfaceExtents (msurface_t *s)
520: {
521: float mins[2], maxs[2], val;
522: int i,j, e;
523: mvertex_t *v;
524: mtexinfo_t *tex;
525: int bmins[2], bmaxs[2];
526:
527: mins[0] = mins[1] = 999999;
528: maxs[0] = maxs[1] = -99999;
529:
530: tex = s->texinfo;
531:
532: for (i=0 ; i<s->numedges ; i++)
533: {
534: e = loadmodel->surfedges[s->firstedge+i];
535: if (e >= 0)
536: v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
537: else
538: v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
539:
540: for (j=0 ; j<2 ; j++)
541: {
542: val = v->position[0] * tex->vecs[j][0] +
543: v->position[1] * tex->vecs[j][1] +
544: v->position[2] * tex->vecs[j][2] +
545: tex->vecs[j][3];
546: if (val < mins[j])
547: mins[j] = val;
548: if (val > maxs[j])
549: maxs[j] = val;
550: }
551: }
552:
553: for (i=0 ; i<2 ; i++)
554: {
555: bmins[i] = floor(mins[i]/16);
556: bmaxs[i] = ceil(maxs[i]/16);
557:
558: s->texturemins[i] = bmins[i] * 16;
559: s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
560: if (s->extents[i] < 16)
561: s->extents[i] = 16; // take at least one cache block
562: if ( !(tex->flags & (SURF_WARP|SURF_SKY)) && s->extents[i] > 256)
563: ri.Sys_Error (ERR_DROP,"Bad surface extents");
564: }
565: }
566:
567:
568: /*
569: =================
570: Mod_LoadFaces
571: =================
572: */
573: void Mod_LoadFaces (lump_t *l)
574: {
575: dface_t *in;
576: msurface_t *out;
577: int i, count, surfnum;
578: int planenum, side;
579:
580: in = (void *)(mod_base + l->fileofs);
581: if (l->filelen % sizeof(*in))
582: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
583: count = l->filelen / sizeof(*in);
584: out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
585:
586: loadmodel->surfaces = out;
587: loadmodel->numsurfaces = count;
588:
589: for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
590: {
591: out->firstedge = LittleLong(in->firstedge);
592: out->numedges = LittleShort(in->numedges);
593: if (out->numedges < 3)
594: ri.Sys_Error (ERR_DROP,"Surface with %s edges", out->numedges);
595: out->flags = 0;
596:
597: planenum = LittleShort(in->planenum);
598: side = LittleShort(in->side);
599: if (side)
600: out->flags |= SURF_PLANEBACK;
601:
602: out->plane = loadmodel->planes + planenum;
603:
604: out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
605:
606: CalcSurfaceExtents (out);
607:
608: // lighting info is converted from 24 bit on disk to 8 bit
609:
610: for (i=0 ; i<MAXLIGHTMAPS ; i++)
611: out->styles[i] = in->styles[i];
612: i = LittleLong(in->lightofs);
613: if (i == -1)
614: out->samples = NULL;
615: else
616: out->samples = loadmodel->lightdata + i/3;
617:
618: // set the drawing flags flag
619:
620: if (!out->texinfo->image)
621: continue;
622: if (out->texinfo->flags & SURF_SKY)
623: {
624: out->flags |= SURF_DRAWSKY;
625: continue;
626: }
627:
628: if (out->texinfo->flags & SURF_WARP)
629: {
630: out->flags |= SURF_DRAWTURB;
631: for (i=0 ; i<2 ; i++)
632: {
633: out->extents[i] = 16384;
634: out->texturemins[i] = -8192;
635: }
636: continue;
637: }
638: }
639: }
640:
641:
642: /*
643: =================
644: Mod_SetParent
645: =================
646: */
647: void Mod_SetParent (mnode_t *node, mnode_t *parent)
648: {
649: node->parent = parent;
650: if (node->contents != -1)
651: return;
652: Mod_SetParent (node->children[0], node);
653: Mod_SetParent (node->children[1], node);
654: }
655:
656: /*
657: =================
658: Mod_LoadNodes
659: =================
660: */
661: void Mod_LoadNodes (lump_t *l)
662: {
663: int i, j, count, p;
664: dnode_t *in;
665: mnode_t *out;
666:
667: in = (void *)(mod_base + l->fileofs);
668: if (l->filelen % sizeof(*in))
669: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
670: count = l->filelen / sizeof(*in);
671: out = Hunk_Alloc ( count*sizeof(*out));
672:
673: loadmodel->nodes = out;
674: loadmodel->numnodes = count;
675:
676: for ( i=0 ; i<count ; i++, in++, out++)
677: {
678: for (j=0 ; j<3 ; j++)
679: {
680: out->minmaxs[j] = LittleShort (in->mins[j]);
681: out->minmaxs[3+j] = LittleShort (in->maxs[j]);
682: }
683:
684: p = LittleLong(in->planenum);
685: out->plane = loadmodel->planes + p;
686:
687: out->firstsurface = LittleShort (in->firstface);
688: out->numsurfaces = LittleShort (in->numfaces);
689: out->contents = CONTENTS_NODE; // differentiate from leafs
690:
691: for (j=0 ; j<2 ; j++)
692: {
693: p = LittleLong (in->children[j]);
694: if (p >= 0)
695: out->children[j] = loadmodel->nodes + p;
696: else
697: out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
698: }
699: }
700:
701: Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
702: }
703:
704: /*
705: =================
706: Mod_LoadLeafs
707: =================
708: */
709: void Mod_LoadLeafs (lump_t *l)
710: {
711: dleaf_t *in;
712: mleaf_t *out;
713: int i, j, count;
714:
715: in = (void *)(mod_base + l->fileofs);
716: if (l->filelen % sizeof(*in))
717: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
718: count = l->filelen / sizeof(*in);
719: out = Hunk_Alloc ( count*sizeof(*out));
720:
721: loadmodel->leafs = out;
722: loadmodel->numleafs = count;
723:
724: for ( i=0 ; i<count ; i++, in++, out++)
725: {
726: for (j=0 ; j<3 ; j++)
727: {
728: out->minmaxs[j] = LittleShort (in->mins[j]);
729: out->minmaxs[3+j] = LittleShort (in->maxs[j]);
730: }
731:
732: out->contents = LittleLong(in->contents);
733: out->cluster = LittleShort(in->cluster);
734: out->area = LittleShort(in->area);
735:
736: out->firstmarksurface = loadmodel->marksurfaces +
737: LittleShort(in->firstleafface);
738: out->nummarksurfaces = LittleShort(in->numleaffaces);
739: }
740: }
741:
742:
743: /*
744: =================
745: Mod_LoadMarksurfaces
746: =================
747: */
748: void Mod_LoadMarksurfaces (lump_t *l)
749: {
750: int i, j, count;
751: short *in;
752: msurface_t **out;
753:
754: in = (void *)(mod_base + l->fileofs);
755: if (l->filelen % sizeof(*in))
756: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
757: count = l->filelen / sizeof(*in);
758: out = Hunk_Alloc ( count*sizeof(*out));
759:
760: loadmodel->marksurfaces = out;
761: loadmodel->nummarksurfaces = count;
762:
763: for ( i=0 ; i<count ; i++)
764: {
765: j = LittleShort(in[i]);
766: if (j >= loadmodel->numsurfaces)
767: ri.Sys_Error (ERR_DROP,"Mod_ParseMarksurfaces: bad surface number");
768: out[i] = loadmodel->surfaces + j;
769: }
770: }
771:
772: /*
773: =================
774: Mod_LoadSurfedges
775: =================
776: */
777: void Mod_LoadSurfedges (lump_t *l)
778: {
779: int i, count;
780: int *in, *out;
781:
782: in = (void *)(mod_base + l->fileofs);
783: if (l->filelen % sizeof(*in))
784: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
785: count = l->filelen / sizeof(*in);
786: out = Hunk_Alloc ( (count+24)*sizeof(*out)); // extra for skybox
787:
788: loadmodel->surfedges = out;
789: loadmodel->numsurfedges = count;
790:
791: for ( i=0 ; i<count ; i++)
792: out[i] = LittleLong (in[i]);
793: }
794:
795: /*
796: =================
797: Mod_LoadPlanes
798: =================
799: */
800: void Mod_LoadPlanes (lump_t *l)
801: {
802: int i, j;
803: mplane_t *out;
804: dplane_t *in;
805: int count;
806: int bits;
807:
808: in = (void *)(mod_base + l->fileofs);
809: if (l->filelen % sizeof(*in))
810: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
811: count = l->filelen / sizeof(*in);
812: out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
813:
814: loadmodel->planes = out;
815: loadmodel->numplanes = count;
816:
817: for ( i=0 ; i<count ; i++, in++, out++)
818: {
819: bits = 0;
820: for (j=0 ; j<3 ; j++)
821: {
822: out->normal[j] = LittleFloat (in->normal[j]);
823: if (out->normal[j] < 0)
824: bits |= 1<<j;
825: }
826:
827: out->dist = LittleFloat (in->dist);
828: out->type = LittleLong (in->type);
829: out->signbits = bits;
830: }
831: }
832:
833:
834: /*
835: =================
836: Mod_LoadBrushModel
837: =================
838: */
839: void Mod_LoadBrushModel (model_t *mod, void *buffer)
840: {
841: int i;
842: dheader_t *header;
843: dmodel_t *bm;
844:
845: loadmodel->type = mod_brush;
846: if (loadmodel != mod_known)
847: ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world");
848:
849: header = (dheader_t *)buffer;
850:
851: i = LittleLong (header->version);
852: if (i != BSPVERSION)
853: ri.Sys_Error (ERR_DROP,"Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
854:
855: // swap all the lumps
856: mod_base = (byte *)header;
857:
858: for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
859: ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
860:
861: // load into heap
862:
863: Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
864: Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
865: Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
866: Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
867: Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
868: Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
869: Mod_LoadFaces (&header->lumps[LUMP_FACES]);
870: Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]);
871: Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
872: Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
873: Mod_LoadNodes (&header->lumps[LUMP_NODES]);
874: Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
875: r_numvisleafs = 0;
876: R_NumberLeafs (loadmodel->nodes);
877:
878: //
879: // set up the submodels
880: //
881: for (i=0 ; i<mod->numsubmodels ; i++)
882: {
883: model_t *starmod;
884:
885: bm = &mod->submodels[i];
886: starmod = &mod_inline[i];
887:
888: *starmod = *loadmodel;
889:
890: starmod->firstmodelsurface = bm->firstface;
891: starmod->nummodelsurfaces = bm->numfaces;
892: starmod->firstnode = bm->headnode;
893: if (starmod->firstnode >= loadmodel->numnodes)
894: ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i);
895:
896: VectorCopy (bm->maxs, starmod->maxs);
897: VectorCopy (bm->mins, starmod->mins);
898:
899: if (i == 0)
900: *loadmodel = *starmod;
901: }
902:
903: R_InitSkyBox ();
904: }
905:
906: /*
907: ==============================================================================
908:
909: ALIAS MODELS
910:
911: ==============================================================================
912: */
913:
914: /*
915: =================
916: Mod_LoadAliasModel
917: =================
918: */
919: void Mod_LoadAliasModel (model_t *mod, void *buffer)
920: {
921: int i, j;
922: dmdl_t *pinmodel, *pheader;
923: dstvert_t *pinst, *poutst;
924: dtriangle_t *pintri, *pouttri;
925: daliasframe_t *pinframe, *poutframe;
926: int *pincmd, *poutcmd;
927: int version;
928:
929: pinmodel = (dmdl_t *)buffer;
930:
931: version = LittleLong (pinmodel->version);
932: if (version != ALIAS_VERSION)
933: ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
934: mod->name, version, ALIAS_VERSION);
935:
936: pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
937:
938: // byte swap the header fields and sanity check
939: for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
940: ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);
941:
942: if (pheader->skinheight > MAX_LBM_HEIGHT)
943: ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
944: MAX_LBM_HEIGHT);
945:
946: if (pheader->num_xyz <= 0)
947: ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name);
948:
949: if (pheader->num_xyz > MAX_VERTS)
950: ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name);
951:
952: if (pheader->num_st <= 0)
953: ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name);
954:
955: if (pheader->num_tris <= 0)
956: ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name);
957:
958: if (pheader->num_frames <= 0)
959: ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name);
960:
961: //
962: // load base s and t vertices (not used in gl version)
963: //
964: pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
965: poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);
966:
967: for (i=0 ; i<pheader->num_st ; i++)
968: {
969: poutst[i].s = LittleShort (pinst[i].s);
970: poutst[i].t = LittleShort (pinst[i].t);
971: }
972:
973: //
974: // load triangle lists
975: //
976: pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
977: pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
978:
979: for (i=0 ; i<pheader->num_tris ; i++)
980: {
981: for (j=0 ; j<3 ; j++)
982: {
983: pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
984: pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
985: }
986: }
987:
988: //
989: // load the frames
990: //
991: for (i=0 ; i<pheader->num_frames ; i++)
992: {
993: pinframe = (daliasframe_t *) ((byte *)pinmodel
994: + pheader->ofs_frames + i * pheader->framesize);
995: poutframe = (daliasframe_t *) ((byte *)pheader
996: + pheader->ofs_frames + i * pheader->framesize);
997:
998: memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
999: for (j=0 ; j<3 ; j++)
1000: {
1001: poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
1002: poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
1003: }
1004: // verts are all 8 bit, so no swapping needed
1005: memcpy (poutframe->verts, pinframe->verts,
1006: pheader->num_xyz*sizeof(dtrivertx_t));
1007:
1008: }
1009:
1010: mod->type = mod_alias;
1011:
1012: //
1013: // load the glcmds
1014: //
1015: pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
1016: poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
1017: for (i=0 ; i<pheader->num_glcmds ; i++)
1018: poutcmd[i] = LittleLong (pincmd[i]);
1019:
1020:
1021: // register all skins
1022: memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
1023: pheader->num_skins*MAX_SKINNAME);
1024: for (i=0 ; i<pheader->num_skins ; i++)
1025: {
1026: mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
1027: }
1028: }
1029:
1030: /*
1031: ==============================================================================
1032:
1033: SPRITE MODELS
1034:
1035: ==============================================================================
1036: */
1037:
1038: /*
1039: =================
1040: Mod_LoadSpriteModel
1041: =================
1042: */
1043: void Mod_LoadSpriteModel (model_t *mod, void *buffer)
1044: {
1045: dsprite_t *sprin, *sprout;
1046: int i;
1047:
1048: sprin = (dsprite_t *)buffer;
1049: sprout = Hunk_Alloc (modfilelen);
1050:
1051: sprout->ident = LittleLong (sprin->ident);
1052: sprout->version = LittleLong (sprin->version);
1053: sprout->numframes = LittleLong (sprin->numframes);
1054:
1055: if (sprout->version != SPRITE_VERSION)
1056: ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
1057: mod->name, sprout->version, SPRITE_VERSION);
1058:
1059: if (sprout->numframes > MAX_MD2SKINS)
1060: ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)",
1061: mod->name, sprout->numframes, MAX_MD2SKINS);
1062:
1063: // byte swap everything
1064: for (i=0 ; i<sprout->numframes ; i++)
1065: {
1066: sprout->frames[i].width = LittleLong (sprin->frames[i].width);
1067: sprout->frames[i].height = LittleLong (sprin->frames[i].height);
1068: sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x);
1069: sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y);
1070: memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
1071: mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
1072: }
1073:
1074: mod->type = mod_sprite;
1075: }
1076:
1077: //=============================================================================
1078:
1079: /*
1080: @@@@@@@@@@@@@@@@@@@@@
1081: R_BeginRegistration
1082:
1083: Specifies the model that will be used as the world
1084: @@@@@@@@@@@@@@@@@@@@@
1085: */
1086: void R_BeginRegistration (char *model)
1087: {
1088: char fullname[MAX_QPATH];
1089: cvar_t *flushmap;
1090:
1091: registration_sequence++;
1092: r_oldviewcluster = -1; // force markleafs
1093: Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model);
1094:
1095: D_FlushCaches ();
1096: // explicitly free the old map if different
1097: // this guarantees that mod_known[0] is the world map
1098: flushmap = ri.Cvar_Get ("flushmap", "0", 0);
1099: if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
1100: Mod_Free (&mod_known[0]);
1101: r_worldmodel = R_RegisterModel (fullname);
1102: R_NewMap ();
1103: }
1104:
1105:
1106: /*
1107: @@@@@@@@@@@@@@@@@@@@@
1108: R_RegisterModel
1109:
1110: @@@@@@@@@@@@@@@@@@@@@
1111: */
1112: struct model_s *R_RegisterModel (char *name)
1113: {
1114: model_t *mod;
1115: int i;
1116: dsprite_t *sprout;
1117: dmdl_t *pheader;
1118:
1119: mod = Mod_ForName (name, false);
1120: if (mod)
1121: {
1122: mod->registration_sequence = registration_sequence;
1123:
1124: // register any images used by the models
1125: if (mod->type == mod_sprite)
1126: {
1127: sprout = (dsprite_t *)mod->extradata;
1128: for (i=0 ; i<sprout->numframes ; i++)
1129: mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
1130: }
1131: else if (mod->type == mod_alias)
1132: {
1133: pheader = (dmdl_t *)mod->extradata;
1134: for (i=0 ; i<pheader->num_skins ; i++)
1135: mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
1136: }
1137: else if (mod->type == mod_brush)
1138: {
1139: for (i=0 ; i<mod->numtexinfo ; i++)
1140: mod->texinfo[i].image->registration_sequence = registration_sequence;
1141: }
1142: }
1143: return mod;
1144: }
1145:
1146: /*
1147: @@@@@@@@@@@@@@@@@@@@@
1148: R_EndRegistration
1149:
1150: @@@@@@@@@@@@@@@@@@@@@
1151: */
1152: void R_EndRegistration (void)
1153: {
1154: int i;
1155: model_t *mod;
1156:
1157: for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
1158: {
1159: if (!mod->name[0])
1160: continue;
1161: if (mod->registration_sequence != registration_sequence)
1162: { // don't need this model
1163: Hunk_Free (mod->extradata);
1164: memset (mod, 0, sizeof(*mod));
1165: }
1166: else
1167: { // make sure it is paged in
1168: Com_PageInMemory (mod->extradata, mod->extradatasize);
1169: }
1170: }
1171:
1172: R_FreeUnusedImages ();
1173: }
1174:
1175:
1176: //=============================================================================
1177:
1178: /*
1179: ================
1180: Mod_Free
1181: ================
1182: */
1183: void Mod_Free (model_t *mod)
1184: {
1185: Hunk_Free (mod->extradata);
1186: memset (mod, 0, sizeof(*mod));
1187: }
1188:
1189: /*
1190: ================
1191: Mod_FreeAll
1192: ================
1193: */
1194: void Mod_FreeAll (void)
1195: {
1196: int i;
1197:
1198: for (i=0 ; i<mod_numknown ; i++)
1199: {
1200: if (mod_known[i].extradatasize)
1201: Mod_Free (&mod_known[i]);
1202: }
1203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.