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