Back to index

extremetuxracer  0.5beta
viewfrustum.cpp
Go to the documentation of this file.
00001 /* 
00002  * PPRacer 
00003  * Copyright (C) 2004-2005 Volker Stroebel <volker@planetpenguin.de>
00004  *
00005  * Copyright (C) 1999-2001 Jasmin F. Patry
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020  */
00021 
00022 #include "viewfrustum.h"
00023 #include "game_config.h"
00024 
00025 #include "ppgltk/alg/defs.h"
00026 
00027 #define DOT_PRODUCT( v1, v2 ) ((double) (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z))
00028 
00029 
00030 static pp::Plane frustum_planes[6];
00031 
00032 /* This will be used as a bitfield to select the "n" and "p" vertices
00033 of the bounding boxes wrt to each plane.  
00034 */
00035 
00036 //static char p_vertex_code[6];
00037 static bool p_vertex_code_x[6];
00038 static bool p_vertex_code_y[6];
00039 static bool p_vertex_code_z[6];
00040 
00041 
00042 void setup_view_frustum( Player& plyr, double near_dist, 
00043                       double far_dist )
00044 {
00045     double aspect = (double) getparam_x_resolution() /
00046        getparam_y_resolution();
00047 
00048     int i;
00049     pp::Vec3d pt;
00050     pp::Vec3d origin(0., 0., 0.);
00051     double half_fov = ANGLES_TO_RADIANS( getparam_fov() * 0.5 );
00052     double half_fov_horiz = atan( tan( half_fov ) * aspect ); 
00053 
00054 
00055     /* create frustum in viewing coordinates */
00056 
00057     /* near */
00058     frustum_planes[0] = pp::Plane(0, 0, 1, near_dist);
00059     
00060     /* far */
00061     frustum_planes[1] = pp::Plane(0, 0, -1, -far_dist);
00062 
00063     /* left */
00064     frustum_planes[2] = pp::Plane( -cos(half_fov_horiz), 0, 
00065                                 sin(half_fov_horiz), 0 );
00066 
00067     /* right */
00068     frustum_planes[3] = pp::Plane( cos(half_fov_horiz), 0, 
00069                                 sin(half_fov_horiz), 0 );
00070 
00071     /* top */
00072     frustum_planes[4] = pp::Plane( 0, cos(half_fov),  
00073                                 sin(half_fov), 0 );
00074 
00075     /* bottom */
00076     frustum_planes[5] = pp::Plane( 0, -cos(half_fov),  
00077                                 sin(half_fov), 0 );
00078 
00079 
00080     /* We now transform frustum to world coordinates */
00081     for (i=0; i<6; i++) {
00082        pt = plyr.view.inv_view_mat.transformPoint(
00083            origin + (-frustum_planes[i].d*frustum_planes[i].nml) );
00084 
00085        frustum_planes[i].nml = plyr.view.inv_view_mat.transformVector( frustum_planes[i].nml );
00086 
00087        frustum_planes[i].d = -( 
00088            frustum_planes[i].nml*
00089            (pt-origin));
00090     }
00091 
00092     for (i=0; i<6; i++) {
00093               p_vertex_code_x[i] = false;
00094               p_vertex_code_y[i] = false;
00095               p_vertex_code_z[i] = false;
00096               
00097               
00098        if ( frustum_planes[i].nml.x > 0 ) {
00099               p_vertex_code_x[i] = true;
00100        }
00101        if ( frustum_planes[i].nml.y > 0 ) {
00102               p_vertex_code_y[i] = true;
00103        }
00104        if ( frustum_planes[i].nml.z > 0 ) {
00105               p_vertex_code_z[i] = true;
00106        }
00107 
00108        
00109     }
00110 }
00111 
00115 clip_result_t clip_aabb_to_view_frustum( const pp::Vec3d& min, const pp::Vec3d& max )
00116 {
00117     pp::Vec3d n, p;
00118     clip_result_t intersect = NoClip;
00119 
00120     for (int i=5; i>=0; i--) {
00121               p = min;
00122               n = max;
00123               
00124               if ( p_vertex_code_x[i]) {
00125                   p.x = max.x;
00126                   n.x = min.x;
00127               }
00128 
00129               if ( p_vertex_code_y[i]) {
00130                   p.y = max.y;
00131                   n.y = min.y;
00132               }
00133 
00134               if ( p_vertex_code_z[i]) {
00135                   p.z = max.z;
00136                   n.z = min.z;
00137               }
00138 
00139               if ( DOT_PRODUCT( n, frustum_planes[i].nml ) +
00140                    frustum_planes[i].d > 0 )
00141               {
00142                   return NotVisible;
00143               }
00144 
00145               if ( DOT_PRODUCT( p, frustum_planes[i].nml ) +
00146                    frustum_planes[i].d > 0 )
00147               {
00148                      intersect = SomeClip;
00149               }
00150 
00151     }  
00152     return intersect;
00153 }
00154 
00155 pp::Plane get_far_clip_plane()
00156 {
00157     return frustum_planes[1];
00158 }
00159 
00160 pp::Plane get_left_clip_plane()
00161 {
00162     return frustum_planes[2];
00163 }
00164 
00165 pp::Plane get_right_clip_plane()
00166 {
00167     return frustum_planes[3];
00168 }
00169 
00170 pp::Plane get_bottom_clip_plane()
00171 {
00172     return frustum_planes[5];
00173 }