1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2011
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 ////////////////////////////////////////////////////////////////////////////////
20
21 #include <math.h>
22 #include <GLEXT/GLState.h>
23 #include <GLEXT/GLCameraFrustum.h>
24 #include <graph/OptionsDisplay.h>
25
26 Vector GLCameraFrustum::FrustrumRed(1.0f, 0.0f, 0.0f);
27 Vector GLCameraFrustum::FrustrumBlue(0.0f, 0.0f, 1.0f);
28 Vector GLCameraFrustum::FrustrumGreen(0.0f, 1.0f, 0.0f);
29 Vector GLCameraFrustum::FrustrumWhite(1.0f, 1.0f, 1.0f);
30
31 GLCameraFrustum *GLCameraFrustum::instance_ = 0;
32
instance()33 GLCameraFrustum *GLCameraFrustum::instance()
34 {
35 if (!instance_)
36 {
37 instance_ = new GLCameraFrustum;
38 }
39
40 return instance_;
41 }
42
GLCameraFrustum()43 GLCameraFrustum::GLCameraFrustum() :
44 GameStateI("GLCameraFrustum")
45 {
46
47 }
48
~GLCameraFrustum()49 GLCameraFrustum::~GLCameraFrustum()
50 {
51
52 }
53
normalize(float vector[4])54 void GLCameraFrustum::normalize(float vector[4])
55 {
56 float fT = (float) sqrt(
57 vector[0] * vector[0] +
58 vector[1] * vector[1] +
59 vector[2] * vector[2]);
60
61 vector[0] /= fT;
62 vector[1] /= fT;
63 vector[2] /= fT;
64 vector[3] /= fT;
65 }
66
getBilboardVectorX()67 Vector &GLCameraFrustum::getBilboardVectorX()
68 {
69 static Vector bil;
70 bil[0] = s.fClip[0];
71 bil[1] = s.fClip[4];
72 bil[2] = s.fClip[8];
73 bil *= s.aspect * 0.8f;
74
75 return bil;
76 }
77
getBilboardVectorY()78 Vector &GLCameraFrustum::getBilboardVectorY()
79 {
80 static Vector bil;
81 bil[0] = s.fClip[1];
82 bil[1] = s.fClip[5];
83 bil[2] = s.fClip[9];
84 bil *= 0.8f;
85
86 return bil;
87 }
88
draw(const unsigned state)89 void GLCameraFrustum::draw(const unsigned state)
90 {
91 // Get the current projection matrix from OpenGL
92 // Get the current modelview matrix from OpenGL
93 glGetFloatv(GL_PROJECTION_MATRIX, s.fProj);
94 glGetFloatv(GL_MODELVIEW_MATRIX, s.fView);
95 glGetFloatv(GL_VIEWPORT, s.viewport);
96 s.aspect = s.viewport[2] / s.viewport[3];
97
98 // Concenate the two matrices
99 s.fClip[ 0] = s.fView[ 0] * s.fProj[ 0] + s.fView[ 1] * s.fProj[ 4] + s.fView[ 2] * s.fProj[ 8] + s.fView[ 3] * s.fProj[12];
100 s.fClip[ 1] = s.fView[ 0] * s.fProj[ 1] + s.fView[ 1] * s.fProj[ 5] + s.fView[ 2] * s.fProj[ 9] + s.fView[ 3] * s.fProj[13];
101 s.fClip[ 2] = s.fView[ 0] * s.fProj[ 2] + s.fView[ 1] * s.fProj[ 6] + s.fView[ 2] * s.fProj[10] + s.fView[ 3] * s.fProj[14];
102 s.fClip[ 3] = s.fView[ 0] * s.fProj[ 3] + s.fView[ 1] * s.fProj[ 7] + s.fView[ 2] * s.fProj[11] + s.fView[ 3] * s.fProj[15];
103
104 s.fClip[ 4] = s.fView[ 4] * s.fProj[ 0] + s.fView[ 5] * s.fProj[ 4] + s.fView[ 6] * s.fProj[ 8] + s.fView[ 7] * s.fProj[12];
105 s.fClip[ 5] = s.fView[ 4] * s.fProj[ 1] + s.fView[ 5] * s.fProj[ 5] + s.fView[ 6] * s.fProj[ 9] + s.fView[ 7] * s.fProj[13];
106 s.fClip[ 6] = s.fView[ 4] * s.fProj[ 2] + s.fView[ 5] * s.fProj[ 6] + s.fView[ 6] * s.fProj[10] + s.fView[ 7] * s.fProj[14];
107 s.fClip[ 7] = s.fView[ 4] * s.fProj[ 3] + s.fView[ 5] * s.fProj[ 7] + s.fView[ 6] * s.fProj[11] + s.fView[ 7] * s.fProj[15];
108
109 s.fClip[ 8] = s.fView[ 8] * s.fProj[ 0] + s.fView[ 9] * s.fProj[ 4] + s.fView[10] * s.fProj[ 8] + s.fView[11] * s.fProj[12];
110 s.fClip[ 9] = s.fView[ 8] * s.fProj[ 1] + s.fView[ 9] * s.fProj[ 5] + s.fView[10] * s.fProj[ 9] + s.fView[11] * s.fProj[13];
111 s.fClip[10] = s.fView[ 8] * s.fProj[ 2] + s.fView[ 9] * s.fProj[ 6] + s.fView[10] * s.fProj[10] + s.fView[11] * s.fProj[14];
112 s.fClip[11] = s.fView[ 8] * s.fProj[ 3] + s.fView[ 9] * s.fProj[ 7] + s.fView[10] * s.fProj[11] + s.fView[11] * s.fProj[15];
113
114 s.fClip[12] = s.fView[12] * s.fProj[ 0] + s.fView[13] * s.fProj[ 4] + s.fView[14] * s.fProj[ 8] + s.fView[15] * s.fProj[12];
115 s.fClip[13] = s.fView[12] * s.fProj[ 1] + s.fView[13] * s.fProj[ 5] + s.fView[14] * s.fProj[ 9] + s.fView[15] * s.fProj[13];
116 s.fClip[14] = s.fView[12] * s.fProj[ 2] + s.fView[13] * s.fProj[ 6] + s.fView[14] * s.fProj[10] + s.fView[15] * s.fProj[14];
117 s.fClip[15] = s.fView[12] * s.fProj[ 3] + s.fView[13] * s.fProj[ 7] + s.fView[14] * s.fProj[11] + s.fView[15] * s.fProj[15];
118
119 // Bilboard matrix
120 s.fBilboard[0] = s.fClip[0];
121 s.fBilboard[1] = s.fClip[4];
122 s.fBilboard[2] = s.fClip[8];
123 s.fBilboard[3] = 0.0f; // x
124
125 s.fBilboard[4] = s.fClip[1];
126 s.fBilboard[5] = s.fClip[5];
127 s.fBilboard[6] = s.fClip[9];
128 s.fBilboard[7] = 0.0f; // y
129
130 s.fBilboard[8] = s.fClip[2];
131 s.fBilboard[9] = s.fClip[6];
132 s.fBilboard[10] = s.fClip[10];
133 s.fBilboard[11] = 0.0f; // z
134
135 s.fBilboard[12] = 0.0f;
136 s.fBilboard[13] = 0.0f;
137 s.fBilboard[14] = 0.0f;
138 s.fBilboard[15] = 1.0f;
139
140 // Extract the right plane
141 s.frustum_[0][0] = s.fClip[ 3] - s.fClip[ 0];
142 s.frustum_[0][1] = s.fClip[ 7] - s.fClip[ 4];
143 s.frustum_[0][2] = s.fClip[11] - s.fClip[ 8];
144 s.frustum_[0][3] = s.fClip[15] - s.fClip[12];
145 normalize(s.frustum_[0]);
146
147 // Extract the left plane
148 s.frustum_[1][0] = s.fClip[ 3] + s.fClip[ 0];
149 s.frustum_[1][1] = s.fClip[ 7] + s.fClip[ 4];
150 s.frustum_[1][2] = s.fClip[11] + s.fClip[ 8];
151 s.frustum_[1][3] = s.fClip[15] + s.fClip[12];
152 normalize(s.frustum_[1]);
153
154 // Extract the bottom plane
155 s.frustum_[2][0] = s.fClip[ 3] + s.fClip[ 1];
156 s.frustum_[2][1] = s.fClip[ 7] + s.fClip[ 5];
157 s.frustum_[2][2] = s.fClip[11] + s.fClip[ 9];
158 s.frustum_[2][3] = s.fClip[15] + s.fClip[13];
159 normalize(s.frustum_[2]);
160
161 // Extract the top plane
162 s.frustum_[3][0] = s.fClip[ 3] - s.fClip[ 1];
163 s.frustum_[3][1] = s.fClip[ 7] - s.fClip[ 5];
164 s.frustum_[3][2] = s.fClip[11] - s.fClip[ 9];
165 s.frustum_[3][3] = s.fClip[15] - s.fClip[13];
166 normalize(s.frustum_[3]);
167
168 // Extract the far plane
169 s.frustum_[4][0] = s.fClip[ 3] - s.fClip[ 2];
170 s.frustum_[4][1] = s.fClip[ 7] - s.fClip[ 6];
171 s.frustum_[4][2] = s.fClip[11] - s.fClip[10];
172 s.frustum_[4][3] = s.fClip[15] - s.fClip[14];
173 normalize(s.frustum_[4]);
174
175 // Extract the near plane
176 s.frustum_[5][0] = s.fClip[ 3] + s.fClip[ 2];
177 s.frustum_[5][1] = s.fClip[ 7] + s.fClip[ 6];
178 s.frustum_[5][2] = s.fClip[11] + s.fClip[10];
179 s.frustum_[5][3] = s.fClip[15] + s.fClip[14];
180 normalize(s.frustum_[5]);
181 }
182
sphereInFrustum(Vector & point,float fRadius,Vector & color)183 bool GLCameraFrustum::sphereInFrustum(Vector &point,
184 float fRadius, Vector &color)
185 {
186 if (OptionsDisplay::instance()->getDrawBoundingSpheres())
187 {
188 static GLUquadric *obj = 0;
189 if (!obj)
190 {
191 obj = gluNewQuadric();
192 gluQuadricDrawStyle(obj, GLU_LINE);
193 }
194
195 GLState glState(GLState::TEXTURE_OFF);
196 glColor3fv(color);
197 glPushMatrix();
198 glTranslatef(point[0], point[1], point[2]);
199 gluSphere(obj, fRadius, 6, 6);
200 glPopMatrix();
201 }
202
203 return sphereInFrustumThreadSafe(point, fRadius);
204 }
205
sphereInFrustumThreadSafe(Vector & point,float fRadius)206 bool GLCameraFrustum::sphereInFrustumThreadSafe(Vector &point, float fRadius)
207 {
208 for (int iCurPlane = 0; iCurPlane<6; iCurPlane++)
209 {
210 float value =
211 s.frustum_[iCurPlane][0] * point[0] +
212 s.frustum_[iCurPlane][1] * point[1] +
213 s.frustum_[iCurPlane][2] * point[2] +
214 s.frustum_[iCurPlane][3];
215 if (value <= -fRadius)
216 {
217 return false;
218 }
219 }
220
221 return true;
222 }
223
backupFrustum()224 void GLCameraFrustum::backupFrustum()
225 {
226 memcpy(&b, &s, sizeof(b));
227 }
228
restoreFrustum()229 void GLCameraFrustum::restoreFrustum()
230 {
231 memcpy(&s, &b, sizeof(b));
232 }
233
drawBilboard(Vector & position,Vector & color,float alpha,float width,float height,bool additive,int textureCoord)234 void GLCameraFrustum::drawBilboard(Vector &position, Vector &color, float alpha,
235 float width, float height, bool additive, int textureCoord)
236 {
237 if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE);
238
239 Vector &bilX = getBilboardVectorX();
240 Vector &bilY = getBilboardVectorY();
241
242 float bilXX = bilX[0] * width;
243 float bilXY = bilX[1] * width;
244 float bilXZ = bilX[2] * width;
245 float bilYX = bilY[0] * height;
246 float bilYY = bilY[1] * height;
247 float bilYZ = bilY[2] * height;
248
249 glColor4f(color[0], color[1], color[2], alpha);
250 glBegin(GL_QUADS);
251 switch(textureCoord)
252 {
253 default: glTexCoord2d(1.0f, 1.0f); break;
254 case 1: glTexCoord2d(0.0f, 1.0f); break;
255 case 2: glTexCoord2d(0.0f, 0.0f); break;
256 case 3: glTexCoord2d(1.0f, 0.0f); break;
257 }
258 glVertex3f(
259 position[0] + bilXX + bilYX,
260 position[1] + bilXY + bilYY,
261 position[2] + bilXZ + bilYZ);
262 switch(textureCoord)
263 {
264 default: glTexCoord2d(0.0f, 1.0f); break;
265 case 1: glTexCoord2d(0.0f, 0.0f); break;
266 case 2: glTexCoord2d(1.0f, 0.0f); break;
267 case 3: glTexCoord2d(1.0f, 1.0f); break;
268 }
269 glVertex3f(
270 position[0] - bilXX + bilYX,
271 position[1] - bilXY + bilYY,
272 position[2] - bilXZ + bilYZ);
273 switch(textureCoord)
274 {
275 default: glTexCoord2d(0.0f, 0.0f); break;
276 case 1: glTexCoord2d(1.0f, 0.0f); break;
277 case 2: glTexCoord2d(1.0f, 1.0f); break;
278 case 3: glTexCoord2d(0.0f, 1.0f); break;
279 }
280 glVertex3f(
281 position[0] - bilXX - bilYX,
282 position[1] - bilXY - bilYY,
283 position[2] - bilXZ - bilYZ);
284 switch(textureCoord)
285 {
286 default: glTexCoord2d(1.0f, 0.0f); break;
287 case 1: glTexCoord2d(1.0f, 1.0f); break;
288 case 2: glTexCoord2d(0.0f, 1.0f); break;
289 case 3: glTexCoord2d(0.0f, 0.0f); break;
290 }
291 glVertex3f(
292 position[0] + bilXX - bilYX,
293 position[1] + bilXY - bilYY,
294 position[2] + bilXZ - bilYZ);
295 glEnd();
296
297 if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
298 }
299
300