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