home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / r_efrag.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  5KB  |  277 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. // r_efrag.c
  21.  
  22. #include "quakedef.h"
  23. #include "r_local.h"
  24.  
  25. mnode_t *r_pefragtopnode;
  26.  
  27.  
  28. //===========================================================================
  29.  
  30. /*
  31. ===============================================================================
  32.  
  33.           ENTITY FRAGMENT FUNCTIONS
  34.  
  35. ===============================================================================
  36. */
  37.  
  38. efrag_t   **lastlink;
  39.  
  40. vec3_t    r_emins, r_emaxs;
  41.  
  42. entity_t  *r_addent;
  43.  
  44.  
  45. /*
  46. ================
  47. R_RemoveEfrags
  48.  
  49. Call when removing an object from the world or moving it to another position
  50. ================
  51. */
  52. void R_RemoveEfrags (entity_t *ent)
  53. {
  54.   efrag_t   *ef, *old, *walk, **prev;
  55.   
  56.   ef = ent->efrag;
  57.   
  58.   while (ef)
  59.   {
  60.     prev = &ef->leaf->efrags;
  61.     while (1)
  62.     {
  63.       walk = *prev;
  64.       if (!walk)
  65.         break;
  66.       if (walk == ef)
  67.       { // remove this fragment
  68.         *prev = ef->leafnext;
  69.         break;
  70.       }
  71.       else
  72.         prev = &walk->leafnext;
  73.     }
  74.         
  75.     old = ef;
  76.     ef = ef->entnext;
  77.     
  78.   // put it on the free list
  79.     old->entnext = cl.free_efrags;
  80.     cl.free_efrags = old;
  81.   }
  82.   
  83.   ent->efrag = NULL; 
  84. }
  85.  
  86. /*
  87. ===================
  88. R_SplitEntityOnNode
  89. ===================
  90. */
  91. void R_SplitEntityOnNode (mnode_t *node)
  92. {
  93.   efrag_t   *ef;
  94.   mplane_t  *splitplane;
  95.   mleaf_t   *leaf;
  96.   int     sides;
  97.   
  98.   if (node->contents == CONTENTS_SOLID)
  99.   {
  100.     return;
  101.   }
  102.   
  103. // add an efrag if the node is a leaf
  104.  
  105.   if ( node->contents < 0)
  106.   {
  107.     if (!r_pefragtopnode)
  108.       r_pefragtopnode = node;
  109.  
  110.     leaf = (mleaf_t *)node;
  111.  
  112. // grab an efrag off the free list
  113.     ef = cl.free_efrags;
  114.     if (!ef)
  115.     {
  116.       Con_Printf ("Too many efrags!\n");
  117.       return;   // no free fragments...
  118.     }
  119.     cl.free_efrags = cl.free_efrags->entnext;
  120.  
  121.     ef->entity = r_addent;
  122.     
  123. // add the entity link  
  124.     *lastlink = ef;
  125.     lastlink = &ef->entnext;
  126.     ef->entnext = NULL;
  127.     
  128. // set the leaf links
  129.     ef->leaf = leaf;
  130.     ef->leafnext = leaf->efrags;
  131.     leaf->efrags = ef;
  132.       
  133.     return;
  134.   }
  135.   
  136. // NODE_MIXED
  137.  
  138.   splitplane = node->plane;
  139.   sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
  140.   
  141.   if (sides == 3)
  142.   {
  143.   // split on this plane
  144.   // if this is the first splitter of this bmodel, remember it
  145.     if (!r_pefragtopnode)
  146.       r_pefragtopnode = node;
  147.   }
  148.   
  149. // recurse down the contacted sides
  150.   if (sides & 1)
  151.     R_SplitEntityOnNode (node->children[0]);
  152.     
  153.   if (sides & 2)
  154.     R_SplitEntityOnNode (node->children[1]);
  155. }
  156.  
  157.  
  158. /*
  159. ===================
  160. R_SplitEntityOnNode2
  161. ===================
  162. */
  163. void R_SplitEntityOnNode2 (mnode_t *node)
  164. {
  165.   mplane_t  *splitplane;
  166.   int     sides;
  167.  
  168.   if (node->visframe != r_visframecount)
  169.     return;
  170.   
  171.   if (node->contents < 0)
  172.   {
  173.     if (node->contents != CONTENTS_SOLID)
  174.       r_pefragtopnode = node; // we've reached a non-solid leaf, so it's
  175.                   //  visible and not BSP clipped
  176.     return;
  177.   }
  178.   
  179.   splitplane = node->plane;
  180.   sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
  181.   
  182.   if (sides == 3)
  183.   {
  184.   // remember first splitter
  185.     r_pefragtopnode = node;
  186.     return;
  187.   }
  188.   
  189. // not split yet; recurse down the contacted side
  190.   if (sides & 1)
  191.     R_SplitEntityOnNode2 (node->children[0]);
  192.   else
  193.     R_SplitEntityOnNode2 (node->children[1]);
  194. }
  195.  
  196.  
  197. /*
  198. ===========
  199. R_AddEfrags
  200. ===========
  201. */
  202. void R_AddEfrags (entity_t *ent)
  203. {
  204.   model_t   *entmodel;
  205.   int     i;
  206.     
  207.   if (!ent->model)
  208.     return;
  209.  
  210.   if (ent == cl_entities)
  211.     return;   // never add the world
  212.  
  213.   r_addent = ent;
  214.       
  215.   lastlink = &ent->efrag;
  216.   r_pefragtopnode = NULL;
  217.   
  218.   entmodel = ent->model;
  219.  
  220.   for (i=0 ; i<3 ; i++)
  221.   {
  222.     r_emins[i] = ent->origin[i] + entmodel->mins[i];
  223.     r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
  224.   }
  225.  
  226.   R_SplitEntityOnNode (cl.worldmodel->nodes);
  227.  
  228.   ent->topnode = r_pefragtopnode;
  229. }
  230.  
  231.  
  232. /*
  233. ================
  234. R_StoreEfrags
  235.  
  236. // FIXME: a lot of this goes away with edge-based
  237. ================
  238. */
  239. void R_StoreEfrags (efrag_t **ppefrag)
  240. {
  241.   entity_t  *pent;
  242.   model_t   *clmodel;
  243.   efrag_t   *pefrag;
  244.  
  245.  
  246.   while ((pefrag = *ppefrag) != NULL)
  247.   {
  248.     pent = pefrag->entity;
  249.     clmodel = pent->model;
  250.  
  251.     switch (clmodel->type)
  252.     {
  253.     case mod_alias:
  254.     case mod_brush:
  255.     case mod_sprite:
  256.       pent = pefrag->entity;
  257.  
  258.       if ((pent->visframe != r_framecount) &&
  259.         (cl_numvisedicts < MAX_VISEDICTS))
  260.       {
  261.         cl_visedicts[cl_numvisedicts++] = pent;
  262.  
  263.       // mark that we've recorded this entity for this frame
  264.         pent->visframe = r_framecount;
  265.       }
  266.  
  267.       ppefrag = &pefrag->leafnext;
  268.       break;
  269.  
  270.     default:  
  271.       Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
  272.     }
  273.   }
  274. }
  275.  
  276.  
  277.