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 */
R_RemoveEfrags(entity_t * ent)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 */
R_SplitEntityOnNode(mnode_t * node)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 */
R_AddEfrags(entity_t * ent)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 */
R_StoreEfrags(efrag_t ** ppefrag)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