diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/r_efrag.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/r_efrag.c | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/r_efrag.c b/apps/plugins/sdl/progs/quake/r_efrag.c new file mode 100644 index 0000000000..5e4d3f9e06 --- /dev/null +++ b/apps/plugins/sdl/progs/quake/r_efrag.c | |||
@@ -0,0 +1,276 @@ | |||
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 | } | ||
275 | |||
276 | |||