Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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. // 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.