|
|
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: }
1.1.1.2 ! root 638: //==============
! 639: //PGM
! 640: // this marks flowing surfaces as turbulent, but with the new
! 641: // SURF_FLOW flag.
! 642: if (out->texinfo->flags & SURF_FLOWING)
! 643: {
! 644: out->flags |= SURF_DRAWTURB | SURF_FLOW;
! 645: for (i=0 ; i<2 ; i++)
! 646: {
! 647: out->extents[i] = 16384;
! 648: out->texturemins[i] = -8192;
! 649: }
! 650: continue;
! 651: }
! 652: //PGM
! 653: //==============
1.1 root 654: }
655: }
656:
657:
658: /*
659: =================
660: Mod_SetParent
661: =================
662: */
663: void Mod_SetParent (mnode_t *node, mnode_t *parent)
664: {
665: node->parent = parent;
666: if (node->contents != -1)
667: return;
668: Mod_SetParent (node->children[0], node);
669: Mod_SetParent (node->children[1], node);
670: }
671:
672: /*
673: =================
674: Mod_LoadNodes
675: =================
676: */
677: void Mod_LoadNodes (lump_t *l)
678: {
679: int i, j, count, p;
680: dnode_t *in;
681: mnode_t *out;
682:
683: in = (void *)(mod_base + l->fileofs);
684: if (l->filelen % sizeof(*in))
685: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
686: count = l->filelen / sizeof(*in);
687: out = Hunk_Alloc ( count*sizeof(*out));
688:
689: loadmodel->nodes = out;
690: loadmodel->numnodes = count;
691:
692: for ( i=0 ; i<count ; i++, in++, out++)
693: {
694: for (j=0 ; j<3 ; j++)
695: {
696: out->minmaxs[j] = LittleShort (in->mins[j]);
697: out->minmaxs[3+j] = LittleShort (in->maxs[j]);
698: }
699:
700: p = LittleLong(in->planenum);
701: out->plane = loadmodel->planes + p;
702:
703: out->firstsurface = LittleShort (in->firstface);
704: out->numsurfaces = LittleShort (in->numfaces);
705: out->contents = CONTENTS_NODE; // differentiate from leafs
706:
707: for (j=0 ; j<2 ; j++)
708: {
709: p = LittleLong (in->children[j]);
710: if (p >= 0)
711: out->children[j] = loadmodel->nodes + p;
712: else
713: out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
714: }
715: }
716:
717: Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
718: }
719:
720: /*
721: =================
722: Mod_LoadLeafs
723: =================
724: */
725: void Mod_LoadLeafs (lump_t *l)
726: {
727: dleaf_t *in;
728: mleaf_t *out;
729: int i, j, count;
730:
731: in = (void *)(mod_base + l->fileofs);
732: if (l->filelen % sizeof(*in))
733: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
734: count = l->filelen / sizeof(*in);
735: out = Hunk_Alloc ( count*sizeof(*out));
736:
737: loadmodel->leafs = out;
738: loadmodel->numleafs = count;
739:
740: for ( i=0 ; i<count ; i++, in++, out++)
741: {
742: for (j=0 ; j<3 ; j++)
743: {
744: out->minmaxs[j] = LittleShort (in->mins[j]);
745: out->minmaxs[3+j] = LittleShort (in->maxs[j]);
746: }
747:
748: out->contents = LittleLong(in->contents);
749: out->cluster = LittleShort(in->cluster);
750: out->area = LittleShort(in->area);
751:
752: out->firstmarksurface = loadmodel->marksurfaces +
753: LittleShort(in->firstleafface);
754: out->nummarksurfaces = LittleShort(in->numleaffaces);
755: }
756: }
757:
758:
759: /*
760: =================
761: Mod_LoadMarksurfaces
762: =================
763: */
764: void Mod_LoadMarksurfaces (lump_t *l)
765: {
766: int i, j, count;
767: short *in;
768: msurface_t **out;
769:
770: in = (void *)(mod_base + l->fileofs);
771: if (l->filelen % sizeof(*in))
772: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
773: count = l->filelen / sizeof(*in);
774: out = Hunk_Alloc ( count*sizeof(*out));
775:
776: loadmodel->marksurfaces = out;
777: loadmodel->nummarksurfaces = count;
778:
779: for ( i=0 ; i<count ; i++)
780: {
781: j = LittleShort(in[i]);
782: if (j >= loadmodel->numsurfaces)
783: ri.Sys_Error (ERR_DROP,"Mod_ParseMarksurfaces: bad surface number");
784: out[i] = loadmodel->surfaces + j;
785: }
786: }
787:
788: /*
789: =================
790: Mod_LoadSurfedges
791: =================
792: */
793: void Mod_LoadSurfedges (lump_t *l)
794: {
795: int i, count;
796: int *in, *out;
797:
798: in = (void *)(mod_base + l->fileofs);
799: if (l->filelen % sizeof(*in))
800: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
801: count = l->filelen / sizeof(*in);
802: out = Hunk_Alloc ( (count+24)*sizeof(*out)); // extra for skybox
803:
804: loadmodel->surfedges = out;
805: loadmodel->numsurfedges = count;
806:
807: for ( i=0 ; i<count ; i++)
808: out[i] = LittleLong (in[i]);
809: }
810:
811: /*
812: =================
813: Mod_LoadPlanes
814: =================
815: */
816: void Mod_LoadPlanes (lump_t *l)
817: {
818: int i, j;
819: mplane_t *out;
820: dplane_t *in;
821: int count;
822: int bits;
823:
824: in = (void *)(mod_base + l->fileofs);
825: if (l->filelen % sizeof(*in))
826: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
827: count = l->filelen / sizeof(*in);
828: out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
829:
830: loadmodel->planes = out;
831: loadmodel->numplanes = count;
832:
833: for ( i=0 ; i<count ; i++, in++, out++)
834: {
835: bits = 0;
836: for (j=0 ; j<3 ; j++)
837: {
838: out->normal[j] = LittleFloat (in->normal[j]);
839: if (out->normal[j] < 0)
840: bits |= 1<<j;
841: }
842:
843: out->dist = LittleFloat (in->dist);
844: out->type = LittleLong (in->type);
845: out->signbits = bits;
846: }
847: }
848:
849:
850: /*
851: =================
852: Mod_LoadBrushModel
853: =================
854: */
855: void Mod_LoadBrushModel (model_t *mod, void *buffer)
856: {
857: int i;
858: dheader_t *header;
859: dmodel_t *bm;
860:
861: loadmodel->type = mod_brush;
862: if (loadmodel != mod_known)
863: ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world");
864:
865: header = (dheader_t *)buffer;
866:
867: i = LittleLong (header->version);
868: if (i != BSPVERSION)
869: ri.Sys_Error (ERR_DROP,"Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
870:
871: // swap all the lumps
872: mod_base = (byte *)header;
873:
874: for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
875: ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
876:
877: // load into heap
878:
879: Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
880: Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
881: Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
882: Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
883: Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
884: Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
885: Mod_LoadFaces (&header->lumps[LUMP_FACES]);
886: Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]);
887: Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
888: Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
889: Mod_LoadNodes (&header->lumps[LUMP_NODES]);
890: Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
891: r_numvisleafs = 0;
892: R_NumberLeafs (loadmodel->nodes);
893:
894: //
895: // set up the submodels
896: //
897: for (i=0 ; i<mod->numsubmodels ; i++)
898: {
899: model_t *starmod;
900:
901: bm = &mod->submodels[i];
902: starmod = &mod_inline[i];
903:
904: *starmod = *loadmodel;
905:
906: starmod->firstmodelsurface = bm->firstface;
907: starmod->nummodelsurfaces = bm->numfaces;
908: starmod->firstnode = bm->headnode;
909: if (starmod->firstnode >= loadmodel->numnodes)
910: ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i);
911:
912: VectorCopy (bm->maxs, starmod->maxs);
913: VectorCopy (bm->mins, starmod->mins);
914:
915: if (i == 0)
916: *loadmodel = *starmod;
917: }
918:
919: R_InitSkyBox ();
920: }
921:
922: /*
923: ==============================================================================
924:
925: ALIAS MODELS
926:
927: ==============================================================================
928: */
929:
930: /*
931: =================
932: Mod_LoadAliasModel
933: =================
934: */
935: void Mod_LoadAliasModel (model_t *mod, void *buffer)
936: {
937: int i, j;
938: dmdl_t *pinmodel, *pheader;
939: dstvert_t *pinst, *poutst;
940: dtriangle_t *pintri, *pouttri;
941: daliasframe_t *pinframe, *poutframe;
942: int *pincmd, *poutcmd;
943: int version;
944:
945: pinmodel = (dmdl_t *)buffer;
946:
947: version = LittleLong (pinmodel->version);
948: if (version != ALIAS_VERSION)
949: ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
950: mod->name, version, ALIAS_VERSION);
951:
952: pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
953:
954: // byte swap the header fields and sanity check
955: for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
956: ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);
957:
958: if (pheader->skinheight > MAX_LBM_HEIGHT)
959: ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
960: MAX_LBM_HEIGHT);
961:
962: if (pheader->num_xyz <= 0)
963: ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name);
964:
965: if (pheader->num_xyz > MAX_VERTS)
966: ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name);
967:
968: if (pheader->num_st <= 0)
969: ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name);
970:
971: if (pheader->num_tris <= 0)
972: ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name);
973:
974: if (pheader->num_frames <= 0)
975: ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name);
976:
977: //
978: // load base s and t vertices (not used in gl version)
979: //
980: pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
981: poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);
982:
983: for (i=0 ; i<pheader->num_st ; i++)
984: {
985: poutst[i].s = LittleShort (pinst[i].s);
986: poutst[i].t = LittleShort (pinst[i].t);
987: }
988:
989: //
990: // load triangle lists
991: //
992: pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
993: pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
994:
995: for (i=0 ; i<pheader->num_tris ; i++)
996: {
997: for (j=0 ; j<3 ; j++)
998: {
999: pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
1000: pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
1001: }
1002: }
1003:
1004: //
1005: // load the frames
1006: //
1007: for (i=0 ; i<pheader->num_frames ; i++)
1008: {
1009: pinframe = (daliasframe_t *) ((byte *)pinmodel
1010: + pheader->ofs_frames + i * pheader->framesize);
1011: poutframe = (daliasframe_t *) ((byte *)pheader
1012: + pheader->ofs_frames + i * pheader->framesize);
1013:
1014: memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
1015: for (j=0 ; j<3 ; j++)
1016: {
1017: poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
1018: poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
1019: }
1020: // verts are all 8 bit, so no swapping needed
1021: memcpy (poutframe->verts, pinframe->verts,
1022: pheader->num_xyz*sizeof(dtrivertx_t));
1023:
1024: }
1025:
1026: mod->type = mod_alias;
1027:
1028: //
1029: // load the glcmds
1030: //
1031: pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
1032: poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
1033: for (i=0 ; i<pheader->num_glcmds ; i++)
1034: poutcmd[i] = LittleLong (pincmd[i]);
1035:
1036:
1037: // register all skins
1038: memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
1039: pheader->num_skins*MAX_SKINNAME);
1040: for (i=0 ; i<pheader->num_skins ; i++)
1041: {
1042: mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
1043: }
1044: }
1045:
1046: /*
1047: ==============================================================================
1048:
1049: SPRITE MODELS
1050:
1051: ==============================================================================
1052: */
1053:
1054: /*
1055: =================
1056: Mod_LoadSpriteModel
1057: =================
1058: */
1059: void Mod_LoadSpriteModel (model_t *mod, void *buffer)
1060: {
1061: dsprite_t *sprin, *sprout;
1062: int i;
1063:
1064: sprin = (dsprite_t *)buffer;
1065: sprout = Hunk_Alloc (modfilelen);
1066:
1067: sprout->ident = LittleLong (sprin->ident);
1068: sprout->version = LittleLong (sprin->version);
1069: sprout->numframes = LittleLong (sprin->numframes);
1070:
1071: if (sprout->version != SPRITE_VERSION)
1072: ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
1073: mod->name, sprout->version, SPRITE_VERSION);
1074:
1075: if (sprout->numframes > MAX_MD2SKINS)
1076: ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)",
1077: mod->name, sprout->numframes, MAX_MD2SKINS);
1078:
1079: // byte swap everything
1080: for (i=0 ; i<sprout->numframes ; i++)
1081: {
1082: sprout->frames[i].width = LittleLong (sprin->frames[i].width);
1083: sprout->frames[i].height = LittleLong (sprin->frames[i].height);
1084: sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x);
1085: sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y);
1086: memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
1087: mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
1088: }
1089:
1090: mod->type = mod_sprite;
1091: }
1092:
1093: //=============================================================================
1094:
1095: /*
1096: @@@@@@@@@@@@@@@@@@@@@
1097: R_BeginRegistration
1098:
1099: Specifies the model that will be used as the world
1100: @@@@@@@@@@@@@@@@@@@@@
1101: */
1102: void R_BeginRegistration (char *model)
1103: {
1104: char fullname[MAX_QPATH];
1105: cvar_t *flushmap;
1106:
1107: registration_sequence++;
1108: r_oldviewcluster = -1; // force markleafs
1109: Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model);
1110:
1111: D_FlushCaches ();
1112: // explicitly free the old map if different
1113: // this guarantees that mod_known[0] is the world map
1114: flushmap = ri.Cvar_Get ("flushmap", "0", 0);
1115: if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
1116: Mod_Free (&mod_known[0]);
1117: r_worldmodel = R_RegisterModel (fullname);
1118: R_NewMap ();
1119: }
1120:
1121:
1122: /*
1123: @@@@@@@@@@@@@@@@@@@@@
1124: R_RegisterModel
1125:
1126: @@@@@@@@@@@@@@@@@@@@@
1127: */
1128: struct model_s *R_RegisterModel (char *name)
1129: {
1130: model_t *mod;
1131: int i;
1132: dsprite_t *sprout;
1133: dmdl_t *pheader;
1134:
1135: mod = Mod_ForName (name, false);
1136: if (mod)
1137: {
1138: mod->registration_sequence = registration_sequence;
1139:
1140: // register any images used by the models
1141: if (mod->type == mod_sprite)
1142: {
1143: sprout = (dsprite_t *)mod->extradata;
1144: for (i=0 ; i<sprout->numframes ; i++)
1145: mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
1146: }
1147: else if (mod->type == mod_alias)
1148: {
1149: pheader = (dmdl_t *)mod->extradata;
1150: for (i=0 ; i<pheader->num_skins ; i++)
1151: mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
1.1.1.2 ! root 1152: //PGM
! 1153: mod->numframes = pheader->num_frames;
! 1154: //PGM
1.1 root 1155: }
1156: else if (mod->type == mod_brush)
1157: {
1158: for (i=0 ; i<mod->numtexinfo ; i++)
1159: mod->texinfo[i].image->registration_sequence = registration_sequence;
1160: }
1161: }
1162: return mod;
1163: }
1164:
1165: /*
1166: @@@@@@@@@@@@@@@@@@@@@
1167: R_EndRegistration
1168:
1169: @@@@@@@@@@@@@@@@@@@@@
1170: */
1171: void R_EndRegistration (void)
1172: {
1173: int i;
1174: model_t *mod;
1175:
1176: for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
1177: {
1178: if (!mod->name[0])
1179: continue;
1180: if (mod->registration_sequence != registration_sequence)
1181: { // don't need this model
1182: Hunk_Free (mod->extradata);
1183: memset (mod, 0, sizeof(*mod));
1184: }
1185: else
1186: { // make sure it is paged in
1187: Com_PageInMemory (mod->extradata, mod->extradatasize);
1188: }
1189: }
1190:
1191: R_FreeUnusedImages ();
1192: }
1193:
1194:
1195: //=============================================================================
1196:
1197: /*
1198: ================
1199: Mod_Free
1200: ================
1201: */
1202: void Mod_Free (model_t *mod)
1203: {
1204: Hunk_Free (mod->extradata);
1205: memset (mod, 0, sizeof(*mod));
1206: }
1207:
1208: /*
1209: ================
1210: Mod_FreeAll
1211: ================
1212: */
1213: void Mod_FreeAll (void)
1214: {
1215: int i;
1216:
1217: for (i=0 ; i<mod_numknown ; i++)
1218: {
1219: if (mod_known[i].extradatasize)
1220: Mod_Free (&mod_known[i]);
1221: }
1222: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.