gKitGL
|
00001 00002 #ifndef _GK_CAMERA_H 00003 #define _GK_CAMERA_H 00004 00005 #include "Transform.h" 00006 #include "IOFileSystem.h" 00007 00008 namespace gk { 00009 00010 //! camera generique. 00011 class Camera 00012 { 00013 protected: 00014 Transform m_view; 00015 Transform m_projection; 00016 Transform m_viewport; 00017 00018 float m_width; 00019 float m_height; 00020 00021 public: 00022 //! renvoie la position de l'origine. 00023 Point origin( ) const 00024 { 00025 return m_view.inverse( Point(0.f, 0.f, 0.f) ); 00026 } 00027 00028 //! renvoie le vecteur 'vers le haut'. 00029 Vector up( ) const // Y 00030 { 00031 return m_view.inverse( Vector(0.f, 1.f, 0.f) ); 00032 } 00033 00034 //! renvoie le vecteur 'vers la droite'. 00035 Vector right( ) const // X 00036 { 00037 return m_view.inverse( Vector(1.f, 0.f, 0.f) ); 00038 } 00039 00040 //! renvoie le vecteur 'devant'. 00041 Vector forward( ) const // Z 00042 { 00043 return m_view.inverse( Vector(0.f, 0.f, 1.f) ); 00044 } 00045 00046 public: 00047 //! constructeur par defaut. 00048 Camera( ) 00049 : 00050 m_view(), 00051 m_projection(), 00052 m_viewport( Viewport(100.f, 100.f) ), 00053 m_width(100.f), 00054 m_height(100.f) 00055 {} 00056 00057 //! constructeur, definit la projection utilisee par la camera. 00058 Camera( const Transform& projection, const int width= 100, const int height= 100 ) 00059 : 00060 m_view(), 00061 m_projection(projection), 00062 m_viewport( Viewport(width, height) ), 00063 m_width(width), 00064 m_height(height) 00065 {} 00066 00067 //! destructeur. 00068 ~Camera() {} 00069 00070 //! modifie le viewport de la camera. 00071 void setViewport( const int width, const int height ) 00072 { 00073 m_width= width; 00074 m_height= height; 00075 m_viewport= Viewport(width, height); 00076 } 00077 00078 //! modifie le viewport de la camera. 00079 void setViewport( int viewport[4] ) 00080 { 00081 m_width= viewport[2]; 00082 m_height= viewport[3]; 00083 m_viewport= Viewport(viewport[2], viewport[3]); 00084 } 00085 00086 //! modifie la projection de la camera. 00087 void setProjection( const Transform& projection ) 00088 { 00089 m_projection= projection; 00090 } 00091 00092 //! renvoie la transformation de projection de la camera. 00093 const Transform& projection( ) 00094 { 00095 return m_projection; 00096 } 00097 00098 //! renvoie la transforamtion view de la camera. 00099 const Transform& view( ) 00100 { 00101 return m_view; 00102 } 00103 00104 //! renvoie la transformation viewport. 00105 const Transform& viewport( ) 00106 { 00107 return m_viewport; 00108 } 00109 00110 //! renvoie la largeur du viewport 00111 float width( ) 00112 { 00113 return m_width; 00114 } 00115 00116 //! renvoie la hauteur du viewport 00117 float height( ) 00118 { 00119 return m_height; 00120 } 00121 }; 00122 00123 //! camera perspective. 00124 class PerspectiveCamera : public gk::Camera 00125 { 00126 public: 00127 //! constructeur par defaut. 00128 PerspectiveCamera( ) 00129 : 00130 gk::Camera() 00131 {} 00132 00133 //! constructeur, parametre la projection perspective, cf gk::Perspective(). 00134 PerspectiveCamera( const float fov, const float aspect, const float znear, const float zfar, const int width= 100, const int height= 100 ) 00135 : 00136 Camera( Perspective(fov, aspect, znear, zfar), width, height) 00137 {} 00138 00139 //! constructeur, parametre la projection perspective, cf gk::Perspective(). 00140 PerspectiveCamera( const Transform& projection, const int width= 100, const int height= 100 ) 00141 : 00142 Camera(projection, width, height) 00143 {} 00144 00145 float znear( ) const 00146 { 00147 gk::Point p= m_projection.inverse( gk::Point(.0f, .0f, -1.f) ); 00148 return -p.z; 00149 } 00150 00151 float zfar( ) const 00152 { 00153 gk::Point p= m_projection.inverse( gk::Point(.0f, .0f, 1.f) ); 00154 return -p.z; 00155 } 00156 00157 //! destructeur. 00158 ~PerspectiveCamera( ) {} 00159 }; 00160 00161 //! camera first person. 00162 class FirstPersonCamera : public PerspectiveCamera 00163 { 00164 protected: 00165 Point m_position; 00166 float m_rotation_x; 00167 float m_rotation_y; 00168 float m_rotation_z; 00169 float m_speed; 00170 00171 public: 00172 FirstPersonCamera( ) 00173 : 00174 PerspectiveCamera(), 00175 m_position(), 00176 m_rotation_x(0.f), 00177 m_rotation_y(0.f), 00178 m_rotation_z(0.f), 00179 m_speed(1.f) 00180 {} 00181 00182 //! constructeur, parametre la projection perspective, cf gk::Perspective(). 00183 FirstPersonCamera( const float fov, const float aspect, const float znear, const float zfar, const int width= 100, const int height= 100 ) 00184 : 00185 PerspectiveCamera(fov, aspect, znear, zfar, width, height), 00186 m_position(), 00187 m_rotation_x(0.f), 00188 m_rotation_y(0.f), 00189 m_rotation_z(0.f), 00190 m_speed(1.f) 00191 {} 00192 00193 FirstPersonCamera( const Transform& projection, const int width= 100, const int height= 100 ) 00194 : 00195 PerspectiveCamera(projection, width, height), 00196 m_position(), 00197 m_rotation_x(0.f), 00198 m_rotation_y(0.f), 00199 m_rotation_z(0.f), 00200 m_speed(1.f) 00201 {} 00202 00203 ~FirstPersonCamera( ) {} 00204 00205 //! definit la 'vitesse' de deplacement == l'amplitude des deplacements. 00206 void setSpeed( const float v ) 00207 { 00208 m_speed= v; 00209 } 00210 00211 //! renvoie la 'vitesse' de deplacement == l'amplitude des deplacements. 00212 float speed( ) const 00213 { 00214 return m_speed; 00215 } 00216 00217 //! deplace l'objet, vers l'avant, +Z. 00218 void moveForward( const float v ) 00219 { 00220 m_position= m_position + forward() * v * m_speed; 00221 } 00222 00223 //! deplace l'objet, vers la droite, +X. 00224 void moveRight( const float v ) 00225 { 00226 m_position= m_position + right() * v * m_speed; 00227 } 00228 00229 //! deplace l'objet, en haut, +Y. 00230 void moveUp( const float v ) 00231 { 00232 m_position= m_position + up() * v * m_speed; 00233 } 00234 00235 //! repositionne l'objet. 00236 void move( const Point& p ) 00237 { 00238 m_position= p; 00239 } 00240 00241 //! rotation gauche-droite (autour de up / Y local). 00242 void rotateUp( const float v ) 00243 { 00244 m_rotation_y+= v; 00245 } 00246 00247 //! rotation haut-bas (autour de right / X local). 00248 void rotateRight( const float v ) 00249 { 00250 m_rotation_x+= v; 00251 } 00252 00253 //! rotation autour de l'axe optique (forward / Z). 00254 void rotateForward( const float v ) 00255 { 00256 m_rotation_z+= v; 00257 } 00258 00259 //! renvoie la 'position' de la camera. 00260 const Point& position( ) 00261 { 00262 return m_position; 00263 } 00264 00265 //! renvoie la transformation view de la camera. 00266 const Transform& view( ) 00267 { 00268 m_view= (Translate( Vector(m_position) ) * RotateZ(m_rotation_z) * RotateX(m_rotation_x) * RotateY(m_rotation_y)).getInverse(); 00269 return m_view; 00270 } 00271 00272 //! enregistre la description de la camera dans un fichier. 00273 int read( const std::string& filename ) 00274 { 00275 std::string pref= gk::IOFileSystem::changeType(filename, ".gkcamera"); 00276 #ifdef VERBOSE 00277 printf("loading camera prefs '%s'...\n", pref.c_str()); 00278 #endif 00279 00280 FILE *in= fopen(pref.c_str(), "rt"); 00281 if(in == NULL) 00282 { 00283 #ifdef VERBOSE 00284 printf("failed.\n"); 00285 #endif 00286 return -1; 00287 } 00288 00289 float x, y, z; 00290 float speed; 00291 float angle1, angle2, angle3; 00292 if(fscanf(in, "x %f y %f z %f v %f a %f b %f c %f", 00293 &x, &y, &z, 00294 &speed, 00295 &angle1, &angle2, &angle3) == 7) 00296 { 00297 #ifdef VERBOSE // _DEBUG 00298 printf("camera %f %f %f, rotate %f %f %f, speed %f\n", 00299 x, y, z, angle1, angle2, angle3, speed); 00300 #endif 00301 00302 m_position= Point(x, y, z); 00303 m_rotation_y= angle1; 00304 m_rotation_x= angle2; 00305 m_rotation_z= angle3; 00306 m_speed= speed; 00307 00308 #ifdef VERBOSE 00309 printf("done.\n"); 00310 #endif 00311 fclose(in); 00312 return 0; 00313 } 00314 00315 #ifdef VERBOSE 00316 printf("failed.\n"); 00317 #endif 00318 fclose(in); 00319 return -1; 00320 } 00321 00322 //! recharge une description de camera depuis un fichier. 00323 int write( const std::string& filename ) 00324 { 00325 std::string pref= gk::IOFileSystem::changeType(filename, ".gkcamera"); 00326 #ifdef VERBOSE 00327 printf("writing camera prefs '%s'...\n", pref.c_str()); 00328 #endif 00329 00330 FILE *out= fopen(pref.c_str(), "wt"); 00331 if(out == NULL) 00332 { 00333 #ifdef VERBOSE 00334 printf("failed.\n"); 00335 #endif 00336 return -1; 00337 } 00338 00339 if(fprintf(out, "x %f y %f z %f v %f a %f b %f c %f", 00340 m_position.x, m_position.y, m_position.z, 00341 m_speed, 00342 m_rotation_y, m_rotation_x, m_rotation_z) < 0) 00343 { 00344 #ifdef VERBOSE 00345 printf("failed.\n"); 00346 #endif 00347 fclose(out); 00348 return -1; 00349 } 00350 00351 fclose(out); 00352 00353 // 2ieme format 00354 pref= gk::IOFileSystem::changeType(filename, ".camera"); 00355 #ifdef VERBOSE 00356 printf("writing camera prefs '%s'...\n", pref.c_str()); 00357 #endif 00358 00359 out= fopen(pref.c_str(), "wt"); 00360 if(out == NULL) 00361 { 00362 #ifdef VERBOSE 00363 printf("failed.\n"); 00364 #endif 00365 return -1; 00366 } 00367 00368 Point p= position(); 00369 Vector f= forward(); 00370 Vector u= up(); 00371 00372 if(fprintf(out, "camera position(%f %f %f) forward(%f %f %f) up(%f %f %f) fov(%f)", 00373 p.x, p.y, p.z, 00374 f.x, f.y, f.z, 00375 u.x, u.y, u.z, 50.f) < 0) 00376 { 00377 #ifdef VERBOSE 00378 printf("failed.\n"); 00379 #endif 00380 fclose(out); 00381 return -1; 00382 } 00383 00384 fclose(out); 00385 return 0; 00386 } 00387 }; 00388 00389 00390 //! camera orthographique. 00391 class OrthographicCamera : public gk::Camera 00392 { 00393 public: 00394 //! constructeur par defaut. 00395 OrthographicCamera( ) 00396 : 00397 gk::Camera() 00398 {} 00399 00400 //! constructeur, parametre la projection orthographique, cf gk::Orthographic(). 00401 OrthographicCamera( const float znear, const float zfar, const int width= 100, const int height= 100 ) 00402 : 00403 Camera( Orthographic(znear, zfar), width, height ) 00404 {} 00405 00406 //! destructeur. 00407 ~OrthographicCamera( ) {} 00408 }; 00409 00410 } 00411 00412 #endif