r_efrag.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // r_efrag.c
  16. #include "quakedef.h"
  17. #include "r_local.h"
  18. mnode_t *r_pefragtopnode;
  19. //===========================================================================
  20. /*
  21. ===============================================================================
  22. ENTITY FRAGMENT FUNCTIONS
  23. ===============================================================================
  24. */
  25. efrag_t **lastlink;
  26. vec3_t r_emins, r_emaxs;
  27. entity_t *r_addent;
  28. /*
  29. ================
  30. R_RemoveEfrags
  31. Call when removing an object from the world or moving it to another position
  32. ================
  33. */
  34. void R_RemoveEfrags (entity_t *ent)
  35. {
  36. efrag_t *ef, *old, *walk, **prev;
  37. ef = ent->efrag;
  38. while (ef)
  39. {
  40. prev = &ef->leaf->efrags;
  41. while (1)
  42. {
  43. walk = *prev;
  44. if (!walk)
  45. break;
  46. if (walk == ef)
  47. { // remove this fragment
  48. *prev = ef->leafnext;
  49. break;
  50. }
  51. else
  52. prev = &walk->leafnext;
  53. }
  54. old = ef;
  55. ef = ef->entnext;
  56. // put it on the free list
  57. old->entnext = cl.free_efrags;
  58. cl.free_efrags = old;
  59. }
  60. ent->efrag = NULL;
  61. }
  62. /*
  63. ===================
  64. R_SplitEntityOnNode
  65. ===================
  66. */
  67. void R_SplitEntityOnNode (mnode_t *node)
  68. {
  69. efrag_t *ef;
  70. mplane_t *splitplane;
  71. mleaf_t *leaf;
  72. int sides;
  73. if (node->contents == CONTENTS_SOLID)
  74. {
  75. return;
  76. }
  77. // add an efrag if the node is a leaf
  78. if ( node->contents < 0)
  79. {
  80. if (!r_pefragtopnode)
  81. r_pefragtopnode = node;
  82. leaf = (mleaf_t *)node;
  83. // grab an efrag off the free list
  84. ef = cl.free_efrags;
  85. if (!ef)
  86. {
  87. Con_Printf ("Too many efrags!\n");
  88. return; // no free fragments...
  89. }
  90. cl.free_efrags = cl.free_efrags->entnext;
  91. ef->entity = r_addent;
  92. // add the entity link
  93. *lastlink = ef;
  94. lastlink = &ef->entnext;
  95. ef->entnext = NULL;
  96. // set the leaf links
  97. ef->leaf = leaf;
  98. ef->leafnext = leaf->efrags;
  99. leaf->efrags = ef;
  100. return;
  101. }
  102. // NODE_MIXED
  103. splitplane = node->plane;
  104. sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
  105. if (sides == 3)
  106. {
  107. // split on this plane
  108. // if this is the first splitter of this bmodel, remember it
  109. if (!r_pefragtopnode)
  110. r_pefragtopnode = node;
  111. }
  112. // recurse down the contacted sides
  113. if (sides & 1)
  114. R_SplitEntityOnNode (node->children[0]);
  115. if (sides & 2)
  116. R_SplitEntityOnNode (node->children[1]);
  117. }
  118. /*
  119. ===================
  120. R_SplitEntityOnNode2
  121. ===================
  122. */
  123. void R_SplitEntityOnNode2 (mnode_t *node)
  124. {
  125. mplane_t *splitplane;
  126. int sides;
  127. if (node->visframe != r_visframecount)
  128. return;
  129. if (node->contents < 0)
  130. {
  131. if (node->contents != CONTENTS_SOLID)
  132. r_pefragtopnode = node; // we've reached a non-solid leaf, so it's
  133. // visible and not BSP clipped
  134. return;
  135. }
  136. splitplane = node->plane;
  137. sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
  138. if (sides == 3)
  139. {
  140. // remember first splitter
  141. r_pefragtopnode = node;
  142. return;
  143. }
  144. // not split yet; recurse down the contacted side
  145. if (sides & 1)
  146. R_SplitEntityOnNode2 (node->children[0]);
  147. else
  148. R_SplitEntityOnNode2 (node->children[1]);
  149. }
  150. /*
  151. ===========
  152. R_AddEfrags
  153. ===========
  154. */
  155. void R_AddEfrags (entity_t *ent)
  156. {
  157. model_t *entmodel;
  158. int i;
  159. if (!ent->model)
  160. return;
  161. if (ent == &r_worldentity)
  162. return; // never add the world
  163. r_addent = ent;
  164. lastlink = &ent->efrag;
  165. r_pefragtopnode = NULL;
  166. entmodel = ent->model;
  167. for (i=0 ; i<3 ; i++)
  168. {
  169. r_emins[i] = ent->origin[i] + entmodel->mins[i];
  170. r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
  171. }
  172. R_SplitEntityOnNode (cl.worldmodel->nodes);
  173. ent->topnode = r_pefragtopnode;
  174. }
  175. /*
  176. ================
  177. R_StoreEfrags
  178. // FIXME: a lot of this goes away with edge-based
  179. ================
  180. */
  181. void R_StoreEfrags (efrag_t **ppefrag)
  182. {
  183. entity_t *pent;
  184. model_t *clmodel;
  185. efrag_t *pefrag;
  186. while ((pefrag = *ppefrag) != NULL)
  187. {
  188. pent = pefrag->entity;
  189. clmodel = pent->model;
  190. switch (clmodel->type)
  191. {
  192. case mod_alias:
  193. case mod_brush:
  194. case mod_sprite:
  195. pent = pefrag->entity;
  196. if ((pent->visframe != r_framecount) &&
  197. (cl_numvisedicts < MAX_VISEDICTS))
  198. {
  199. cl_visedicts[cl_numvisedicts++] = *pent;
  200. // mark that we've recorded this entity for this frame
  201. pent->visframe = r_framecount;
  202. }
  203. ppefrag = &pefrag->leafnext;
  204. break;
  205. default:
  206. Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
  207. }
  208. }
  209. }