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 		Sys_Error("Ent with NULL model\n");
170 
171 	} else {
172 		//Con_Printf("Kept ent. %s\n",ent->model->name);
173 	}
174 
175 	r_addent = ent;
176 
177 	lastlink = &ent->efrag;
178 	r_pefragtopnode = NULL;
179 
180 	entmodel = ent->model;
181 
182 	for (i=0 ; i<3 ; i++)
183 	{
184 		r_emins[i] = ent->origin[i] + entmodel->mins[i];
185 		r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
186 	}
187 
188 	R_SplitEntityOnNode (cl.worldmodel->nodes);
189 
190 	ent->topnode = r_pefragtopnode;
191 }
192 
193 
194 /*
195 ================
196 R_StoreEfrags
197 
198 // FIXME: a lot of this goes away with edge-based
199 
200 Wat dit ook doet het voegt in ieder geval de statische ents aan
201 de visibility lijst voor dit frame toe.
202 Maar enkel de statische ents voor een leaf I suppose.
203 ================
204 */
R_StoreEfrags(efrag_t ** ppefrag)205 void R_StoreEfrags (efrag_t **ppefrag)
206 {
207 	entity_t	*pent;
208 	model_t		*clmodel;
209 	efrag_t		*pefrag;
210 
211 
212 	while ((pefrag = *ppefrag) != NULL)
213 	{
214 		pent = pefrag->entity;
215 		clmodel = pent->model;
216 
217 		//PENTA: null model? skip it!
218 		if (!clmodel) {
219 			ppefrag = &pefrag->leafnext;
220 		}
221 
222 		switch (clmodel->type)
223 		{
224 		case mod_alias:
225 		case mod_brush:
226 		case mod_sprite:
227 			pent = pefrag->entity;
228 
229 			//prob kunnen ents in meerdere leafs tegelijk zitten (overlappen van bbox)
230 			//maar we willen ze dus maar 1x tekenen
231 			if ((pent->visframe != r_framecount) &&
232 				(cl_numvisedicts < MAX_VISEDICTS))
233 			{
234 				cl_visedicts[cl_numvisedicts++] = pent;
235 
236 			// mark that we've recorded this entity for this frame
237 				pent->visframe = r_framecount;
238 			}
239 
240 			ppefrag = &pefrag->leafnext;
241 			break;
242 
243 		default:
244 			Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
245 		}
246 	}
247 }
248 /*
249 void R_SplitEntityOnNodePenta (mnode_t *node)
250 {
251 	efrag_t		*ef;
252 	mplane_t	*splitplane;
253 	mleaf_t		*leaf;
254 	int			sides;
255 
256 	if (node->contents == CONTENTS_SOLID)
257 	{
258 		return;
259 	}
260 
261 // add an efrag if the node is a leaf
262 
263 	if ( node->contents < 0)
264 	{
265 		leaf = (mleaf_t *)node;
266 
267 		//Store leaf index for vis lookup
268 		if (r_addent->numleafs < MAX_CLIENT_ENT_LEAFS) {
269 			r_addent->leafnums[r_addent->numleafs] = leaf->index;
270 			r_addent->numleafs++;
271 		} else {
272 			Con_Printf("Entity is in more than MAX_CLIENT_ENT_LEAFS leafs\n");
273 		}
274 
275 		return;
276 	}
277 
278 // NODE_MIXED
279 
280 	splitplane = node->plane;
281 	sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
282 
283 	if (sides == 3)
284 	{
285 	// split on this plane
286 	// if this is the first splitter of this bmodel, remember it
287 		if (!r_pefragtopnode)
288 			r_pefragtopnode = node;
289 	}
290 
291 // recurse down the contacted sides
292 	if (sides & 1)
293 		R_SplitEntityOnNodePenta (node->children[0]);
294 
295 	if (sides & 2)
296 		R_SplitEntityOnNodePenta (node->children[1]);
297 }
298 
299 */
R_SplitEntityOnNodePenta(entity_t * ent,mnode_t * node)300 void R_SplitEntityOnNodePenta (entity_t *ent, mnode_t *node)
301 {
302 	mplane_t	*splitplane;
303 	mleaf_t		*leaf;
304 	int			sides;
305 	int			leafnum;
306 
307 	if (node->contents == CONTENTS_SOLID)
308 		return;
309 
310 // add an efrag if the node is a leaf
311 
312 	if ( node->contents < 0)
313 	{
314 		if (ent->numleafs == MAX_CLIENT_ENT_LEAFS) {
315 			//Con_Printf("Max ent leafs reached\n");
316 			return;
317 		}
318 
319 		leaf = (mleaf_t *)node;
320 		leafnum = leaf - cl.worldmodel->leafs - 1;
321 
322 		ent->leafnums[ent->numleafs] = leafnum;
323 		ent->numleafs++;
324 		return;
325 	}
326 
327 // NODE_MIXED
328 
329 	splitplane = node->plane;
330 	sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
331 
332 // recurse down the contacted sides
333 	if (sides & 1)
334 		R_SplitEntityOnNodePenta (ent, node->children[0]);
335 
336 	if (sides & 2)
337 		R_SplitEntityOnNodePenta (ent, node->children[1]);
338 }
339 
340 
341 /*
342 ===================
343 R_FillEntityLeafs
344 ===================
345 */
R_FillEntityLeafs(entity_t * ent)346 void R_FillEntityLeafs (entity_t *ent)
347 {
348 	model_t		*entmodel;
349 	int			i;
350 
351 	if (!ent->model)
352 		return;
353 
354 	if (ent == cl_entities)
355 		return;		// never add the world
356 
357 	r_addent = ent;
358 
359 	entmodel = ent->model;
360 
361 	for (i=0 ; i<3 ; i++)
362 	{
363 		r_emins[i] = ent->origin[i] + entmodel->mins[i];
364 		r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
365 	}
366 
367 	//fiddle a bit with precision
368 	r_emins[0] -= 5;
369 	r_emins[1] -= 5;
370 	r_emins[2] -= 5;
371 	r_emaxs[0] += 5;
372 	r_emaxs[1] += 5;
373 	r_emaxs[2] += 5;
374 
375 	ent->numleafs = 0;
376 	R_SplitEntityOnNodePenta (ent, cl.worldmodel->nodes);
377 
378 	ent->topnode = r_pefragtopnode;
379 }
380 
381 
382