/* GL-117 Copyright 2001, 2002 Thomas A. Drexl aka heptargon This file is part of GL-117. GL-117 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. GL-117 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 GL-117; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This file includes a collection of GL features. */ #ifndef IS_GL_H #include #include #include #include #include "gl.h" /**************************************************************************** OpenGL ****************************************************************************/ GL::GL () { antialiasing = false; zbuffer = false; alphablending = false; shading = 0; gllistnr = 0; gllightnr = 0; texnum = -1; aktlist = 0; fogcolor [0] = 0.5; fogcolor [1] = 0.5; fogcolor [2] = 0.5; foglum = 1.0; } GL::~GL () { } void GL::clearScreen () { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void GL::drawScreen () { glutSwapBuffers (); } void GL::rotate (int x, int y, int z) { glRotatef (z, 0.0f, 0.0f, 1.0f); glRotatef (y, 0.0f, 1.0f, 0.0f); glRotatef (x, 1.0f, 0.0f, 0.0f); } GLuint GL::genListSphere (GLint slices, GLint stacks, float radius) { GLUquadricObj *quadObj; quadObj = gluNewQuadric (); glNewList (++ gllistnr, GL_COMPILE); gluSphere (quadObj, radius, slices, stacks); glEndList (); return gllistnr; } void GL::setList (GLuint listnr) { glCallList (listnr); } void GL::genList (int *list) { *list = ++ aktlist; glNewList (aktlist, GL_COMPILE_AND_EXECUTE); } int GL::genTexture () { return 1; } void GL::enableLinearTexture (int texnum) { glBindTexture (GL_TEXTURE_2D, texnum); if (!tex [texnum]->mipmap) glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); else glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } void GL::disableLinearTexture (int texnum) { glBindTexture (GL_TEXTURE_2D, texnum); if (!tex [texnum]->mipmap) glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); else glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } CTexture *GL::getTextureTGA (char *fname) { int i; for (i = 0; i <= texnum; i ++) { if (!strcmp (fname, tex [i]->name)) break; } if (i <= texnum) return tex [i]; return NULL; } CTexture *GL::genTextureTGA (char *fname, int quality, int alphatype, int mipmap2, bool alpha) { char buf [STDSIZE]; CTexture *mytex; if ((mytex = getTextureTGA (fname)) != NULL) { return mytex; } texnum ++; glBindTexture (GL_TEXTURE_2D, texnum); tex [texnum] = new CTexture (); if (!tex [texnum]->loadFromTGA (fname, quality, alphatype, mipmap2)) { sprintf (buf, "Texture %s not found", fname); display (buf, LOG_ERROR); // exit (EXIT_LOADFILE); // If texture cannot be loaded, allocate dummy tex buffer tex [texnum]->width = 8; tex [texnum]->height = 8; int buflen = tex [texnum]->width * tex [texnum]->height * 4; tex [texnum]->data = (unsigned char *) malloc (buflen); if (tex [texnum] == NULL) error_outofmemory (); memset (tex [texnum]->data, 0, buflen); } tex [texnum]->alpha = alpha; tex [texnum]->textureID = texnum; if (!antialiasing) disableLinearTexture (texnum); else enableLinearTexture (texnum); if (!mipmap2) glTexImage2D (GL_TEXTURE_2D, 0, 4, tex [texnum]->width, tex [texnum]->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex [texnum]->data); else gluBuild2DMipmaps (GL_TEXTURE_2D, 4, tex [texnum]->width, tex [texnum]->height, GL_RGBA, GL_UNSIGNED_BYTE, tex [texnum]->data); return tex [texnum]; } float GL::getTexLight () { return tex [akttex]->texlight; } void GL::enableAntiAliasing () { glEnable (GL_LINE_SMOOTH); glEnable (GL_POINT_SMOOTH); glEnable (GL_POLYGON_SMOOTH); glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST); glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST); glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST); antialiasing = true; } void GL::disableAntiAliasing () { glDisable (GL_LINE_SMOOTH); glDisable (GL_POINT_SMOOTH); glDisable (GL_POLYGON_SMOOTH); antialiasing = false; } void GL::enableAlphaBlending () { glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); alphablending = true; } void GL::disableAlphaBlending () { glDisable (GL_BLEND); alphablending = false; } void GL::enableTextures (int num) { akttex = num; glBindTexture (GL_TEXTURE_2D, num); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); /* GL_CLAMP or GL_REPEAT? */ glEnable (GL_TEXTURE_2D); } void GL::enableLighting () { glEnable (GL_LIGHTING); } void GL::enableZBuffer () { glEnable (GL_DEPTH_TEST); glDepthFunc (GL_LEQUAL); glDepthRange (10.0, -10.0); zbuffer = true; } void GL::disableZBuffer () { glDisable (GL_DEPTH_TEST); zbuffer = false; } void GL::shadeFlat () { glShadeModel (GL_FLAT); shading = 1; } void GL::shadeSmooth () { glShadeModel (GL_SMOOTH); shading = 2; } void GL::enableFog (float view) { float fcol [3]; fcol [0] = fogcolor [0] * foglum; fcol [1] = fogcolor [1] * foglum; fcol [2] = fogcolor [2] * foglum; glEnable (GL_FOG); glFogfv (GL_FOG_COLOR, fcol); glFogf (GL_FOG_DENSITY, 0.1); glFogi (GL_FOG_MODE, GL_LINEAR); // possible alternatives: // glFogf (GL_FOG_DENSITY, 0.017 * 100 / view); // glFogi (GL_FOG_MODE, GL_EXP2); if (quality <= 5) glHint (GL_FOG_HINT, GL_FASTEST); else glHint (GL_FOG_HINT, GL_NICEST); glFogf (GL_FOG_START, 1.0 * GLOBALSCALE); glFogf (GL_FOG_END, view * GLOBALSCALE); } // Frustum Culling according to OpenGL Page void GL::extractFrustum() { float proj[16]; float modl[16]; float clip[16]; float t; // extract transformation matrices glGetFloatv( GL_PROJECTION_MATRIX, proj ); glGetFloatv( GL_MODELVIEW_MATRIX, modl ); clip[0] = modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12]; clip[1] = modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13]; clip[2] = modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14]; clip[3] = modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15]; clip[4] = modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12]; clip[5] = modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13]; clip[6] = modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14]; clip[7] = modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15]; clip[8] = modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12]; clip[9] = modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13]; clip[10] = modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14]; clip[11] = modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15]; clip[12] = modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12]; clip[13] = modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13]; clip[14] = modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14]; clip[15] = modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15]; // extract numbers for the RIGHT plane frustum[0][0] = clip[3] - clip[0]; frustum[0][1] = clip[7] - clip[4]; frustum[0][2] = clip[11] - clip[8]; frustum[0][3] = clip[15] - clip[12]; // normalize the result t = sqrt(frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2]); frustum[0][0] /= t; frustum[0][1] /= t; frustum[0][2] /= t; frustum[0][3] /= t; // extract the numbers for the LEFT plane frustum[1][0] = clip[3] + clip[0]; frustum[1][1] = clip[7] + clip[4]; frustum[1][2] = clip[11] + clip[8]; frustum[1][3] = clip[15] + clip[12]; // normalize the result t = sqrt(frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2]); frustum[1][0] /= t; frustum[1][1] /= t; frustum[1][2] /= t; frustum[1][3] /= t; // extract the BOTTOM plane frustum[2][0] = clip[3] + clip[1]; frustum[2][1] = clip[7] + clip[5]; frustum[2][2] = clip[11] + clip[9]; frustum[2][3] = clip[15] + clip[13]; // normalize the result t = sqrt(frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2]); frustum[2][0] /= t; frustum[2][1] /= t; frustum[2][2] /= t; frustum[2][3] /= t; // extract the TOP plane frustum[3][0] = clip[3] - clip[1]; frustum[3][1] = clip[7] - clip[5]; frustum[3][2] = clip[11] - clip[9]; frustum[3][3] = clip[15] - clip[13]; // normalize the result t = sqrt(frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2]); frustum[3][0] /= t; frustum[3][1] /= t; frustum[3][2] /= t; frustum[3][3] /= t; // extract the FAR plane frustum[4][0] = clip[3] - clip[2]; frustum[4][1] = clip[7] - clip[6]; frustum[4][2] = clip[11] - clip[10]; frustum[4][3] = clip[15] - clip[14]; // normalize the result t = sqrt(frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2]); frustum[4][0] /= t; frustum[4][1] /= t; frustum[4][2] /= t; frustum[4][3] /= t; // extract the NEAR plane frustum[5][0] = clip[3] + clip[2]; frustum[5][1] = clip[7] + clip[6]; frustum[5][2] = clip[11] + clip[10]; frustum[5][3] = clip[15] + clip[14]; // normalize the result t = sqrt(frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2]); frustum[5][0] /= t; frustum[5][1] /= t; frustum[5][2] /= t; frustum[5][3] /= t; } bool GL::isPointInFrustum( float x, float y, float z ) { int i; for (i = 0; i < 6; i ++) if (frustum[i][0] * x + frustum[i][1] * y + frustum[i][2] * z + frustum[i][3] <= 0) return false; return true; } bool GL::isSphereInFrustum( float x, float y, float z, float radius ) { int i; for (i = 0; i < 6; i ++) if (frustum[i][0] * x + frustum[i][1] * y + frustum[i][2] * z + frustum[i][3] <= -radius) return false; return true; } bool GL::isCubeInFrustum( float x, float y, float z, float size ) { int i; for (i = 0; i < 6; i ++) { if (frustum[i][0] * (x - size) + frustum[i][1] * (y - size) + frustum[i][2] * (z - size) + frustum[i][3] > 0) continue; if (frustum[i][0] * (x + size) + frustum[i][1] * (y - size) + frustum[i][2] * (z - size) + frustum[i][3] > 0) continue; if (frustum[i][0] * (x - size) + frustum[i][1] * (y + size) + frustum[i][2] * (z - size) + frustum[i][3] > 0) continue; if (frustum[i][0] * (x + size) + frustum[i][1] * (y + size) + frustum[i][2] * (z - size) + frustum[i][3] > 0) continue; if (frustum[i][0] * (x - size) + frustum[i][1] * (y - size) + frustum[i][2] * (z + size) + frustum[i][3] > 0) continue; if (frustum[i][0] * (x + size) + frustum[i][1] * (y - size) + frustum[i][2] * (z + size) + frustum[i][3] > 0) continue; if (frustum[i][0] * (x - size) + frustum[i][1] * (y + size) + frustum[i][2] * (z + size) + frustum[i][3] > 0) continue; if (frustum[i][0] * (x + size) + frustum[i][1] * (y + size) + frustum[i][2] * (z + size) + frustum[i][3] > 0) continue; return false; } return true; } #endif