Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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