1 /*
2 Copyright (C) 1997-2001 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 //
21 // rf_cull.c
22 //
23
24 #include "rf_local.h"
25
26 /*
27 =============================================================================
28
29 FRUSTUM CULLING
30
31 =============================================================================
32 */
33
34 /*
35 ===============
36 R_SetupFrustum
37 ===============
38 */
R_SetupFrustum(void)39 void R_SetupFrustum (void)
40 {
41 int i;
42
43 // Calculate the view frustum
44 Vec3Copy (ri.def.viewAxis[0], ri.scn.viewFrustum[0].normal);
45 RotatePointAroundVector (ri.scn.viewFrustum[1].normal, ri.def.viewAxis[2], ri.def.viewAxis[0], -(90-ri.def.fovX / 2));
46 RotatePointAroundVector (ri.scn.viewFrustum[2].normal, ri.def.viewAxis[2], ri.def.viewAxis[0], 90-ri.def.fovX / 2);
47 RotatePointAroundVector (ri.scn.viewFrustum[3].normal, ri.def.rightVec, ri.def.viewAxis[0], 90-ri.def.fovY / 2);
48 RotatePointAroundVector (ri.scn.viewFrustum[4].normal, ri.def.rightVec, ri.def.viewAxis[0], -(90 - ri.def.fovY / 2));
49
50 for (i=0 ; i<5 ; i++) {
51 ri.scn.viewFrustum[i].type = PLANE_NON_AXIAL;
52 ri.scn.viewFrustum[i].dist = DotProduct (ri.def.viewOrigin, ri.scn.viewFrustum[i].normal);
53 ri.scn.viewFrustum[i].signBits = SignbitsForPlane (&ri.scn.viewFrustum[i]);
54 }
55
56 ri.scn.viewFrustum[0].dist += r_zNear->floatVal;
57 }
58
59
60 /*
61 =================
62 R_CullBox
63
64 Returns qTrue if the box is completely outside the frustum
65 =================
66 */
R_CullBox(vec3_t mins,vec3_t maxs,int clipFlags)67 qBool R_CullBox (vec3_t mins, vec3_t maxs, int clipFlags)
68 {
69 int i;
70 cBspPlane_t *p;
71
72 if (r_noCull->intVal)
73 return qFalse;
74
75 for (i=0, p=ri.scn.viewFrustum ; i<5 ; p++, i++) {
76 if (!(clipFlags & (1<<i)))
77 continue;
78
79 switch (p->signBits) {
80 case 0:
81 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) {
82 ri.pc.cullBounds[CULL_PASS]++;
83 return qTrue;
84 }
85 break;
86
87 case 1:
88 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) {
89 ri.pc.cullBounds[CULL_PASS]++;
90 return qTrue;
91 }
92 break;
93
94 case 2:
95 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) {
96 ri.pc.cullBounds[CULL_PASS]++;
97 return qTrue;
98 }
99 break;
100
101 case 3:
102 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) {
103 ri.pc.cullBounds[CULL_PASS]++;
104 return qTrue;
105 }
106 break;
107
108 case 4:
109 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) {
110 ri.pc.cullBounds[CULL_PASS]++;
111 return qTrue;
112 }
113 break;
114
115 case 5:
116 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) {
117 ri.pc.cullBounds[CULL_PASS]++;
118 return qTrue;
119 }
120 break;
121
122 case 6:
123 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) {
124 ri.pc.cullBounds[CULL_PASS]++;
125 return qTrue;
126 }
127 break;
128
129 case 7:
130 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) {
131 ri.pc.cullBounds[CULL_PASS]++;
132 return qTrue;
133 }
134 break;
135
136 default:
137 assert (0);
138 return qFalse;
139 }
140 }
141
142 ri.pc.cullBounds[CULL_FAIL]++;
143 return qFalse;
144 }
145
146
147 /*
148 =================
149 R_CullSphere
150
151 Returns qTrue if the sphere is completely outside the frustum
152 =================
153 */
R_CullSphere(const vec3_t origin,const float radius,int clipFlags)154 qBool R_CullSphere (const vec3_t origin, const float radius, int clipFlags)
155 {
156 int i;
157 cBspPlane_t *p;
158
159 if (r_noCull->intVal)
160 return qFalse;
161
162 for (i=0, p=ri.scn.viewFrustum ; i<5 ; p++, i++) {
163 if (!(clipFlags & (1<<i)))
164 continue;
165
166 if (DotProduct(origin, p->normal)-p->dist <= -radius) {
167 ri.pc.cullRadius[CULL_PASS]++;
168 return qTrue;
169 }
170 }
171
172 ri.pc.cullRadius[CULL_FAIL]++;
173 return qFalse;
174 }
175
176 /*
177 =============================================================================
178
179 MAP VISIBILITY CULLING
180
181 =============================================================================
182 */
183
184 /*
185 ===============
186 R_CullNode
187
188 Returns qTrue if this node hasn't been touched this frame
189 ===============
190 */
R_CullNode(mBspNode_t * node)191 qBool R_CullNode (mBspNode_t *node)
192 {
193 if (r_noCull->intVal)
194 return qFalse;
195
196 if (!node || node->c.visFrame == ri.scn.visFrameCount) {
197 ri.pc.cullVis[CULL_FAIL]++;
198 return qFalse;
199 }
200
201 ri.pc.cullVis[CULL_PASS]++;
202 return qTrue;
203 }
204
205
206 /*
207 ===============
208 R_CullSurface
209
210 Returns qTrue if this surface hasn't been touched this frame
211 ===============
212 */
R_CullSurface(mBspSurface_t * surf)213 qBool R_CullSurface (mBspSurface_t *surf)
214 {
215 if (r_noCull->intVal)
216 return qFalse;
217
218 if (!surf || surf->visFrame == ri.frameCount) {
219 ri.pc.cullSurf[CULL_FAIL]++;
220 return qFalse;
221 }
222
223 ri.pc.cullSurf[CULL_PASS]++;
224 return qTrue;
225 }
226