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
 
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
*/
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
*/
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
*/
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
*/
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