Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 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 | }>3>>> |
||
275 |