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(const char * name)184 model_t *Mod_FindName (const 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(const char * name)217 void Mod_TouchModel (const 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, sizeof(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(const char * name,qboolean crash)313 model_t *Mod_ForName (const 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 = (texture_t**) 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 = (texture_t*) 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 = (byte*) 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 = (byte*) 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 = (char*) 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 = (dvertex_t*) (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 = (mvertex_t*) 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 = (dmodel_t*) (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 =(dmodel_t*) 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 = (dedge_t *) (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 = (medge_t*) 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 = (texinfo_t *)(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 = (mtexinfo_t*) 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] = (int) floorf(mins[i]/16);
742 bmaxs[i] = (int) ceilf(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 = (dface_t *)(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 = (msurface_t*) 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 = (dnode_t *)(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 = (mnode_t*) 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
899 in = (dleaf_t *)(mod_base + l->fileofs);
900 if (l->filelen % sizeof(*in))
901 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
902 count = l->filelen / sizeof(*in);
903 out = (mleaf_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
904
905 loadmodel->leafs = out;
906 loadmodel->numleafs = count;
907
908 for ( i=0 ; i<count ; i++, in++, out++)
909 {
910 for (j=0 ; j<3 ; j++)
911 {
912 out->minmaxs[j] = LittleShort (in->mins[j]);
913 out->minmaxs[3+j] = LittleShort (in->maxs[j]);
914 }
915
916 p = LittleLong(in->contents);
917 out->contents = p;
918
919 out->firstmarksurface = loadmodel->marksurfaces +
920 LittleShort(in->firstmarksurface);
921 out->nummarksurfaces = LittleShort(in->nummarksurfaces);
922
923 p = LittleLong(in->visofs);
924 if (p == -1)
925 out->compressed_vis = NULL;
926 else
927 out->compressed_vis = loadmodel->visdata + p;
928 out->efrags = NULL;
929
930 for (j=0 ; j<4 ; j++)
931 out->ambient_sound_level[j] = in->ambient_level[j];
932
933 // gl underwater warp
934 if (out->contents != CONTENTS_EMPTY)
935 {
936 for (j=0 ; j<out->nummarksurfaces ; j++)
937 out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
938 }
939 }
940 }
941
942 /*
943 =================
944 Mod_LoadClipnodes
945 =================
946 */
Mod_LoadClipnodes(lump_t * l)947 void Mod_LoadClipnodes (lump_t *l)
948 {
949 dclipnode_t *in, *out;
950 int i, count;
951 hull_t *hull;
952
953 in = (dclipnode_t *)(mod_base + l->fileofs);
954 if (l->filelen % sizeof(*in))
955 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
956 count = l->filelen / sizeof(*in);
957 out = (dclipnode_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
958
959 loadmodel->clipnodes = out;
960 loadmodel->numclipnodes = count;
961
962 hull = &loadmodel->hulls[1];
963 hull->clipnodes = out;
964 hull->firstclipnode = 0;
965 hull->lastclipnode = count-1;
966 hull->planes = loadmodel->planes;
967 hull->clip_mins[0] = -16;
968 hull->clip_mins[1] = -16;
969 hull->clip_mins[2] = -24;
970 hull->clip_maxs[0] = 16;
971 hull->clip_maxs[1] = 16;
972 hull->clip_maxs[2] = 32;
973
974 hull = &loadmodel->hulls[2];
975 hull->clipnodes = out;
976 hull->firstclipnode = 0;
977 hull->lastclipnode = count-1;
978 hull->planes = loadmodel->planes;
979 hull->clip_mins[0] = -32;
980 hull->clip_mins[1] = -32;
981 hull->clip_mins[2] = -24;
982 hull->clip_maxs[0] = 32;
983 hull->clip_maxs[1] = 32;
984 hull->clip_maxs[2] = 64;
985
986 for (i=0 ; i<count ; i++, out++, in++)
987 {
988 out->planenum = LittleLong(in->planenum);
989 out->children[0] = LittleShort(in->children[0]);
990 out->children[1] = LittleShort(in->children[1]);
991 }
992 }
993
994 /*
995 =================
996 Mod_MakeHull0
997
998 Deplicate the drawing hull structure as a clipping hull
999 =================
1000 */
Mod_MakeHull0(void)1001 void Mod_MakeHull0 (void)
1002 {
1003 mnode_t *in, *child;
1004 dclipnode_t *out;
1005 int i, j, count;
1006 hull_t *hull;
1007
1008 hull = &loadmodel->hulls[0];
1009
1010 in = loadmodel->nodes;
1011 count = loadmodel->numnodes;
1012 out = (dclipnode_t*) Hunk_AllocName ( count*sizeof(*out), loadname);
1013
1014 hull->clipnodes = out;
1015 hull->firstclipnode = 0;
1016 hull->lastclipnode = count-1;
1017 hull->planes = loadmodel->planes;
1018
1019 for (i=0 ; i<count ; i++, out++, in++)
1020 {
1021 out->planenum = in->plane - loadmodel->planes;
1022 for (j=0 ; j<2 ; j++)
1023 {
1024 child = in->children[j];
1025 if (child->contents < 0)
1026 out->children[j] = child->contents;
1027 else
1028 out->children[j] = child - loadmodel->nodes;
1029 }
1030 }
1031 }
1032
1033 /*
1034 =================
1035 Mod_LoadMarksurfaces
1036 =================
1037 */
Mod_LoadMarksurfaces(lump_t * l)1038 void Mod_LoadMarksurfaces (lump_t *l)
1039 {
1040 int i, j, count;
1041 short *in;
1042 msurface_t **out;
1043
1044 in = (short *)(mod_base + l->fileofs);
1045 if (l->filelen % sizeof(*in))
1046 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1047 count = l->filelen / sizeof(*in);
1048 out = (msurface_t **) Hunk_AllocName ( count*sizeof(*out), loadname);
1049
1050 loadmodel->marksurfaces = out;
1051 loadmodel->nummarksurfaces = count;
1052
1053 for ( i=0 ; i<count ; i++)
1054 {
1055 j = LittleShort(in[i]);
1056 if (j >= loadmodel->numsurfaces)
1057 Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
1058 out[i] = loadmodel->surfaces + j;
1059 }
1060 }
1061
1062 /*
1063 =================
1064 Mod_LoadSurfedges
1065 =================
1066 */
Mod_LoadSurfedges(lump_t * l)1067 void Mod_LoadSurfedges (lump_t *l)
1068 {
1069 int i, count;
1070 int *in, *out;
1071
1072 in = (int *)(mod_base + l->fileofs);
1073 if (l->filelen % sizeof(*in))
1074 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1075 count = l->filelen / sizeof(*in);
1076 out = (int*) Hunk_AllocName ( count*sizeof(*out), loadname);
1077
1078 loadmodel->surfedges = out;
1079 loadmodel->numsurfedges = count;
1080
1081 for ( i=0 ; i<count ; i++)
1082 out[i] = LittleLong (in[i]);
1083 }
1084
1085
1086 /*
1087 =================
1088 Mod_LoadPlanes
1089 =================
1090 */
Mod_LoadPlanes(lump_t * l)1091 void Mod_LoadPlanes (lump_t *l)
1092 {
1093 int i, j;
1094 mplane_t *out;
1095 dplane_t *in;
1096 int count;
1097 int bits;
1098
1099 in = (dplane_t *)(mod_base + l->fileofs);
1100 if (l->filelen % sizeof(*in))
1101 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1102 count = l->filelen / sizeof(*in);
1103 out = (mplane_t*) Hunk_AllocName ( count*2*sizeof(*out), loadname);
1104
1105 loadmodel->planes = out;
1106 loadmodel->numplanes = count;
1107
1108 for ( i=0 ; i<count ; i++, in++, out++)
1109 {
1110 bits = 0;
1111 for (j=0 ; j<3 ; j++)
1112 {
1113 out->normal[j] = LittleFloat (in->normal[j]);
1114 if (out->normal[j] < 0)
1115 bits |= 1<<j;
1116 }
1117
1118 out->dist = LittleFloat (in->dist);
1119 out->type = LittleLong (in->type);
1120 out->signbits = bits;
1121 }
1122 }
1123
1124 /*
1125 =================
1126 RadiusFromBounds
1127 =================
1128 */
RadiusFromBounds(vec3_t mins,vec3_t maxs)1129 float RadiusFromBounds (vec3_t mins, vec3_t maxs)
1130 {
1131 int i;
1132 vec3_t corner;
1133
1134 for (i=0 ; i<3 ; i++)
1135 {
1136 corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
1137 }
1138
1139 return Length (corner);
1140 }
1141
1142 /*
1143 =================
1144 Mod_LoadBrushModel
1145 =================
1146 */
Mod_LoadBrushModel(model_t * mod,void * buffer)1147 void Mod_LoadBrushModel (model_t *mod, void *buffer)
1148 {
1149 int i, j;
1150 dheader_t *header;
1151 dmodel_t *bm;
1152
1153 loadmodel->type = mod_brush;
1154
1155 header = (dheader_t *)buffer;
1156
1157 i = LittleLong (header->version);
1158 if (i != BSPVERSION)
1159 Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
1160
1161 // swap all the lumps
1162 mod_base = (byte *)header;
1163
1164 for (i=0 ; i< (int) (sizeof(dheader_t)/4) ; i++)
1165 ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
1166
1167 // load into heap
1168
1169 Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
1170 Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
1171 Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
1172 Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
1173 Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
1174 Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
1175 Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
1176 Mod_LoadFaces (&header->lumps[LUMP_FACES]);
1177 Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
1178 Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
1179 Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
1180 Mod_LoadNodes (&header->lumps[LUMP_NODES]);
1181 Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
1182 Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
1183 Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
1184
1185 Mod_MakeHull0 ();
1186
1187 mod->numframes = 2; // regular and alternate animation
1188
1189 //
1190 // set up the submodels (FIXME: this is confusing)
1191 //
1192 for (i=0 ; i<mod->numsubmodels ; i++)
1193 {
1194 bm = &mod->submodels[i];
1195
1196 mod->hulls[0].firstclipnode = bm->headnode[0];
1197 for (j=1 ; j<MAX_MAP_HULLS ; j++)
1198 {
1199 mod->hulls[j].firstclipnode = bm->headnode[j];
1200 mod->hulls[j].lastclipnode = mod->numclipnodes-1;
1201 }
1202
1203 mod->firstmodelsurface = bm->firstface;
1204 mod->nummodelsurfaces = bm->numfaces;
1205
1206 VectorCopy (bm->maxs, mod->maxs);
1207 VectorCopy (bm->mins, mod->mins);
1208
1209 mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
1210
1211 mod->numleafs = bm->visleafs;
1212
1213 if (i < mod->numsubmodels-1)
1214 { // duplicate the basic information
1215 char name[10];
1216
1217 sprintf (name, "*%i", i+1);
1218 loadmodel = Mod_FindName (name);
1219 *loadmodel = *mod;
1220 strcpy (loadmodel->name, name);
1221 mod = loadmodel;
1222 }
1223 }
1224 }
1225
1226 /*
1227 ==============================================================================
1228
1229 ALIAS MODELS
1230
1231 ==============================================================================
1232 */
1233
1234 aliashdr_t *pheader;
1235
1236 stvert_t stverts[MAXALIASVERTS];
1237 mtriangle_t triangles[MAXALIASTRIS];
1238
1239 // a pose is a single set of vertexes. a frame may be
1240 // an animating sequence of poses
1241 trivertx_t *poseverts[MAXALIASFRAMES];
1242 int posenum;
1243
1244 byte **player_8bit_texels_tbl;
1245 byte *player_8bit_texels;
1246
1247 /*
1248 =================
1249 Mod_LoadAliasFrame
1250 =================
1251 */
Mod_LoadAliasFrame(void * pin,maliasframedesc_t * frame)1252 void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
1253 {
1254 trivertx_t *pframe, *pinframe;
1255 int i, j;
1256 daliasframe_t *pdaliasframe;
1257
1258 pdaliasframe = (daliasframe_t *)pin;
1259
1260 strcpy (frame->name, pdaliasframe->name);
1261 frame->firstpose = posenum;
1262 frame->numposes = 1;
1263
1264 for (i=0 ; i<3 ; i++)
1265 {
1266 // these are byte values, so we don't have to worry about
1267 // endianness
1268 frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
1269 frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
1270 }
1271
1272 pinframe = (trivertx_t *)(pdaliasframe + 1);
1273
1274 poseverts[posenum] = pinframe;
1275 posenum++;
1276
1277 pinframe += pheader->numverts;
1278
1279 return (void *)pinframe;
1280 }
1281
1282
1283 /*
1284 =================
1285 Mod_LoadAliasGroup
1286 =================
1287 */
Mod_LoadAliasGroup(void * pin,maliasframedesc_t * frame)1288 void *Mod_LoadAliasGroup (void * pin, maliasframedesc_t *frame)
1289 {
1290 daliasgroup_t *pingroup;
1291 int i, numframes;
1292 daliasinterval_t *pin_intervals;
1293 void *ptemp;
1294
1295 pingroup = (daliasgroup_t *)pin;
1296
1297 numframes = LittleLong (pingroup->numframes);
1298
1299 frame->firstpose = posenum;
1300 frame->numposes = numframes;
1301
1302 for (i=0 ; i<3 ; i++)
1303 {
1304 // these are byte values, so we don't have to worry about endianness
1305 frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
1306 frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
1307 }
1308
1309 pin_intervals = (daliasinterval_t *)(pingroup + 1);
1310
1311 frame->interval = LittleFloat (pin_intervals->interval);
1312
1313 pin_intervals += numframes;
1314
1315 ptemp = (void *)pin_intervals;
1316
1317 for (i=0 ; i<numframes ; i++)
1318 {
1319 poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
1320 posenum++;
1321
1322 ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
1323 }
1324
1325 return ptemp;
1326 }
1327
1328 //=========================================================
1329
1330 /*
1331 =================
1332 Mod_FloodFillSkin
1333
1334 Fill background pixels so mipmapping doesn't have haloes - Ed
1335 =================
1336 */
1337
1338 typedef struct
1339 {
1340 short x, y;
1341 } floodfill_t;
1342
1343 extern unsigned d_8to24table[];
1344
1345 // must be a power of 2
1346 #define FLOODFILL_FIFO_SIZE 0x1000
1347 #define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
1348
1349 #define FLOODFILL_STEP( off, dx, dy ) \
1350 { \
1351 if (pos[off] == fillcolor) \
1352 { \
1353 pos[off] = 255; \
1354 fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
1355 inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
1356 } \
1357 else if (pos[off] != 255) fdc = pos[off]; \
1358 }
1359
Mod_FloodFillSkin(byte * skin,int skinwidth,int skinheight)1360 void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
1361 {
1362 byte fillcolor = *skin; // assume this is the pixel to fill
1363 floodfill_t fifo[FLOODFILL_FIFO_SIZE];
1364 int inpt = 0, outpt = 0;
1365 int filledcolor = -1;
1366 int i;
1367
1368 if (filledcolor == -1)
1369 {
1370 filledcolor = 0;
1371 // attempt to find opaque black
1372 for (i = 0; i < 256; ++i)
1373 if (d_8to24table[i] == (255 << 0)) // alpha 1.0
1374 {
1375 filledcolor = i;
1376 break;
1377 }
1378 }
1379
1380 // can't fill to filled color or to transparent color (used as visited marker)
1381 if ((fillcolor == filledcolor) || (fillcolor == 255))
1382 {
1383 //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
1384 return;
1385 }
1386
1387 fifo[inpt].x = 0, fifo[inpt].y = 0;
1388 inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
1389
1390 while (outpt != inpt)
1391 {
1392 int x = fifo[outpt].x, y = fifo[outpt].y;
1393 int fdc = filledcolor;
1394 byte *pos = &skin[x + skinwidth * y];
1395
1396 outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
1397
1398 if (x > 0) FLOODFILL_STEP( -1, -1, 0 );
1399 if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 );
1400 if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 );
1401 if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 );
1402 skin[x + skinwidth * y] = fdc;
1403 }
1404 }
1405
1406 /*
1407 ===============
1408 Mod_LoadAllSkins
1409 ===============
1410 */
Mod_LoadAllSkins(int numskins,daliasskintype_t * pskintype)1411 void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
1412 {
1413 int i, j, k;
1414 char name[32];
1415 int s;
1416 byte *copy;
1417 byte *skin;
1418 byte *texels;
1419 daliasskingroup_t *pinskingroup;
1420 int groupskins;
1421 daliasskininterval_t *pinskinintervals;
1422
1423 skin = (byte *)(pskintype + 1);
1424
1425 if (numskins < 1 || numskins > MAX_SKINS)
1426 Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
1427
1428 s = pheader->skinwidth * pheader->skinheight;
1429
1430 for (i=0 ; i<numskins ; i++)
1431 {
1432 if (pskintype->type == ALIAS_SKIN_SINGLE) {
1433 Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
1434
1435 // save 8 bit texels for the player model to remap
1436 // if (!strcmp(loadmodel->name,"progs/player.mdl")) {
1437 texels = (byte*) Hunk_AllocName(s, loadname);
1438 pheader->texels[i] = texels - (byte *)pheader;
1439 memcpy (texels, (byte *)(pskintype + 1), s);
1440 // }
1441 sprintf (name, "%s_%i", loadmodel->name, i);
1442 pheader->gl_texturenum[i][0] =
1443 pheader->gl_texturenum[i][1] =
1444 pheader->gl_texturenum[i][2] =
1445 pheader->gl_texturenum[i][3] =
1446 GL_LoadTexture (name, pheader->skinwidth,
1447 pheader->skinheight, (byte *)(pskintype + 1), true, false);
1448 pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
1449 } else {
1450 // animating skin group. yuck.
1451 pskintype++;
1452 pinskingroup = (daliasskingroup_t *)pskintype;
1453 groupskins = LittleLong (pinskingroup->numskins);
1454 pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
1455
1456 pskintype = (daliasskintype_t *)(pinskinintervals + groupskins);
1457
1458 for (j=0 ; j<groupskins ; j++)
1459 {
1460 Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
1461 if (j == 0) {
1462 texels = (byte*) Hunk_AllocName(s, loadname);
1463 pheader->texels[i] = texels - (byte *)pheader;
1464 memcpy (texels, (byte *)(pskintype), s);
1465 }
1466 sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
1467 pheader->gl_texturenum[i][j&3] =
1468 GL_LoadTexture (name, pheader->skinwidth,
1469 pheader->skinheight, (byte *)(pskintype), true, false);
1470 pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
1471 }
1472 k = j;
1473 for (/* */; j < 4; j++)
1474 pheader->gl_texturenum[i][j&3] =
1475 pheader->gl_texturenum[i][j - k];
1476 }
1477 }
1478
1479 return (void *)pskintype;
1480 }
1481
1482 //=========================================================================
1483
1484 /*
1485 =================
1486 Mod_LoadAliasModel
1487 =================
1488 */
Mod_LoadAliasModel(model_t * mod,void * buffer)1489 void Mod_LoadAliasModel (model_t *mod, void *buffer)
1490 {
1491 int i, j;
1492 mdl_t *pinmodel;
1493 stvert_t *pinstverts;
1494 dtriangle_t *pintriangles;
1495 int version, numframes, numskins;
1496 int size;
1497 daliasframetype_t *pframetype;
1498 daliasskintype_t *pskintype;
1499 int start, end, total;
1500
1501 start = Hunk_LowMark ();
1502
1503 pinmodel = (mdl_t *)buffer;
1504
1505 version = LittleLong (pinmodel->version);
1506 if (version != ALIAS_VERSION)
1507 Sys_Error ("%s has wrong version number (%i should be %i)",
1508 mod->name, version, ALIAS_VERSION);
1509
1510 //
1511 // allocate space for a working header, plus all the data except the frames,
1512 // skin and group info
1513 //
1514 size = sizeof (aliashdr_t)
1515 + (LittleLong (pinmodel->numframes) - 1) *
1516 sizeof (pheader->frames[0]);
1517 pheader = (aliashdr_t*) Hunk_AllocName (size, loadname);
1518
1519 mod->flags = LittleLong (pinmodel->flags);
1520
1521 //
1522 // endian-adjust and copy the data, starting with the alias model header
1523 //
1524 pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
1525 pheader->numskins = LittleLong (pinmodel->numskins);
1526 pheader->skinwidth = LittleLong (pinmodel->skinwidth);
1527 pheader->skinheight = LittleLong (pinmodel->skinheight);
1528
1529 if (pheader->skinheight > MAX_LBM_HEIGHT)
1530 Sys_Error ("model %s has a skin taller than %d", mod->name,
1531 MAX_LBM_HEIGHT);
1532
1533 pheader->numverts = LittleLong (pinmodel->numverts);
1534
1535 if (pheader->numverts <= 0)
1536 Sys_Error ("model %s has no vertices", mod->name);
1537
1538 if (pheader->numverts > MAXALIASVERTS)
1539 Sys_Error ("model %s has too many vertices", mod->name);
1540
1541 pheader->numtris = LittleLong (pinmodel->numtris);
1542
1543 if (pheader->numtris <= 0)
1544 Sys_Error ("model %s has no triangles", mod->name);
1545
1546 pheader->numframes = LittleLong (pinmodel->numframes);
1547 numframes = pheader->numframes;
1548 if (numframes < 1)
1549 Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
1550
1551 pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
1552 mod->synctype = (synctype_t) LittleLong (pinmodel->synctype);
1553 mod->numframes = pheader->numframes;
1554
1555 for (i=0 ; i<3 ; i++)
1556 {
1557 pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
1558 pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
1559 pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
1560 }
1561
1562
1563 //
1564 // load the skins
1565 //
1566 pskintype = (daliasskintype_t *)&pinmodel[1];
1567 pskintype = (daliasskintype_t*) Mod_LoadAllSkins (pheader->numskins, pskintype);
1568
1569 //
1570 // load base s and t vertices
1571 //
1572 pinstverts = (stvert_t *)pskintype;
1573
1574 for (i=0 ; i<pheader->numverts ; i++)
1575 {
1576 stverts[i].onseam = LittleLong (pinstverts[i].onseam);
1577 stverts[i].s = LittleLong (pinstverts[i].s);
1578 stverts[i].t = LittleLong (pinstverts[i].t);
1579 }
1580
1581 //
1582 // load triangle lists
1583 //
1584 pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
1585
1586 for (i=0 ; i<pheader->numtris ; i++)
1587 {
1588 triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
1589
1590 for (j=0 ; j<3 ; j++)
1591 {
1592 triangles[i].vertindex[j] =
1593 LittleLong (pintriangles[i].vertindex[j]);
1594 }
1595 }
1596
1597 //
1598 // load the frames
1599 //
1600 posenum = 0;
1601 pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
1602
1603 for (i=0 ; i<numframes ; i++)
1604 {
1605 aliasframetype_t frametype;
1606
1607 frametype = (aliasframetype_t) LittleLong (pframetype->type);
1608
1609 if (frametype == ALIAS_SINGLE)
1610 {
1611 pframetype = (daliasframetype_t *)
1612 Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
1613 }
1614 else
1615 {
1616 pframetype = (daliasframetype_t *)
1617 Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
1618 }
1619 }
1620
1621 pheader->numposes = posenum;
1622
1623 mod->type = mod_alias;
1624
1625 // FIXME: do this right
1626 mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
1627 mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
1628
1629 //
1630 // build the draw lists
1631 //
1632 GL_MakeAliasModelDisplayLists (mod, pheader);
1633
1634 //
1635 // move the complete, relocatable alias model to the cache
1636 //
1637 end = Hunk_LowMark ();
1638 total = end - start;
1639
1640 Cache_Alloc (&mod->cache, total, loadname);
1641 if (!mod->cache.data)
1642 return;
1643 memcpy (mod->cache.data, pheader, total);
1644
1645 Hunk_FreeToLowMark (start);
1646 }
1647
1648 //=============================================================================
1649
1650 /*
1651 =================
1652 Mod_LoadSpriteFrame
1653 =================
1654 */
Mod_LoadSpriteFrame(void * pin,mspriteframe_t ** ppframe,int framenum)1655 void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
1656 {
1657 dspriteframe_t *pinframe;
1658 mspriteframe_t *pspriteframe;
1659 int i, width, height, size, origin[2];
1660 unsigned short *ppixout;
1661 byte *ppixin;
1662 char name[64];
1663
1664 pinframe = (dspriteframe_t *)pin;
1665
1666 width = LittleLong (pinframe->width);
1667 height = LittleLong (pinframe->height);
1668 size = width * height;
1669
1670 pspriteframe = (mspriteframe_t*) Hunk_AllocName (sizeof (mspriteframe_t),loadname);
1671
1672 Q_memset (pspriteframe, 0, sizeof (mspriteframe_t));
1673
1674 *ppframe = pspriteframe;
1675
1676 pspriteframe->width = width;
1677 pspriteframe->height = height;
1678 origin[0] = LittleLong (pinframe->origin[0]);
1679 origin[1] = LittleLong (pinframe->origin[1]);
1680
1681 pspriteframe->up = origin[1];
1682 pspriteframe->down = origin[1] - height;
1683 pspriteframe->left = origin[0];
1684 pspriteframe->right = width + origin[0];
1685
1686 sprintf (name, "%s_%i", loadmodel->name, framenum);
1687 pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true);
1688
1689 return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
1690 }
1691
1692
1693 /*
1694 =================
1695 Mod_LoadSpriteGroup
1696 =================
1697 */
Mod_LoadSpriteGroup(void * pin,mspriteframe_t ** ppframe,int framenum)1698 void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum)
1699 {
1700 dspritegroup_t *pingroup;
1701 mspritegroup_t *pspritegroup;
1702 int i, numframes;
1703 dspriteinterval_t *pin_intervals;
1704 float *poutintervals;
1705 void *ptemp;
1706
1707 pingroup = (dspritegroup_t *)pin;
1708
1709 numframes = LittleLong (pingroup->numframes);
1710
1711 pspritegroup = (mspritegroup_t*) Hunk_AllocName (sizeof (mspritegroup_t) +
1712 (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
1713
1714 pspritegroup->numframes = numframes;
1715
1716 *ppframe = (mspriteframe_t *)pspritegroup;
1717
1718 pin_intervals = (dspriteinterval_t *)(pingroup + 1);
1719
1720 poutintervals = (float*) Hunk_AllocName (numframes * sizeof (float), loadname);
1721
1722 pspritegroup->intervals = poutintervals;
1723
1724 for (i=0 ; i<numframes ; i++)
1725 {
1726 *poutintervals = LittleFloat (pin_intervals->interval);
1727 if (*poutintervals <= 0.0)
1728 Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
1729
1730 poutintervals++;
1731 pin_intervals++;
1732 }
1733
1734 ptemp = (void *)pin_intervals;
1735
1736 for (i=0 ; i<numframes ; i++)
1737 {
1738 ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i);
1739 }
1740
1741 return ptemp;
1742 }
1743
1744
1745 /*
1746 =================
1747 Mod_LoadSpriteModel
1748 =================
1749 */
Mod_LoadSpriteModel(model_t * mod,void * buffer)1750 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
1751 {
1752 int i;
1753 int version;
1754 dsprite_t *pin;
1755 msprite_t *psprite;
1756 int numframes;
1757 int size;
1758 dspriteframetype_t *pframetype;
1759
1760 pin = (dsprite_t *)buffer;
1761
1762 version = LittleLong (pin->version);
1763 if (version != SPRITE_VERSION)
1764 Sys_Error ("%s has wrong version number "
1765 "(%i should be %i)", mod->name, version, SPRITE_VERSION);
1766
1767 numframes = LittleLong (pin->numframes);
1768
1769 size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames);
1770
1771 psprite = (msprite_t*) Hunk_AllocName (size, loadname);
1772
1773 mod->cache.data = psprite;
1774
1775 psprite->type = LittleLong (pin->type);
1776 psprite->maxwidth = LittleLong (pin->width);
1777 psprite->maxheight = LittleLong (pin->height);
1778 psprite->beamlength = LittleFloat (pin->beamlength);
1779 mod->synctype = (synctype_t) LittleLong (pin->synctype);
1780 psprite->numframes = numframes;
1781
1782 mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
1783 mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
1784 mod->mins[2] = -psprite->maxheight/2;
1785 mod->maxs[2] = psprite->maxheight/2;
1786
1787 //
1788 // load the frames
1789 //
1790 if (numframes < 1)
1791 Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
1792
1793 mod->numframes = numframes;
1794
1795 pframetype = (dspriteframetype_t *)(pin + 1);
1796
1797 for (i=0 ; i<numframes ; i++)
1798 {
1799 spriteframetype_t frametype;
1800
1801 frametype = (spriteframetype_t) LittleLong (pframetype->type);
1802 psprite->frames[i].type = frametype;
1803
1804 if (frametype == SPR_SINGLE)
1805 {
1806 pframetype = (dspriteframetype_t *)
1807 Mod_LoadSpriteFrame (pframetype + 1,
1808 &psprite->frames[i].frameptr, i);
1809 }
1810 else
1811 {
1812 pframetype = (dspriteframetype_t *)
1813 Mod_LoadSpriteGroup (pframetype + 1,
1814 &psprite->frames[i].frameptr, i);
1815 }
1816 }
1817
1818 mod->type = mod_sprite;
1819 }
1820
1821 //=============================================================================
1822
1823 /*
1824 ================
1825 Mod_Print
1826 ================
1827 */
Mod_Print(void)1828 void Mod_Print (void)
1829 {
1830 int i;
1831 model_t *mod;
1832
1833 Con_Printf ("Cached models:\n");
1834 for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
1835 {
1836 Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
1837 }
1838 }
1839
1840
1841