• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
R_RemoveEfrags(entity_t * ent)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 */
R_SplitEntityOnNode(mnode_t * node)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 */
R_SplitEntityOnNode2(mnode_t * node)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 */
R_AddEfrags(entity_t * ent)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 */
R_StoreEfrags(efrag_t ** ppefrag)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 
277