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