• 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 
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 		return;
170 
171 	r_addent = ent;
172 
173 	lastlink = &ent->efrag;
174 	r_pefragtopnode = NULL;
175 
176 	entmodel = ent->model;
177 
178 	for (i=0 ; i<3 ; i++)
179 	{
180 		r_emins[i] = ent->origin[i] + entmodel->mins[i];
181 		r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
182 	}
183 
184 	R_SplitEntityOnNode (cl.worldmodel->nodes);
185 
186 	ent->topnode = r_pefragtopnode;
187 }
188 
189 
190 /*
191 ================
192 R_StoreEfrags
193 
194 // FIXME: a lot of this goes away with edge-based
195 ================
196 */
R_StoreEfrags(efrag_t ** ppefrag)197 void R_StoreEfrags (efrag_t **ppefrag)
198 {
199 	entity_t	*pent;
200 	model_t		*clmodel;
201 	efrag_t		*pefrag;
202 
203 
204 	while ((pefrag = *ppefrag) != NULL)
205 	{
206 		pent = pefrag->entity;
207 		clmodel = pent->model;
208 
209 		switch (clmodel->type)
210 		{
211 		case mod_alias:
212 		case mod_brush:
213 		case mod_sprite:
214 			pent = pefrag->entity;
215 
216 			if ((pent->visframe != r_framecount) &&
217 				(cl_numvisedicts < MAX_VISEDICTS))
218 			{
219 				cl_visedicts[cl_numvisedicts++] = pent;
220 
221 			// mark that we've recorded this entity for this frame
222 				pent->visframe = r_framecount;
223 			}
224 
225 			ppefrag = &pefrag->leafnext;
226 			break;
227 
228 		default:
229 			Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
230 		}
231 	}
232 }
233 
234 
235