1 /*
2  * Frustum.cpp
3  * Copyright (C) 2007 by Bryan Duff <duff0097@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * 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
18  * USA
19  */
20 #include <cmath>
21 #include <GL/gl.h>
22 
23 #include "Frustum.h"
24 
GetFrustum()25 void FRUSTUM::GetFrustum()
26 {
27   float projmatrix[16];
28   float mvmatrix[16];
29   float clip[16];
30   float t;
31 
32   glGetFloatv(GL_PROJECTION_MATRIX, projmatrix);
33   glGetFloatv(GL_MODELVIEW_MATRIX, mvmatrix);
34 
35   // Combine the matrices
36   clip[0] =
37       mvmatrix[0] * projmatrix[0] + mvmatrix[1] * projmatrix[4] +
38       mvmatrix[2] * projmatrix[8] + mvmatrix[3] * projmatrix[12];
39   clip[1] =
40       mvmatrix[0] * projmatrix[1] + mvmatrix[1] * projmatrix[5] +
41       mvmatrix[2] * projmatrix[9] + mvmatrix[3] * projmatrix[13];
42   clip[2] =
43       mvmatrix[0] * projmatrix[2] + mvmatrix[1] * projmatrix[6] +
44       mvmatrix[2] * projmatrix[10] + mvmatrix[3] * projmatrix[14];
45   clip[3] =
46       mvmatrix[0] * projmatrix[3] + mvmatrix[1] * projmatrix[7] +
47       mvmatrix[2] * projmatrix[11] + mvmatrix[3] * projmatrix[15];
48 
49   clip[4] =
50       mvmatrix[4] * projmatrix[0] + mvmatrix[5] * projmatrix[4] +
51       mvmatrix[6] * projmatrix[8] + mvmatrix[7] * projmatrix[12];
52   clip[5] =
53       mvmatrix[4] * projmatrix[1] + mvmatrix[5] * projmatrix[5] +
54       mvmatrix[6] * projmatrix[9] + mvmatrix[7] * projmatrix[13];
55   clip[6] =
56       mvmatrix[4] * projmatrix[2] + mvmatrix[5] * projmatrix[6] +
57       mvmatrix[6] * projmatrix[10] + mvmatrix[7] * projmatrix[14];
58   clip[7] =
59       mvmatrix[4] * projmatrix[3] + mvmatrix[5] * projmatrix[7] +
60       mvmatrix[6] * projmatrix[11] + mvmatrix[7] * projmatrix[15];
61 
62   clip[8] =
63       mvmatrix[8] * projmatrix[0] + mvmatrix[9] * projmatrix[4] +
64       mvmatrix[10] * projmatrix[8] + mvmatrix[11] * projmatrix[12];
65   clip[9] =
66       mvmatrix[8] * projmatrix[1] + mvmatrix[9] * projmatrix[5] +
67       mvmatrix[10] * projmatrix[9] + mvmatrix[11] * projmatrix[13];
68   clip[10] =
69       mvmatrix[8] * projmatrix[2] + mvmatrix[9] * projmatrix[6] +
70       mvmatrix[10] * projmatrix[10] + mvmatrix[11] * projmatrix[14];
71   clip[11] =
72       mvmatrix[8] * projmatrix[3] + mvmatrix[9] * projmatrix[7] +
73       mvmatrix[10] * projmatrix[11] + mvmatrix[11] * projmatrix[15];
74 
75   clip[12] =
76       mvmatrix[12] * projmatrix[0] + mvmatrix[13] * projmatrix[4] +
77       mvmatrix[14] * projmatrix[8] + mvmatrix[15] * projmatrix[12];
78   clip[13] =
79       mvmatrix[12] * projmatrix[1] + mvmatrix[13] * projmatrix[5] +
80       mvmatrix[14] * projmatrix[9] + mvmatrix[15] * projmatrix[13];
81   clip[14] =
82       mvmatrix[12] * projmatrix[2] + mvmatrix[13] * projmatrix[6] +
83       mvmatrix[14] * projmatrix[10] + mvmatrix[15] * projmatrix[14];
84   clip[15] =
85       mvmatrix[12] * projmatrix[3] + mvmatrix[13] * projmatrix[7] +
86       mvmatrix[14] * projmatrix[11] + mvmatrix[15] * projmatrix[15];
87 
88   // Right plane
89   frustum[0][0] = clip[3] - clip[0];
90   frustum[0][1] = clip[7] - clip[4];
91   frustum[0][2] = clip[11] - clip[8];
92   frustum[0][3] = clip[15] - clip[12];
93 
94   // Left plane
95   frustum[1][0] = clip[3] + clip[0];
96   frustum[1][1] = clip[7] + clip[4];
97   frustum[1][2] = clip[11] + clip[8];
98   frustum[1][3] = clip[15] + clip[12];
99 
100   // Bottom plane
101   frustum[2][0] = clip[3] + clip[1];
102   frustum[2][1] = clip[7] + clip[5];
103   frustum[2][2] = clip[11] + clip[9];
104   frustum[2][3] = clip[15] + clip[13];
105 
106   // Top plane
107   frustum[3][0] = clip[3] - clip[1];
108   frustum[3][1] = clip[7] - clip[5];
109   frustum[3][2] = clip[11] - clip[9];
110   frustum[3][3] = clip[15] - clip[13];
111 
112   // Far plane
113   frustum[4][0] = clip[3] - clip[2];
114   frustum[4][1] = clip[7] - clip[6];
115   frustum[4][2] = clip[11] - clip[10];
116   frustum[4][3] = clip[15] - clip[14];
117 
118   // Near plane
119   frustum[5][0] = clip[3] + clip[2];
120   frustum[5][1] = clip[7] + clip[6];
121   frustum[5][2] = clip[11] + clip[10];
122   frustum[5][3] = clip[15] + clip[14];
123 
124   /* normalize the right plane */
125   t = sqrt(frustum[0][0] * frustum[0][0]
126            + frustum[0][1] * frustum[0][1]
127            + frustum[0][2] * frustum[0][2]);
128   frustum[0][0] /= t;
129   frustum[0][1] /= t;
130   frustum[0][2] /= t;
131   frustum[0][3] /= t;
132 
133   /* calculate left plane */
134   frustum[1][0] = clip[3] + clip[0];
135   frustum[1][1] = clip[7] + clip[4];
136   frustum[1][2] = clip[11] + clip[8];
137   frustum[1][3] = clip[15] + clip[12];
138 
139   /* normalize the left plane */
140   t = sqrt(frustum[1][0] * frustum[1][0]
141            + frustum[1][1] * frustum[1][1]
142            + frustum[1][2] * frustum[1][2]);
143   frustum[1][0] /= t;
144   frustum[1][1] /= t;
145   frustum[1][2] /= t;
146   frustum[1][3] /= t;
147 
148   /* calculate the bottom plane */
149   frustum[2][0] = clip[3] + clip[1];
150   frustum[2][1] = clip[7] + clip[5];
151   frustum[2][2] = clip[11] + clip[9];
152   frustum[2][3] = clip[15] + clip[13];
153 
154   /* normalize the bottom plane */
155   t = sqrt(frustum[2][0] * frustum[2][0]
156            + frustum[2][1] * frustum[2][1]
157            + frustum[2][2] * frustum[2][2]);
158   frustum[2][0] /= t;
159   frustum[2][1] /= t;
160   frustum[2][2] /= t;
161   frustum[2][3] /= t;
162 
163   /* calculate the top plane */
164   frustum[3][0] = clip[3] - clip[1];
165   frustum[3][1] = clip[7] - clip[5];
166   frustum[3][2] = clip[11] - clip[9];
167   frustum[3][3] = clip[15] - clip[13];
168 
169   /* normalize the top plane */
170   t = sqrt(frustum[3][0] * frustum[3][0]
171            + frustum[3][1] * frustum[3][1]
172            + frustum[3][2] * frustum[3][2]);
173   frustum[3][0] /= t;
174   frustum[3][1] /= t;
175   frustum[3][2] /= t;
176   frustum[3][3] /= t;
177 
178   /* calculate the far plane */
179   frustum[4][0] = clip[3] - clip[2];
180   frustum[4][1] = clip[7] - clip[6];
181   frustum[4][2] = clip[11] - clip[10];
182   frustum[4][3] = clip[15] - clip[14];
183 
184   /* normalize the far plane */
185   t = sqrt(frustum[4][0] * frustum[4][0]
186            + frustum[4][1] * frustum[4][1]
187            + frustum[4][2] * frustum[4][2]);
188   frustum[4][0] /= t;
189   frustum[4][1] /= t;
190   frustum[4][2] /= t;
191   frustum[4][3] /= t;
192 
193   /* calculate the near plane */
194   frustum[5][0] = clip[3] + clip[2];
195   frustum[5][1] = clip[7] + clip[6];
196   frustum[5][2] = clip[11] + clip[10];
197   frustum[5][3] = clip[15] + clip[14];
198 
199   /* normalize the near plane */
200   t = sqrt(frustum[5][0] * frustum[5][0]
201            + frustum[5][1] * frustum[5][1]
202            + frustum[5][2] * frustum[5][2]);
203   frustum[5][0] /= t;
204   frustum[5][1] /= t;
205   frustum[5][2] /= t;
206   frustum[5][3] /= t;
207 
208 }
209 
CubeInFrustum(float x,float y,float z,float size)210 int FRUSTUM::CubeInFrustum(float x, float y, float z, float size)
211 {
212   int c, c2;
213 
214   c2 = 0;
215   for(int i = 0; i < 6; i++) {
216     c = 0;
217     if(frustum[i][0] * (x - size) + frustum[i][1] * (y - size) +
218        frustum[i][2] * (z - size) + frustum[i][3] > 0)
219       c++;
220     if(frustum[i][0] * (x + size) + frustum[i][1] * (y - size) +
221        frustum[i][2] * (z - size) + frustum[i][3] > 0)
222       c++;
223     if(frustum[i][0] * (x - size) + frustum[i][1] * (y + size) +
224        frustum[i][2] * (z - size) + frustum[i][3] > 0)
225       c++;
226     if(frustum[i][0] * (x + size) + frustum[i][1] * (y + size) +
227        frustum[i][2] * (z - size) + frustum[i][3] > 0)
228       c++;
229     if(frustum[i][0] * (x - size) + frustum[i][1] * (y - size) +
230        frustum[i][2] * (z + size) + frustum[i][3] > 0)
231       c++;
232     if(frustum[i][0] * (x + size) + frustum[i][1] * (y - size) +
233        frustum[i][2] * (z + size) + frustum[i][3] > 0)
234       c++;
235     if(frustum[i][0] * (x - size) + frustum[i][1] * (y + size) +
236        frustum[i][2] * (z + size) + frustum[i][3] > 0)
237       c++;
238     if(frustum[i][0] * (x + size) + frustum[i][1] * (y + size) +
239        frustum[i][2] * (z + size) + frustum[i][3] > 0)
240       c++;
241     if(c == 0)
242       return 0;
243     if(c == 8)
244       c2++;
245   }
246   if(c2 >= 6)
247     return 2;
248   else
249     return 1;
250 }
251 
CubeInFrustum(float x,float y,float z,float size,float height)252 int FRUSTUM::CubeInFrustum(float x, float y, float z, float size, float height)
253 {
254   int c, c2;
255 
256   c2 = 0;
257   for(int i = 0; i < 6; i++) {
258     c = 0;
259     if(frustum[i][0] * (x - size) + frustum[i][1] * (y - height) +
260        frustum[i][2] * (z - size) + frustum[i][3] > 0)
261       c++;
262     if(frustum[i][0] * (x + size) + frustum[i][1] * (y - height) +
263        frustum[i][2] * (z - size) + frustum[i][3] > 0)
264       c++;
265     if(frustum[i][0] * (x - size) + frustum[i][1] * (y + height) +
266        frustum[i][2] * (z - size) + frustum[i][3] > 0)
267       c++;
268     if(frustum[i][0] * (x + size) + frustum[i][1] * (y + height) +
269        frustum[i][2] * (z - size) + frustum[i][3] > 0)
270       c++;
271     if(frustum[i][0] * (x - size) + frustum[i][1] * (y - height) +
272        frustum[i][2] * (z + size) + frustum[i][3] > 0)
273       c++;
274     if(frustum[i][0] * (x + size) + frustum[i][1] * (y - height) +
275        frustum[i][2] * (z + size) + frustum[i][3] > 0)
276       c++;
277     if(frustum[i][0] * (x - size) + frustum[i][1] * (y + height) +
278        frustum[i][2] * (z + size) + frustum[i][3] > 0)
279       c++;
280     if(frustum[i][0] * (x + size) + frustum[i][1] * (y + height) +
281        frustum[i][2] * (z + size) + frustum[i][3] > 0)
282       c++;
283     if(c == 0)
284       return 0;
285     if(c == 8)
286       c2++;
287   }
288   if(c2 >= 6)
289     return 2;
290   else
291     return 1;
292 }
293 
SphereInFrustum(float x,float y,float z,float radius)294 int FRUSTUM::SphereInFrustum(float x, float y, float z, float radius)
295 {
296   int c2;
297 
298   c2 = 0;
299   for(int i = 0; i < 6; i++) {
300     if(frustum[i][0] * x + frustum[i][1] * y + frustum[i][2] * z +
301        frustum[i][3] > -1 * radius)
302       c2++;
303     else
304       return 0;
305   }
306   if(c2 >= 6)
307     return 2;
308   else
309     return 1;
310 }
311