Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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][0] + j) = LittleFloat (*(&in->vecs[0][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. {      
  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. =================
  1061. Mod_LoadSurfedges
  1062. =================
  1063. */
  1064. void 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. =================
  1084. Mod_LoadPlanes
  1085. =================
  1086. */
  1087. void 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. =================
  1122. RadiusFromBounds
  1123. =================
  1124. */
  1125. float 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. =================
  1140. Mod_LoadBrushModel
  1141. =================
  1142. */
  1143. void 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.                 Sys_Error ("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.  
  1225. ALIAS MODELS
  1226.  
  1227. ==============================================================================
  1228. */
  1229.  
  1230. /*
  1231. =================
  1232. Mod_LoadAliasFrame
  1233. =================
  1234. */
  1235. void * 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. =================
  1280. Mod_LoadAliasGroup
  1281. =================
  1282. */
  1283. void * 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. =================
  1345. Mod_LoadAliasSkin
  1346. =================
  1347. */
  1348. void * 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. =================
  1384. Mod_LoadAliasSkinGroup
  1385. =================
  1386. */
  1387. void * 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. =================
  1439. Mod_LoadAliasModel
  1440. =================
  1441. */
  1442. void 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. =================
  1666. Mod_LoadSpriteFrame
  1667. =================
  1668. */
  1669. void * 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. =================
  1723. Mod_LoadSpriteGroup
  1724. =================
  1725. */
  1726. void * 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. =================
  1775. Mod_LoadSpriteModel
  1776. =================
  1777. */
  1778. void 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. ================
  1854. Mod_Print
  1855. ================
  1856. */
  1857. void 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.  
  1875.