home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / model.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  42.2 KB  |  1,875 lines

  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. #include "r_local.h"
  27.  
  28. model_t *loadmodel;
  29. char  loadname[32]; // for hunk tags
  30.  
  31. void Mod_LoadSpriteModel (model_t *mod, void *buffer);
  32. void Mod_LoadBrushModel (model_t *mod, void *buffer);
  33. void Mod_LoadAliasModel (model_t *mod, void *buffer);
  34. model_t *Mod_LoadModel (model_t *mod, qboolean crash);
  35.  
  36. byte  mod_novis[MAX_MAP_LEAFS/8];
  37.  
  38. #define MAX_MOD_KNOWN 256
  39. model_t mod_known[MAX_MOD_KNOWN];
  40. int   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. ===============
  49. Mod_Init
  50. ===============
  51. */
  52. void Mod_Init (void)
  53. {
  54.   memset (mod_novis, 0xff, sizeof(mod_novis));
  55. }
  56.  
  57. /*
  58. ===============
  59. Mod_Extradata
  60.  
  61. Caches the data if needed
  62. ===============
  63. */
  64. void *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. ===============
  81. Mod_PointInLeaf
  82. ===============
  83. */
  84. mleaf_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. ===================
  112. Mod_DecompressVis
  113. ===================
  114. */
  115. byte *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.  
  155. byte *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. ===================
  164. Mod_ClearAll
  165. ===================
  166. */
  167. void 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. ==================
  182. Mod_FindName
  183.  
  184. ==================
  185. */
  186. model_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. ==================
  232. Mod_TouchModel
  233.  
  234. ==================
  235. */
  236. void 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. ==================
  251. Mod_LoadModel
  252.  
  253. Loads a model into the cache
  254. ==================
  255. */
  256. model_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. ==================
  324. Mod_ForName
  325.  
  326. Loads in a model for the given name
  327. ==================
  328. */
  329. model_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.  
  347. byte  *mod_base;
  348.  
  349.  
  350. /*
  351. =================
  352. Mod_LoadTextures
  353. =================
  354. */
  355. void 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. =================
  501. Mod_LoadLighting
  502. =================
  503. */
  504. void 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. =================
  518. Mod_LoadVisibility
  519. =================
  520. */
  521. void 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. =================
  535. Mod_LoadEntities
  536. =================
  537. */
  538. void 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. =================
  552. Mod_LoadVertexes
  553. =================
  554. */
  555. void 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. =================
  580. Mod_LoadSubmodels
  581. =================
  582. */
  583. void 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. =================
  616. Mod_LoadEdges
  617. =================
  618. */
  619. void 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. =================
  643. Mod_LoadTexinfo
  644. =================
  645. */
  646. void 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. ================
  709. CalcSurfaceExtents
  710.  
  711. Fills in s->texturemins[] and s->extents[]
  712. ================
  713. */
  714. void 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. =================
  763. Mod_LoadFaces
  764. =================
  765. */
  766. void 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. =================
  833. Mod_SetParent
  834. =================
  835. */
  836. void 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. =================
  847. Mod_LoadNodes
  848. =================
  849. */
  850. void 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. =================
  894. Mod_LoadLeafs
  895. =================
  896. */
  897. void 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. =================
  941. Mod_LoadClipnodes
  942. =================
  943. */
  944. void 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. =================
  993. Mod_MakeHull0
  994.  
  995. Deplicate the drawing hull structure as a clipping hull
  996. =================
  997. */
  998. void 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. =================
  1032. Mod_LoadMarksurfaces
  1033. =================
  1034. */
  1035. void Mod_LoadMarksurfaces (lump_t *l)
  1036.   int   i, j, count;
  1037.   short   *in;
  1038.   msurface_t **out;
  1039.   
  1040.   in = (void *)(mod_base + l->fileofs);
  1041.   if (l->filelen % sizeof(*in))
  1042.     Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  1043.   count = l->filelen / sizeof(*in);
  1044.   out = Hunk_AllocName ( count*sizeof(*out), loadname); 
  1045.  
  1046.   loadmodel->marksurfaces = out;
  1047.   loadmodel->nummarksurfaces = count;
  1048.  
  1049.   for ( i=0 ; i<count ; i++)
  1050.   {
  1051.     j = LittleShort(in[i]);
  1052.     if (j >= loadmodel->numsurfaces)
  1053.       Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
  1054.     out[i] = loadmodel->surfaces + j;
  1055.   }
  1056. }
  1057.  
  1058. /*
  1059. =================
  1060. Mod_LoadSurfedges
  1061. =================
  1062. */
  1063. void Mod_LoadSurfedges (lump_t *l)
  1064.   int   i, count;
  1065.   int   *in, *out;
  1066.   
  1067.   in = (void *)(mod_base + l->fileofs);
  1068.   if (l->filelen % sizeof(*in))
  1069.     Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  1070.   count = l->filelen / sizeof(*in);
  1071.   out = Hunk_AllocName ( count*sizeof(*out), loadname); 
  1072.  
  1073.   loadmodel->surfedges = out;
  1074.   loadmodel->numsurfedges = count;
  1075.  
  1076.   for ( i=0 ; i<count ; i++)
  1077.     out[i] = LittleLong (in[i]);
  1078. }
  1079.  
  1080. /*
  1081. =================
  1082. Mod_LoadPlanes
  1083. =================
  1084. */
  1085. void Mod_LoadPlanes (lump_t *l)
  1086. {
  1087.   int     i, j;
  1088.   mplane_t  *out;
  1089.   dplane_t  *in;
  1090.   int     count;
  1091.   int     bits;
  1092.   
  1093.   in = (void *)(mod_base + l->fileofs);
  1094.   if (l->filelen % sizeof(*in))
  1095.     Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  1096.   count = l->filelen / sizeof(*in);
  1097.   out = Hunk_AllocName ( count*2*sizeof(*out), loadname); 
  1098.   
  1099.   loadmodel->planes = out;
  1100.   loadmodel->numplanes = count;
  1101.  
  1102.   for ( i=0 ; i<count ; i++, in++, out++)
  1103.   {
  1104.     bits = 0;
  1105.     for (j=0 ; j<3 ; j++)
  1106.     {
  1107.       out->normal[j] = LittleFloat (in->normal[j]);
  1108.       if (out->normal[j] < 0)
  1109.         bits |= 1<<j;
  1110.     }
  1111.  
  1112.     out->dist = LittleFloat (in->dist);
  1113.     out->type = LittleLong (in->type);
  1114.     out->signbits = bits;
  1115.   }
  1116. }
  1117.  
  1118. /*
  1119. =================
  1120. RadiusFromBounds
  1121. =================
  1122. */
  1123. float RadiusFromBounds (vec3_t mins, vec3_t maxs)
  1124. {
  1125.   int   i;
  1126.   vec3_t  corner;
  1127.  
  1128.   for (i=0 ; i<3 ; i++)
  1129.   {
  1130.     corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
  1131.   }
  1132.  
  1133.   return Length (corner);
  1134. }
  1135.  
  1136. /*
  1137. =================
  1138. Mod_LoadBrushModel
  1139. =================
  1140. */
  1141. void Mod_LoadBrushModel (model_t *mod, void *buffer)
  1142. {
  1143.   int     i, j;
  1144.   dheader_t *header;
  1145.   dmodel_t  *bm;
  1146.   
  1147.   loadmodel->type = mod_brush;
  1148.   
  1149.   header = (dheader_t *)buffer;
  1150.  
  1151.   i = LittleLong (header->version);
  1152.   if (i != BSPVERSION)
  1153.     Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
  1154.  
  1155. // swap all the lumps
  1156.   mod_base = (byte *)header;
  1157.  
  1158.   for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
  1159.     ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
  1160.  
  1161. // load into heap
  1162.   
  1163.   Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
  1164.   Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
  1165.   Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
  1166.   Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
  1167.   Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
  1168.   Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
  1169.   Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
  1170.   Mod_LoadFaces (&header->lumps[LUMP_FACES]);
  1171.   Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
  1172.   Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
  1173.   Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
  1174.   Mod_LoadNodes (&header->lumps[LUMP_NODES]);
  1175.   Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
  1176.   Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
  1177.   Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
  1178.  
  1179.   Mod_MakeHull0 ();
  1180.   
  1181.   mod->numframes = 2;   // regular and alternate animation
  1182.   mod->flags = 0;
  1183.   
  1184. //
  1185. // set up the submodels (FIXME: this is confusing)
  1186. //
  1187.   for (i=0 ; i<mod->numsubmodels ; i++)
  1188.   {
  1189.     bm = &mod->submodels[i];
  1190.  
  1191.     mod->hulls[0].firstclipnode = bm->headnode[0];
  1192.     for (j=1 ; j<MAX_MAP_HULLS ; j++)
  1193.     {
  1194.       mod->hulls[j].firstclipnode = bm->headnode[j];
  1195.       mod->hulls[j].lastclipnode = mod->numclipnodes-1;
  1196.     }
  1197.     
  1198.     mod->firstmodelsurface = bm->firstface;
  1199.     mod->nummodelsurfaces = bm->numfaces;
  1200.     
  1201.     VectorCopy (bm->maxs, mod->maxs);
  1202.     VectorCopy (bm->mins, mod->mins);
  1203.     mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
  1204.     
  1205.     mod->numleafs = bm->visleafs;
  1206.  
  1207.     if (i < mod->numsubmodels-1)
  1208.     { // duplicate the basic information
  1209.       char  name[10];
  1210.  
  1211.       sprintf (name, "*%i", i+1);
  1212.       loadmodel = Mod_FindName (name);
  1213.       *loadmodel = *mod;
  1214.       strcpy (loadmodel->name, name);
  1215.       mod = loadmodel;
  1216.     }
  1217.   }
  1218. }
  1219.  
  1220. /*
  1221. ==============================================================================
  1222.  
  1223. ALIAS MODELS
  1224.  
  1225. ==============================================================================
  1226. */
  1227.  
  1228. /*
  1229. =================
  1230. Mod_LoadAliasFrame
  1231. =================
  1232. */
  1233. void * Mod_LoadAliasFrame (void * pin, int *pframeindex, int numv,
  1234.   trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
  1235. {
  1236.   trivertx_t    *pframe, *pinframe;
  1237.   int       i, j;
  1238.   daliasframe_t *pdaliasframe;
  1239.  
  1240.   pdaliasframe = (daliasframe_t *)pin;
  1241.  
  1242.   strcpy (name, pdaliasframe->name);
  1243.  
  1244.   for (i=0 ; i<3 ; i++)
  1245.   {
  1246.   // these are byte values, so we don't have to worry about
  1247.   // endianness
  1248.     pbboxmin->v[i] = pdaliasframe->bboxmin.v[i];
  1249.     pbboxmax->v[i] = pdaliasframe->bboxmax.v[i];
  1250.   }
  1251.  
  1252.   pinframe = (trivertx_t *)(pdaliasframe + 1);
  1253.   pframe = Hunk_AllocName (numv * sizeof(*pframe), loadname);
  1254.  
  1255.   *pframeindex = (byte *)pframe - (byte *)pheader;
  1256.  
  1257.   for (j=0 ; j<numv ; j++)
  1258.   {
  1259.     int   k;
  1260.  
  1261.   // these are all byte values, so no need to deal with endianness
  1262.     pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
  1263.  
  1264.     for (k=0 ; k<3 ; k++)
  1265.     {
  1266.       pframe[j].v[k] = pinframe[j].v[k];
  1267.     }
  1268.   }
  1269.  
  1270.   pinframe += numv;
  1271.  
  1272.   return (void *)pinframe;
  1273. }
  1274.  
  1275.  
  1276. /*
  1277. =================
  1278. Mod_LoadAliasGroup
  1279. =================
  1280. */
  1281. void * Mod_LoadAliasGroup (void * pin, int *pframeindex, int numv,
  1282.   trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
  1283. {
  1284.   daliasgroup_t   *pingroup;
  1285.   maliasgroup_t   *paliasgroup;
  1286.   int         i, numframes;
  1287.   daliasinterval_t  *pin_intervals;
  1288.   float       *poutintervals;
  1289.   void        *ptemp;
  1290.   
  1291.   pingroup = (daliasgroup_t *)pin;
  1292.  
  1293.   numframes = LittleLong (pingroup->numframes);
  1294.  
  1295.   paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) +
  1296.       (numframes - 1) * sizeof (paliasgroup->frames[0]), loadname);
  1297.  
  1298.   paliasgroup->numframes = numframes;
  1299.  
  1300.   for (i=0 ; i<3 ; i++)
  1301.   {
  1302.   // these are byte values, so we don't have to worry about endianness
  1303.     pbboxmin->v[i] = pingroup->bboxmin.v[i];
  1304.     pbboxmax->v[i] = pingroup->bboxmax.v[i];
  1305.   }
  1306.  
  1307.   *pframeindex = (byte *)paliasgroup - (byte *)pheader;
  1308.  
  1309.   pin_intervals = (daliasinterval_t *)(pingroup + 1);
  1310.  
  1311.   poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
  1312.  
  1313.   paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
  1314.  
  1315.   for (i=0 ; i<numframes ; i++)
  1316.   {
  1317.     *poutintervals = LittleFloat (pin_intervals->interval);
  1318.     if (*poutintervals <= 0.0)
  1319.       Sys_Error ("Mod_LoadAliasGroup: interval<=0");
  1320.  
  1321.     poutintervals++;
  1322.     pin_intervals++;
  1323.   }
  1324.  
  1325.   ptemp = (void *)pin_intervals;
  1326.  
  1327.   for (i=0 ; i<numframes ; i++)
  1328.   {
  1329.     ptemp = Mod_LoadAliasFrame (ptemp,
  1330.                   &paliasgroup->frames[i].frame,
  1331.                   numv,
  1332.                   &paliasgroup->frames[i].bboxmin,
  1333.                   &paliasgroup->frames[i].bboxmax,
  1334.                   pheader, name);
  1335.   }
  1336.  
  1337.   return ptemp;
  1338. }
  1339.  
  1340.  
  1341. /*
  1342. =================
  1343. Mod_LoadAliasSkin
  1344. =================
  1345. */
  1346. void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinsize,
  1347.   aliashdr_t *pheader)
  1348. {
  1349.   int   i;
  1350.   byte  *pskin, *pinskin;
  1351.   unsigned short  *pusskin;
  1352.  
  1353.   pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname);
  1354.   pinskin = (byte *)pin;
  1355.   *pskinindex = (byte *)pskin - (byte *)pheader;
  1356.  
  1357.   if (r_pixbytes == 1)
  1358.   {
  1359.     Q_memcpy (pskin, pinskin, skinsize);
  1360.   }
  1361.   else if (r_pixbytes == 2)
  1362.   {
  1363.     pusskin = (unsigned short *)pskin;
  1364.  
  1365.     for (i=0 ; i<skinsize ; i++)
  1366.       pusskin[i] = d_8to16table[pinskin[i]];
  1367.   }
  1368.   else
  1369.   {
  1370.     Sys_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: %d\n",
  1371.          r_pixbytes);
  1372.   }
  1373.  
  1374.   pinskin += skinsize;
  1375.  
  1376.   return ((void *)pinskin);
  1377. }
  1378.  
  1379.  
  1380. /*
  1381. =================
  1382. Mod_LoadAliasSkinGroup
  1383. =================
  1384. */
  1385. void * Mod_LoadAliasSkinGroup (void * pin, int *pskinindex, int skinsize,
  1386.   aliashdr_t *pheader)
  1387. {
  1388.   daliasskingroup_t   *pinskingroup;
  1389.   maliasskingroup_t   *paliasskingroup;
  1390.   int           i, numskins;
  1391.   daliasskininterval_t  *pinskinintervals;
  1392.   float         *poutskinintervals;
  1393.   void          *ptemp;
  1394.  
  1395.   pinskingroup = (daliasskingroup_t *)pin;
  1396.  
  1397.   numskins = LittleLong (pinskingroup->numskins);
  1398.  
  1399.   paliasskingroup = Hunk_AllocName (sizeof (maliasskingroup_t) +
  1400.       (numskins - 1) * sizeof (paliasskingroup->skindescs[0]),
  1401.       loadname);
  1402.  
  1403.   paliasskingroup->numskins = numskins;
  1404.  
  1405.   *pskinindex = (byte *)paliasskingroup - (byte *)pheader;
  1406.  
  1407.   pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
  1408.  
  1409.   poutskinintervals = Hunk_AllocName (numskins * sizeof (float),loadname);
  1410.  
  1411.   paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
  1412.  
  1413.   for (i=0 ; i<numskins ; i++)
  1414.   {
  1415.     *poutskinintervals = LittleFloat (pinskinintervals->interval);
  1416.     if (*poutskinintervals <= 0)
  1417.       Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0");
  1418.  
  1419.     poutskinintervals++;
  1420.     pinskinintervals++;
  1421.   }
  1422.  
  1423.   ptemp = (void *)pinskinintervals;
  1424.  
  1425.   for (i=0 ; i<numskins ; i++)
  1426.   {
  1427.     ptemp = Mod_LoadAliasSkin (ptemp,
  1428.         &paliasskingroup->skindescs[i].skin, skinsize, pheader);
  1429.   }
  1430.  
  1431.   return ptemp;
  1432. }
  1433.  
  1434.  
  1435. /*
  1436. =================
  1437. Mod_LoadAliasModel
  1438. =================
  1439. */
  1440. void Mod_LoadAliasModel (model_t *mod, void *buffer)
  1441. {
  1442.   int         i;
  1443.   mdl_t       *pmodel, *pinmodel;
  1444.   stvert_t      *pstverts, *pinstverts;
  1445.   aliashdr_t      *pheader;
  1446.   mtriangle_t     *ptri;
  1447.   dtriangle_t     *pintriangles;
  1448.   int         version, numframes, numskins;
  1449.   int         size;
  1450.   daliasframetype_t *pframetype;
  1451.   daliasskintype_t  *pskintype;
  1452.   maliasskindesc_t  *pskindesc;
  1453.   int         skinsize;
  1454.   int         start, end, total;
  1455.   
  1456.   start = Hunk_LowMark ();
  1457.  
  1458.   pinmodel = (mdl_t *)buffer;
  1459.  
  1460.   version = LittleLong (pinmodel->version);
  1461.   if (version != ALIAS_VERSION)
  1462.     Sys_Error ("%s has wrong version number (%i should be %i)",
  1463.          mod->name, version, ALIAS_VERSION);
  1464.  
  1465. //
  1466. // allocate space for a working header, plus all the data except the frames,
  1467. // skin and group info
  1468. //
  1469.   size =  sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) *
  1470.        sizeof (pheader->frames[0]) +
  1471.       sizeof (mdl_t) +
  1472.       LittleLong (pinmodel->numverts) * sizeof (stvert_t) +
  1473.       LittleLong (pinmodel->numtris) * sizeof (mtriangle_t);
  1474.  
  1475.   pheader = Hunk_AllocName (size, loadname);
  1476.   pmodel = (mdl_t *) ((byte *)&pheader[1] +
  1477.       (LittleLong (pinmodel->numframes) - 1) *
  1478.        sizeof (pheader->frames[0]));
  1479.   
  1480. //  mod->cache.data = pheader;
  1481.   mod->flags = LittleLong (pinmodel->flags);
  1482.  
  1483. //
  1484. // endian-adjust and copy the data, starting with the alias model header
  1485. //
  1486.   pmodel->boundingradius = LittleFloat (pinmodel->boundingradius);
  1487.   pmodel->numskins = LittleLong (pinmodel->numskins);
  1488.   pmodel->skinwidth = LittleLong (pinmodel->skinwidth);
  1489.   pmodel->skinheight = LittleLong (pinmodel->skinheight);
  1490.  
  1491.   if (pmodel->skinheight > MAX_LBM_HEIGHT)
  1492.     Sys_Error ("model %s has a skin taller than %d", mod->name,
  1493.            MAX_LBM_HEIGHT);
  1494.  
  1495.   pmodel->numverts = LittleLong (pinmodel->numverts);
  1496.  
  1497.   if (pmodel->numverts <= 0)
  1498.     Sys_Error ("model %s has no vertices", mod->name);
  1499.  
  1500.   if (pmodel->numverts > MAXALIASVERTS)
  1501.     Sys_Error ("model %s has too many vertices", mod->name);
  1502.  
  1503.   pmodel->numtris = LittleLong (pinmodel->numtris);
  1504.  
  1505.   if (pmodel->numtris <= 0)
  1506.     Sys_Error ("model %s has no triangles", mod->name);
  1507.  
  1508.   pmodel->numframes = LittleLong (pinmodel->numframes);
  1509.   pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
  1510.   mod->synctype = LittleLong (pinmodel->synctype);
  1511.   mod->numframes = pmodel->numframes;
  1512.  
  1513.   for (i=0 ; i<3 ; i++)
  1514.   {
  1515.     pmodel->scale[i] = LittleFloat (pinmodel->scale[i]);
  1516.     pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
  1517.     pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
  1518.   }
  1519.  
  1520.   numskins = pmodel->numskins;
  1521.   numframes = pmodel->numframes;
  1522.  
  1523.   if (pmodel->skinwidth & 0x03)
  1524.     Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4");
  1525.  
  1526.   pheader->model = (byte *)pmodel - (byte *)pheader;
  1527.  
  1528. //
  1529. // load the skins
  1530. //
  1531.   skinsize = pmodel->skinheight * pmodel->skinwidth;
  1532.  
  1533.   if (numskins < 1)
  1534.     Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
  1535.  
  1536.   pskintype = (daliasskintype_t *)&pinmodel[1];
  1537.  
  1538.   pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t),
  1539.                 loadname);
  1540.  
  1541.   pheader->skindesc = (byte *)pskindesc - (byte *)pheader;
  1542.  
  1543.   for (i=0 ; i<numskins ; i++)
  1544.   {
  1545.     aliasskintype_t skintype;
  1546.  
  1547.     skintype = LittleLong (pskintype->type);
  1548.     pskindesc[i].type = skintype;
  1549.  
  1550.     if (skintype == ALIAS_SKIN_SINGLE)
  1551.     {
  1552.       pskintype = (daliasskintype_t *)
  1553.           Mod_LoadAliasSkin (pskintype + 1,
  1554.                      &pskindesc[i].skin,
  1555.                      skinsize, pheader);
  1556.     }
  1557.     else
  1558.     {
  1559.       pskintype = (daliasskintype_t *)
  1560.           Mod_LoadAliasSkinGroup (pskintype + 1,
  1561.                       &pskindesc[i].skin,
  1562.                       skinsize, pheader);
  1563.     }
  1564.   }
  1565.  
  1566. //
  1567. // set base s and t vertices
  1568. //
  1569.   pstverts = (stvert_t *)&pmodel[1];
  1570.   pinstverts = (stvert_t *)pskintype;
  1571.  
  1572.   pheader->stverts = (byte *)pstverts - (byte *)pheader;
  1573.  
  1574.   for (i=0 ; i<pmodel->numverts ; i++)
  1575.   {
  1576.     pstverts[i].onseam = LittleLong (pinstverts[i].onseam);
  1577.   // put s and t in 16.16 format
  1578.     pstverts[i].s = LittleLong (pinstverts[i].s) << 16;
  1579.     pstverts[i].t = LittleLong (pinstverts[i].t) << 16;
  1580.   }
  1581.  
  1582. //
  1583. // set up the triangles
  1584. //
  1585.   ptri = (mtriangle_t *)&pstverts[pmodel->numverts];
  1586.   pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts];
  1587.  
  1588.   pheader->triangles = (byte *)ptri - (byte *)pheader;
  1589.  
  1590.   for (i=0 ; i<pmodel->numtris ; i++)
  1591.   {
  1592.     int   j;
  1593.  
  1594.     ptri[i].facesfront = LittleLong (pintriangles[i].facesfront);
  1595.  
  1596.     for (j=0 ; j<3 ; j++)
  1597.     {
  1598.       ptri[i].vertindex[j] =
  1599.           LittleLong (pintriangles[i].vertindex[j]);
  1600.     }
  1601.   }
  1602.  
  1603. //
  1604. // load the frames
  1605. //
  1606.   if (numframes < 1)
  1607.     Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
  1608.  
  1609.   pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
  1610.  
  1611.   for (i=0 ; i<numframes ; i++)
  1612.   {
  1613.     aliasframetype_t  frametype;
  1614.  
  1615.     frametype = LittleLong (pframetype->type);
  1616.     pheader->frames[i].type = frametype;
  1617.  
  1618.     if (frametype == ALIAS_SINGLE)
  1619.     {
  1620.       pframetype = (daliasframetype_t *)
  1621.           Mod_LoadAliasFrame (pframetype + 1,
  1622.                     &pheader->frames[i].frame,
  1623.                     pmodel->numverts,
  1624.                     &pheader->frames[i].bboxmin,
  1625.                     &pheader->frames[i].bboxmax,
  1626.                     pheader, pheader->frames[i].name);
  1627.     }
  1628.     else
  1629.     {
  1630.       pframetype = (daliasframetype_t *)
  1631.           Mod_LoadAliasGroup (pframetype + 1,
  1632.                     &pheader->frames[i].frame,
  1633.                     pmodel->numverts,
  1634.                     &pheader->frames[i].bboxmin,
  1635.                     &pheader->frames[i].bboxmax,
  1636.                     pheader, pheader->frames[i].name);
  1637.     }
  1638.   }
  1639.  
  1640.   mod->type = mod_alias;
  1641.  
  1642. // FIXME: do this right
  1643.   mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
  1644.   mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
  1645.  
  1646. //
  1647. // move the complete, relocatable alias model to the cache
  1648. //  
  1649.   end = Hunk_LowMark ();
  1650.   total = end - start;
  1651.   
  1652.   Cache_Alloc (&mod->cache, total, loadname);
  1653.   if (!mod->cache.data)
  1654.     return;
  1655.   memcpy (mod->cache.data, pheader, total);
  1656.  
  1657.   Hunk_FreeToLowMark (start);
  1658. }
  1659.  
  1660. //=============================================================================
  1661.  
  1662. /*
  1663. =================
  1664. Mod_LoadSpriteFrame
  1665. =================
  1666. */
  1667. void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe)
  1668. {
  1669.   dspriteframe_t    *pinframe;
  1670.   mspriteframe_t    *pspriteframe;
  1671.   int         i, width, height, size, origin[2];
  1672.   unsigned short    *ppixout;
  1673.   byte        *ppixin;
  1674.  
  1675.   pinframe = (dspriteframe_t *)pin;
  1676.  
  1677.   width = LittleLong (pinframe->width);
  1678.   height = LittleLong (pinframe->height);
  1679.   size = width * height;
  1680.  
  1681.   pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes,
  1682.                    loadname);
  1683.  
  1684.   Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size);
  1685.   *ppframe = pspriteframe;
  1686.  
  1687.   pspriteframe->width = width;
  1688.   pspriteframe->height = height;
  1689.   origin[0] = LittleLong (pinframe->origin[0]);
  1690.   origin[1] = LittleLong (pinframe->origin[1]);
  1691.  
  1692.   pspriteframe->up = origin[1];
  1693.   pspriteframe->down = origin[1] - height;
  1694.   pspriteframe->left = origin[0];
  1695.   pspriteframe->right = width + origin[0];
  1696.  
  1697.   if (r_pixbytes == 1)
  1698.   {
  1699.     Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size);
  1700.   }
  1701.   else if (r_pixbytes == 2)
  1702.   {
  1703.     ppixin = (byte *)(pinframe + 1);
  1704.     ppixout = (unsigned short *)&pspriteframe->pixels[0];
  1705.  
  1706.     for (i=0 ; i<size ; i++)
  1707.       ppixout[i] = d_8to16table[ppixin[i]];
  1708.   }
  1709.   else
  1710.   {
  1711.     Sys_Error ("Mod_LoadSpriteFrame: driver set invalid r_pixbytes: %d\n",
  1712.          r_pixbytes);
  1713.   }
  1714.  
  1715.   return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
  1716. }
  1717.  
  1718.  
  1719. /*
  1720. =================
  1721. Mod_LoadSpriteGroup
  1722. =================
  1723. */
  1724. void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe)
  1725. {
  1726.   dspritegroup_t    *pingroup;
  1727.   mspritegroup_t    *pspritegroup;
  1728.   int         i, numframes;
  1729.   dspriteinterval_t *pin_intervals;
  1730.   float       *poutintervals;
  1731.   void        *ptemp;
  1732.  
  1733.   pingroup = (dspritegroup_t *)pin;
  1734.  
  1735.   numframes = LittleLong (pingroup->numframes);
  1736.  
  1737.   pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
  1738.         (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
  1739.  
  1740.   pspritegroup->numframes = numframes;
  1741.  
  1742.   *ppframe = (mspriteframe_t *)pspritegroup;
  1743.  
  1744.   pin_intervals = (dspriteinterval_t *)(pingroup + 1);
  1745.  
  1746.   poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
  1747.  
  1748.   pspritegroup->intervals = poutintervals;
  1749.  
  1750.   for (i=0 ; i<numframes ; i++)
  1751.   {
  1752.     *poutintervals = LittleFloat (pin_intervals->interval);
  1753.     if (*poutintervals <= 0.0)
  1754.       Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
  1755.  
  1756.     poutintervals++;
  1757.     pin_intervals++;
  1758.   }
  1759.  
  1760.   ptemp = (void *)pin_intervals;
  1761.  
  1762.   for (i=0 ; i<numframes ; i++)
  1763.   {
  1764.     ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i]);
  1765.   }
  1766.  
  1767.   return ptemp;
  1768. }
  1769.  
  1770.  
  1771. /*
  1772. =================
  1773. Mod_LoadSpriteModel
  1774. =================
  1775. */
  1776. void Mod_LoadSpriteModel (model_t *mod, void *buffer)
  1777. {
  1778.   int         i;
  1779.   int         version;
  1780.   dsprite_t     *pin;
  1781.   msprite_t     *psprite;
  1782.   int         numframes;
  1783.   int         size;
  1784.   dspriteframetype_t  *pframetype;
  1785.   
  1786.   pin = (dsprite_t *)buffer;
  1787.  
  1788.   version = LittleLong (pin->version);
  1789.   if (version != SPRITE_VERSION)
  1790.     Sys_Error ("%s has wrong version number "
  1791.          "(%i should be %i)", mod->name, version, SPRITE_VERSION);
  1792.  
  1793.   numframes = LittleLong (pin->numframes);
  1794.  
  1795.   size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames);
  1796.  
  1797.   psprite = Hunk_AllocName (size, loadname);
  1798.  
  1799.   mod->cache.data = psprite;
  1800.  
  1801.   psprite->type = LittleLong (pin->type);
  1802.   psprite->maxwidth = LittleLong (pin->width);
  1803.   psprite->maxheight = LittleLong (pin->height);
  1804.   psprite->beamlength = LittleFloat (pin->beamlength);
  1805.   mod->synctype = LittleLong (pin->synctype);
  1806.   psprite->numframes = numframes;
  1807.  
  1808.   mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
  1809.   mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
  1810.   mod->mins[2] = -psprite->maxheight/2;
  1811.   mod->maxs[2] = psprite->maxheight/2;
  1812.   
  1813. //
  1814. // load the frames
  1815. //
  1816.   if (numframes < 1)
  1817.     Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
  1818.  
  1819.   mod->numframes = numframes;
  1820.   mod->flags = 0;
  1821.  
  1822.   pframetype = (dspriteframetype_t *)(pin + 1);
  1823.  
  1824.   for (i=0 ; i<numframes ; i++)
  1825.   {
  1826.     spriteframetype_t frametype;
  1827.  
  1828.     frametype = LittleLong (pframetype->type);
  1829.     psprite->frames[i].type = frametype;
  1830.  
  1831.     if (frametype == SPR_SINGLE)
  1832.     {
  1833.       pframetype = (dspriteframetype_t *)
  1834.           Mod_LoadSpriteFrame (pframetype + 1,
  1835.                      &psprite->frames[i].frameptr);
  1836.     }
  1837.     else
  1838.     {
  1839.       pframetype = (dspriteframetype_t *)
  1840.           Mod_LoadSpriteGroup (pframetype + 1,
  1841.                      &psprite->frames[i].frameptr);
  1842.     }
  1843.   }
  1844.  
  1845.   mod->type = mod_sprite;
  1846. }
  1847.  
  1848. //=============================================================================
  1849.  
  1850. /*
  1851. ================
  1852. Mod_Print
  1853. ================
  1854. */
  1855. void Mod_Print (void)
  1856. {
  1857.   int   i;
  1858.   model_t *mod;
  1859.  
  1860.   Con_Printf ("Cached models:\n");
  1861.   for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
  1862.   {
  1863.     Con_Printf ("%8p : %s",mod->cache.data, mod->name);
  1864.     if (mod->needload & NL_UNREFERENCED)
  1865.       Con_Printf (" (!R)");
  1866.     if (mod->needload & NL_NEEDS_LOADED)
  1867.       Con_Printf (" (!P)");
  1868.     Con_Printf ("\n");
  1869.   }
  1870. }
  1871.  
  1872.  
  1873.