GLCameraFrustum.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <math.h>
00022 #include <GLEXT/GLState.h>
00023 #include <GLEXT/GLCameraFrustum.h>
00024 #include <graph/OptionsDisplay.h>
00025 
00026 Vector GLCameraFrustum::FrustrumRed(1.0f, 0.0f, 0.0f);
00027 Vector GLCameraFrustum::FrustrumBlue(0.0f, 0.0f, 1.0f);
00028 Vector GLCameraFrustum::FrustrumGreen(0.0f, 1.0f, 0.0f);
00029 Vector GLCameraFrustum::FrustrumWhite(1.0f, 1.0f, 1.0f);
00030 
00031 GLCameraFrustum *GLCameraFrustum::instance_ = 0;
00032 
00033 GLCameraFrustum *GLCameraFrustum::instance()
00034 {
00035         if (!instance_)
00036         {
00037                 instance_ = new GLCameraFrustum;
00038         }
00039 
00040         return instance_;
00041 }
00042 
00043 GLCameraFrustum::GLCameraFrustum() :
00044         GameStateI("GLCameraFrustum")
00045 {
00046 
00047 }
00048 
00049 GLCameraFrustum::~GLCameraFrustum()
00050 {
00051 
00052 }
00053 
00054 void GLCameraFrustum::normalize(float vector[4])
00055 {
00056    float fT = (float) sqrt(
00057            vector[0] * vector[0] + 
00058            vector[1] * vector[1] + 
00059            vector[2] * vector[2]);
00060 
00061    vector[0] /= fT;
00062    vector[1] /= fT;
00063    vector[2] /= fT;
00064    vector[3] /= fT;
00065 }
00066 
00067 Vector &GLCameraFrustum::getBilboardVectorX()
00068 {
00069         static Vector bil;
00070         bil[0] = s.fClip[0];
00071         bil[1] = s.fClip[4];
00072         bil[2] = s.fClip[8];
00073         bil *= s.aspect * 0.8f;
00074 
00075         return bil;
00076 }
00077 
00078 Vector &GLCameraFrustum::getBilboardVectorY()
00079 {
00080         static Vector bil;
00081         bil[0] = s.fClip[1];
00082         bil[1] = s.fClip[5];
00083         bil[2] = s.fClip[9];
00084         bil *= 0.8f;
00085 
00086         return bil;
00087 }
00088 
00089 void GLCameraFrustum::draw(const unsigned state)
00090 {
00091         // Get the current projection matrix from OpenGL
00092         // Get the current modelview matrix from OpenGL
00093         glGetFloatv(GL_PROJECTION_MATRIX, s.fProj);
00094         glGetFloatv(GL_MODELVIEW_MATRIX, s.fView);
00095         glGetFloatv(GL_VIEWPORT, s.viewport);
00096         s.aspect = s.viewport[2] / s.viewport[3];
00097 
00098         // Concenate the two matrices
00099         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];
00100         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];
00101         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];
00102         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];
00103 
00104         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];
00105         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];
00106         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];
00107         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];
00108 
00109         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];
00110         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];
00111         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];
00112         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];
00113 
00114         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];
00115         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];
00116         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];
00117         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];
00118 
00119         // Extract the right plane
00120         s.frustum_[0][0] = s.fClip[ 3] - s.fClip[ 0];
00121         s.frustum_[0][1] = s.fClip[ 7] - s.fClip[ 4];
00122         s.frustum_[0][2] = s.fClip[11] - s.fClip[ 8];
00123         s.frustum_[0][3] = s.fClip[15] - s.fClip[12];
00124         normalize(s.frustum_[0]);
00125 
00126         // Extract the left plane
00127         s.frustum_[1][0] = s.fClip[ 3] + s.fClip[ 0];
00128         s.frustum_[1][1] = s.fClip[ 7] + s.fClip[ 4];
00129         s.frustum_[1][2] = s.fClip[11] + s.fClip[ 8];
00130         s.frustum_[1][3] = s.fClip[15] + s.fClip[12];
00131         normalize(s.frustum_[1]);
00132 
00133         // Extract the bottom plane
00134         s.frustum_[2][0] = s.fClip[ 3] + s.fClip[ 1];
00135         s.frustum_[2][1] = s.fClip[ 7] + s.fClip[ 5];
00136         s.frustum_[2][2] = s.fClip[11] + s.fClip[ 9];
00137         s.frustum_[2][3] = s.fClip[15] + s.fClip[13];
00138         normalize(s.frustum_[2]);
00139 
00140         // Extract the top plane
00141         s.frustum_[3][0] = s.fClip[ 3] - s.fClip[ 1];
00142         s.frustum_[3][1] = s.fClip[ 7] - s.fClip[ 5];
00143         s.frustum_[3][2] = s.fClip[11] - s.fClip[ 9];
00144         s.frustum_[3][3] = s.fClip[15] - s.fClip[13];
00145         normalize(s.frustum_[3]);
00146 
00147         // Extract the far plane
00148         s.frustum_[4][0] = s.fClip[ 3] - s.fClip[ 2];
00149         s.frustum_[4][1] = s.fClip[ 7] - s.fClip[ 6];
00150         s.frustum_[4][2] = s.fClip[11] - s.fClip[10];
00151         s.frustum_[4][3] = s.fClip[15] - s.fClip[14];
00152         normalize(s.frustum_[4]);
00153 
00154         // Extract the near plane
00155         s.frustum_[5][0] = s.fClip[ 3] + s.fClip[ 2];
00156         s.frustum_[5][1] = s.fClip[ 7] + s.fClip[ 6];
00157         s.frustum_[5][2] = s.fClip[11] + s.fClip[10];
00158         s.frustum_[5][3] = s.fClip[15] + s.fClip[14];
00159         normalize(s.frustum_[5]);
00160 }
00161 
00162 bool GLCameraFrustum::sphereInFrustum(Vector &point, 
00163         float fRadius, Vector &color)
00164 {
00165         if (OptionsDisplay::instance()->getDrawBoundingSpheres())
00166         {
00167                 static GLUquadric *obj = 0;
00168                 if (!obj)
00169                 {
00170                         obj = gluNewQuadric();
00171                         gluQuadricDrawStyle(obj, GLU_LINE);
00172                 }
00173 
00174                 GLState glState(GLState::TEXTURE_OFF);
00175                 glColor3fv(color);
00176                 glPushMatrix();
00177                         glTranslatef(point[0], point[1], point[2]);
00178                         gluSphere(obj, fRadius, 6, 6);
00179                 glPopMatrix();
00180         }
00181 
00182         return sphereInFrustumThreadSafe(point, fRadius);
00183 }
00184 
00185 bool GLCameraFrustum::sphereInFrustumThreadSafe(Vector &point, float fRadius)
00186 {
00187         for (int iCurPlane = 0; iCurPlane<6; iCurPlane++)
00188         {
00189                 float value = 
00190                         s.frustum_[iCurPlane][0] * point[0] + 
00191                         s.frustum_[iCurPlane][1] * point[1] + 
00192                         s.frustum_[iCurPlane][2] * point[2] + 
00193                         s.frustum_[iCurPlane][3];
00194                 if (value <= -fRadius)
00195                 {
00196                         return false;
00197                 }
00198         }
00199 
00200         return true;
00201 }
00202 
00203 void GLCameraFrustum::backupFrustum()
00204 {
00205         memcpy(&b, &s, sizeof(b));
00206 }
00207 
00208 void GLCameraFrustum::restoreFrustum()
00209 {
00210         memcpy(&s, &b, sizeof(b));
00211 }
00212 
00213 void GLCameraFrustum::drawBilboard(Vector &position, Vector &color, float alpha,
00214         float width, float height, bool additive, int textureCoord)
00215 {
00216         if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00217 
00218         Vector &bilX = getBilboardVectorX();
00219         Vector &bilY = getBilboardVectorY();
00220 
00221         float bilXX = bilX[0] * width;
00222         float bilXY = bilX[1] * width;
00223         float bilXZ = bilX[2] * width;
00224         float bilYX = bilY[0] * height;
00225         float bilYY = bilY[1] * height;
00226         float bilYZ = bilY[2] * height;
00227 
00228         glColor4f(color[0], color[1], color[2], alpha);
00229         glBegin(GL_QUADS);
00230         switch(textureCoord)
00231         {
00232         default: glTexCoord2d(1.0f, 1.0f); break;
00233         case 1:  glTexCoord2d(0.0f, 1.0f); break;
00234         case 2:  glTexCoord2d(0.0f, 0.0f); break;
00235         case 3:  glTexCoord2d(1.0f, 0.0f); break;
00236         }
00237         glVertex3f(
00238                 position[0] + bilXX + bilYX, 
00239                 position[1] + bilXY + bilYY, 
00240                 position[2] + bilXZ + bilYZ);
00241         switch(textureCoord)
00242         {
00243         default: glTexCoord2d(0.0f, 1.0f); break;
00244         case 1:  glTexCoord2d(0.0f, 0.0f); break;
00245         case 2:  glTexCoord2d(1.0f, 0.0f); break;
00246         case 3:  glTexCoord2d(1.0f, 1.0f); break;
00247         }
00248         glVertex3f(
00249                 position[0] - bilXX + bilYX, 
00250                 position[1] - bilXY + bilYY, 
00251                 position[2] - bilXZ + bilYZ);
00252         switch(textureCoord)
00253         {
00254         default: glTexCoord2d(0.0f, 0.0f); break;
00255         case 1:  glTexCoord2d(1.0f, 0.0f); break;
00256         case 2:  glTexCoord2d(1.0f, 1.0f); break;
00257         case 3:  glTexCoord2d(0.0f, 1.0f); break;
00258         }
00259         glVertex3f(
00260                 position[0] - bilXX - bilYX, 
00261                 position[1] - bilXY - bilYY, 
00262                 position[2] - bilXZ - bilYZ);
00263         switch(textureCoord)
00264         {
00265         default: glTexCoord2d(1.0f, 0.0f); break;
00266         case 1:  glTexCoord2d(1.0f, 1.0f); break;
00267         case 2:  glTexCoord2d(0.0f, 1.0f); break;
00268         case 3:  glTexCoord2d(0.0f, 0.0f); break;
00269         }
00270         glVertex3f(
00271                 position[0] + bilXX - bilYX, 
00272                 position[1] + bilXY - bilYY, 
00273                 position[2] + bilXZ - bilYZ);
00274         glEnd();
00275 
00276         if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00277 }
00278 

Generated on Mon Feb 16 15:14:38 2009 for Scorched3D by  doxygen 1.5.3