summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/r_efrag.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/r_efrag.c')
-rw-r--r--apps/plugins/sdl/progs/quake/r_efrag.c276
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/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 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
25mnode_t *r_pefragtopnode;
26
27
28//===========================================================================
29
30/*
31===============================================================================
32
33 ENTITY FRAGMENT FUNCTIONS
34
35===============================================================================
36*/
37
38efrag_t **lastlink;
39
40vec3_t r_emins, r_emaxs;
41
42entity_t *r_addent;
43
44
45/*
46================
47R_RemoveEfrags
48
49Call when removing an object from the world or moving it to another position
50================
51*/
52void 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===================
88R_SplitEntityOnNode
89===================
90*/
91void 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===================
160R_SplitEntityOnNode2
161===================
162*/
163void 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===========
199R_AddEfrags
200===========
201*/
202void 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================
234R_StoreEfrags
235
236// FIXME: a lot of this goes away with edge-based
237================
238*/
239void 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