//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2003 // // This file is part of Scorched3D. // // Scorched3D is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // Scorched3D is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// #include #include #include #include Vector GLCameraFrustum::FrustrumRed(1.0f, 0.0f, 0.0f); Vector GLCameraFrustum::FrustrumBlue(0.0f, 0.0f, 1.0f); Vector GLCameraFrustum::FrustrumGreen(0.0f, 1.0f, 0.0f); Vector GLCameraFrustum::FrustrumWhite(1.0f, 1.0f, 1.0f); GLCameraFrustum *GLCameraFrustum::instance_ = 0; GLCameraFrustum *GLCameraFrustum::instance() { if (!instance_) { instance_ = new GLCameraFrustum; } return instance_; } GLCameraFrustum::GLCameraFrustum() : GameStateI("GLCameraFrustum") { } GLCameraFrustum::~GLCameraFrustum() { } void GLCameraFrustum::normalize(float vector[4]) { float fT = (float) sqrt( vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]); vector[0] /= fT; vector[1] /= fT; vector[2] /= fT; vector[3] /= fT; } Vector &GLCameraFrustum::getBilboardVectorX() { static Vector bil; bil[0] = s.fClip[0]; bil[1] = s.fClip[4]; bil[2] = s.fClip[8]; return bil; } Vector &GLCameraFrustum::getBilboardVectorY() { static Vector bil; bil[0] = s.fClip[1]; bil[1] = s.fClip[5]; bil[2] = s.fClip[9]; bil /= s.aspect; return bil; } void GLCameraFrustum::draw(const unsigned state) { // Get the current projection matrix from OpenGL // Get the current modelview matrix from OpenGL glGetFloatv(GL_PROJECTION_MATRIX, s.fProj); glGetFloatv(GL_MODELVIEW_MATRIX, s.fView); glGetFloatv(GL_VIEWPORT, s.viewport); s.aspect = s.viewport[2] / s.viewport[3]; // Concenate the two matrices 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]; 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]; 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]; 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]; 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]; 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]; 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]; 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]; 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]; 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]; 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]; 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]; 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]; 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]; 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]; 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]; // Extract the right plane s.frustum_[0][0] = s.fClip[ 3] - s.fClip[ 0]; s.frustum_[0][1] = s.fClip[ 7] - s.fClip[ 4]; s.frustum_[0][2] = s.fClip[11] - s.fClip[ 8]; s.frustum_[0][3] = s.fClip[15] - s.fClip[12]; normalize(s.frustum_[0]); // Extract the left plane s.frustum_[1][0] = s.fClip[ 3] + s.fClip[ 0]; s.frustum_[1][1] = s.fClip[ 7] + s.fClip[ 4]; s.frustum_[1][2] = s.fClip[11] + s.fClip[ 8]; s.frustum_[1][3] = s.fClip[15] + s.fClip[12]; normalize(s.frustum_[1]); // Extract the bottom plane s.frustum_[2][0] = s.fClip[ 3] + s.fClip[ 1]; s.frustum_[2][1] = s.fClip[ 7] + s.fClip[ 5]; s.frustum_[2][2] = s.fClip[11] + s.fClip[ 9]; s.frustum_[2][3] = s.fClip[15] + s.fClip[13]; normalize(s.frustum_[2]); // Extract the top plane s.frustum_[3][0] = s.fClip[ 3] - s.fClip[ 1]; s.frustum_[3][1] = s.fClip[ 7] - s.fClip[ 5]; s.frustum_[3][2] = s.fClip[11] - s.fClip[ 9]; s.frustum_[3][3] = s.fClip[15] - s.fClip[13]; normalize(s.frustum_[3]); // Extract the far plane s.frustum_[4][0] = s.fClip[ 3] - s.fClip[ 2]; s.frustum_[4][1] = s.fClip[ 7] - s.fClip[ 6]; s.frustum_[4][2] = s.fClip[11] - s.fClip[10]; s.frustum_[4][3] = s.fClip[15] - s.fClip[14]; normalize(s.frustum_[4]); // Extract the near plane s.frustum_[5][0] = s.fClip[ 3] + s.fClip[ 2]; s.frustum_[5][1] = s.fClip[ 7] + s.fClip[ 6]; s.frustum_[5][2] = s.fClip[11] + s.fClip[10]; s.frustum_[5][3] = s.fClip[15] + s.fClip[14]; normalize(s.frustum_[5]); } bool GLCameraFrustum::sphereInFrustum(Vector &point, float fRadius, Vector &color) { if (OptionsDisplay::instance()->getDrawBoundingSpheres()) { static GLUquadric *obj = 0; if (!obj) { obj = gluNewQuadric(); gluQuadricDrawStyle(obj, GLU_LINE); } GLState glState(GLState::TEXTURE_OFF); glColor3fv(color); glPushMatrix(); glTranslatef(point[0], point[1], point[2]); gluSphere(obj, fRadius, 6, 6); glPopMatrix(); } for (int iCurPlane = 0; iCurPlane<6; iCurPlane++) { float value = s.frustum_[iCurPlane][0] * point[0] + s.frustum_[iCurPlane][1] * point[1] + s.frustum_[iCurPlane][2] * point[2] + s.frustum_[iCurPlane][3]; if (value <= -fRadius) { return false; } } return true; } void GLCameraFrustum::backupFrustum() { memcpy(&b, &s, sizeof(b)); } void GLCameraFrustum::restoreFrustum() { memcpy(&s, &b, sizeof(b)); } void GLCameraFrustum::drawBilboard(Vector &position, Vector &color, float alpha, float width, float height, bool additive, int textureCoord) { if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE); Vector &bilX = getBilboardVectorX(); Vector &bilY = getBilboardVectorY(); float bilXX = bilX[0] * width; float bilXY = bilX[1] * width; float bilXZ = bilX[2] * width; float bilYX = bilY[0] * height; float bilYY = bilY[1] * height; float bilYZ = bilY[2] * height; glColor4f(color[0], color[1], color[2], alpha); glBegin(GL_QUADS); switch(textureCoord) { default: glTexCoord2d(1.0f, 1.0f); break; case 1: glTexCoord2d(0.0f, 1.0f); break; case 2: glTexCoord2d(0.0f, 0.0f); break; case 3: glTexCoord2d(1.0f, 0.0f); break; } glVertex3f( position[0] + bilXX + bilYX, position[1] + bilXY + bilYY, position[2] + bilXZ + bilYZ); switch(textureCoord) { default: glTexCoord2d(0.0f, 1.0f); break; case 1: glTexCoord2d(0.0f, 0.0f); break; case 2: glTexCoord2d(1.0f, 0.0f); break; case 3: glTexCoord2d(1.0f, 1.0f); break; } glVertex3f( position[0] - bilXX + bilYX, position[1] - bilXY + bilYY, position[2] - bilXZ + bilYZ); switch(textureCoord) { default: glTexCoord2d(0.0f, 0.0f); break; case 1: glTexCoord2d(1.0f, 0.0f); break; case 2: glTexCoord2d(1.0f, 1.0f); break; case 3: glTexCoord2d(0.0f, 1.0f); break; } glVertex3f( position[0] - bilXX - bilYX, position[1] - bilXY - bilYY, position[2] - bilXZ - bilYZ); switch(textureCoord) { default: glTexCoord2d(1.0f, 0.0f); break; case 1: glTexCoord2d(1.0f, 1.0f); break; case 2: glTexCoord2d(0.0f, 1.0f); break; case 3: glTexCoord2d(0.0f, 0.0f); break; } glVertex3f( position[0] + bilXX - bilYX, position[1] + bilXY - bilYY, position[2] + bilXZ - bilYZ); glEnd(); if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }