/* 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 "plane.h" #include "vector.h" #include "types.h" #include "glincl.h" #include #define MAX_CLIP_DISTANCE 800.0f #define m( _col, _row ) _m[_row*4+_col] #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].distancePoint( _box.vertexP( planes[i].n ) ) < 0 ) return OUTSIDE; // is the negative vertex outside? else if ( planes[i].distancePoint( _box.vertexN( planes[i].n ) ) < 0 ) result = INTERSECT; } return result; } inline int pointInFrustum( const Vector& _point) { int result = INSIDE; for(int i=0; i < 6; i++) { if (planes[i].distancePoint( _point ) < 0) return OUTSIDE; } return result; } inline Plane getPlane( int _plane ) { return planes[_plane]; } inline void setFrustum( float *_m ) { planes[NEAR] = Plane( Vector( m(2,0) + m(3,0), m(2,1) + m(3,1), m(2,2) + m(3,2) ), m(2,3) + m(3,3) ); planes[FAR] = Plane( Vector( -m(2,0) + m(3,0), -m(2,1) + m(3,1), -m(2,2) + m(3,2) ), -m(2,3) + m(3,3) ); planes[BOTTOM] = Plane( Vector( m(1,0) + m(3,0), m(1,1) + m(3,1), m(1,2) + m(3,2) ), m(1,3) + m(3,3) ); planes[TOP] = Plane( Vector( -m(1,0) + m(3,0), -m(1,1) + m(3,1), -m(1,2) + m(3,2) ), -m(1,3) + m(3,3) ); planes[LEFT] = Plane( Vector( m(0,0) + m(3,0), m(0,1) + m(3,1), m(0,2) + m(3,2) ), m(0,3) + m(3,3) ); planes[RIGHT] = Plane( Vector( -m(0,0) + m(3,0), -m(0,1) + m(3,1), -m(0,2) + m(3,2) ), -m(0,3) + m(3,3) ); if ( planes[NEAR].k +planes[FAR].k > MAX_CLIP_DISTANCE ) { planes[FAR].k = -planes[NEAR].k+MAX_CLIP_DISTANCE; } } protected: Plane *planes; }; #endif