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