/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2006 orx This program 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, or (at your option) any later version. ### File Specific: main programmer: Marco Biasini */ #ifndef _FRUSTUM_H #define _FRUSTUM_H #include "types.h" #include "glincl.h" #include #define MAX_CLIP_DISTANCE 400.0f #define m( _row,_col ) _m[_col*4+_row-5] #define CHECK_GL_ERROR( _d ) do { \ GLenum __err = glGetError(); \ if ( __err != GL_NO_ERROR ) \ printf( "check%s: %s\n", _d, (char*)gluErrorString( __err ) );\ }\ while ( 0 ) /** * Code borrowed from Lighthouse 3D. Its a very good tutorial on culling. */ class Frustum; typedef Frustum *pFrustum; class Frustum { public: enum { NEAR = 0 , FAR = 1, TOP = 2, BOTTOM = 3, LEFT = 4, RIGHT = 5 }; enum { OUTSIDE, INTERSECT, INSIDE }; Frustum() { planes = new Plane[6]; } ~Frustum() { if ( planes ) delete[] planes; } /** * Extracts the frustum planes from the GL_PROJECTION and GL_MODELVIEW * matrices... */ inline void extractPlanes() { float proj[16], view[16], combined[16]; glGetFloatv( GL_MODELVIEW_MATRIX, view ); glGetFloatv( GL_PROJECTION_MATRIX, proj ); multMat( combined, view, proj ); setFrustum( combined ); } inline int boxInFrustum( const ABox& _box ) { int result = INSIDE; //for each plane do ... for( int i = 0; i < 6; ++i ) { // is the positive vertex outside? if ( planes[i].distance( _box.vertexP( planes[i].n ) ) < 0 ) return OUTSIDE; // is the negative vertex outside? else if ( planes[i].distance( _box.vertexN( planes[i].n ) ) < 0 ) result = INTERSECT; } return result; } inline int pointInFrustum( const Triple& _point) { int result = INSIDE; for(int i=0; i < 6; i++) { if (planes[i].distance( _point ) < 0) return OUTSIDE; } return result; } inline Plane getPlane( int _plane ) { return planes[_plane]; } inline void setFrustum( float *_m ) { planes[NEAR].setCoefficients( m( 3, 1 ) + m( 4, 1 ), m( 3, 2 ) + m( 4, 2 ), m( 3, 3 ) + m( 4, 3 ), m( 3, 4 ) + m( 4, 4 ) ); planes[FAR].setCoefficients( -m( 3, 1 ) + m( 4, 1 ), -m( 3, 2 ) + m( 4, 2 ), -m( 3, 3 ) + m( 4, 3 ), -m( 3, 4 ) + m( 4, 4 ) ); planes[BOTTOM].setCoefficients( m( 2, 1 ) + m( 4, 1 ), m( 2, 2 ) + m( 4, 2 ), m( 2, 3 ) + m( 4, 3 ), m( 2, 4 ) + m( 4, 4 ) ); planes[TOP].setCoefficients( -m( 2, 1 ) + m( 4, 1 ), -m( 2, 2 ) + m( 4, 2 ), -m( 2, 3 ) + m( 4, 3 ), -m( 2, 4 ) + m( 4, 4 ) ); planes[LEFT].setCoefficients( m( 1, 1 ) + m( 4, 1 ), m( 1, 2 ) + m( 4, 2 ), m( 1, 3 ) + m( 4, 3 ), m( 1, 4 ) + m( 4, 4 ) ); planes[RIGHT].setCoefficients( -m( 1, 1 ) + m( 4, 1 ), -m( 1, 2 ) + m( 4, 2 ), -m( 1, 3 ) + m( 4, 3 ), -m( 1, 4 ) + m( 4, 4 ) ); if ( planes[NEAR].d +planes[FAR].d > MAX_CLIP_DISTANCE ) { planes[FAR].d = -planes[NEAR].d+MAX_CLIP_DISTANCE; } } protected: Plane *planes; }; #endif