00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "Teddy/TeddyConfig.h"
00026 #include "Teddy/Graphics/View.h"
00027 #include "Teddy/Graphics/PsRenderer.h"
00028 #include "Teddy/Models/Model.h"
00029 #include "Teddy/Models/Geometry.h"
00030 #include "Teddy/PhysicalComponents/Projection.h"
00031 #include "Teddy/Scenes/Camera.h"
00032 #include "Teddy/Scenes/Scene.h"
00033 #include "Teddy/SysSupport/Messages.h"
00034 #include "Teddy/SysSupport/StdMaths.h"
00035 using namespace Teddy::Graphics;
00036 using namespace Teddy::Models;
00037 using namespace Teddy::PhysicalComponents;
00038 using namespace Teddy::SysSupport;
00039
00040
00041 namespace Teddy {
00042 namespace Scenes {
00043
00044
00050 Camera::Camera( const std::string &name, Scene *scene )
00051 :
00052 Model ( name ),
00053 scene ( scene ),
00054 near_clip( 2 ),
00055 far_clip ( 4096 ),
00056 fov ( 80 )
00057 {
00058 for( int i=0; i<MSD; i++ ){
00059 model_view_matrix[i] = Matrix::IDENTITY;
00060 }
00061 model_view_matrix_sp = 0;
00062 active_projection = NULL;
00063 mirror_x = false;
00064 projection_dirty = true;
00065 }
00066
00067
00068 void Camera::setMirrorX( const bool mirror_x ){
00069 this->mirror_x = mirror_x;
00070 msg( M_INIT, "SetMirror %s", mirror_x?"true":"false" );
00071 }
00072
00077 void Camera::doProjection( Projection *p, const bool load_matrix ){
00078 projection_matrix = getPerspectiveMatrix( fov, p->getRatio(), near_clip, far_clip );
00079 if( mirror_x ){
00080 projection_matrix = projection_matrix * Matrix::MIRROR_X;
00081 }
00082 if( load_matrix == true ){
00083 p->setProjectionMatrix( projection_matrix );
00084 glMatrixMode( GL_MODELVIEW );
00085 }
00086 updatePlanes();
00087 }
00088
00089
00096 void Camera::doCamera( Projection *p, const bool load_matrix ){
00097
00098
00099 view_matrix = getWorldToLocalMatrix();
00100
00101 if( load_matrix == true ){
00102 p->setModelViewMatrix( view_matrix );
00103 }
00104 }
00105
00106
00107 void Camera::pushObjectMatrix(){
00108 model_view_matrix_sp++;
00109 }
00110
00111
00112 void Camera::popObjectMatrix(){
00113 model_view_matrix_sp--;
00114 }
00115
00116
00118 void Camera::doObjectMatrix( Projection *p, const Matrix &m, const bool load_matrix ){
00119 if( model_view_matrix_sp>0 ){
00120 model_view_matrix[model_view_matrix_sp] =
00121 model_view_matrix[model_view_matrix_sp-1] * m;
00122 }else{
00123 model_view_matrix[model_view_matrix_sp] = view_matrix * m;
00124 }
00125 to_screen_s_matrix = projection_matrix * model_view_matrix[model_view_matrix_sp];
00126 if( load_matrix == true ){
00127 p->setModelViewMatrix( model_view_matrix[model_view_matrix_sp] );
00128 }
00129 }
00130
00131
00133 Vector4 Camera::projectVector( const Vector4 &v ) const{
00134 return to_screen_s_matrix.transformVector4( v );
00135 }
00136
00137
00139 void Camera::projectScene( Projection *p ){
00140 View *view = p->getView();
00141 this->active_projection = p;
00142 this->rect = IntRect( p->getRect() );
00143
00144 Geometry::draw_count = 0;
00145
00146
00147
00148
00149 doProjection( p );
00150
00151
00152
00153 doCamera( p );
00154
00155
00156 scene->lock ();
00157 scene->draw ( this, p );
00158 scene->unlock();
00159 }
00160
00161
00166 Model *Camera::pick( Projection *p, const IntVector2 &pos ){
00167 Vector2 pick_pos = pos;
00168 Vector2 pick_size = Vector2( 3.0, 3.0 );
00169 projection_matrix =
00170 getPickMatrix ( pick_pos, pick_size, p->getRect() ) *
00171 getPerspectiveMatrix( fov, p->getRatio(), near_clip, far_clip );
00172 p->setProjectionMatrix( projection_matrix );
00173
00174 doCamera( p, true );
00175 return scene->pick( this, p );
00176 }
00177
00178
00179 void Camera::setNearFar( const float near_clip, const float far_clip ){
00180 this->near_clip = near_clip;
00181 this->far_clip = far_clip;
00182 }
00183
00184
00185 double Camera::getNear(){
00186 return this->near_clip;
00187 }
00188
00189
00190 double Camera::getFar(){
00191 return this->far_clip;
00192 }
00193
00194
00196 void Camera::setFov( const float fov ){
00197 this->fov = fov;
00198 }
00199
00200
00201 void Camera::modFov( const float mod ){
00202 fov += mod;
00203 }
00204
00205
00207 float Camera::getFov() const {
00208 return fov;
00209 }
00210
00211
00213 void Camera::setScene( Scene *scene ){
00214 this->scene = scene;
00215 }
00216
00217
00219 Scene *Camera::getScene() const {
00220 return scene;
00221 }
00222
00223
00225 bool Camera::cull( const Model &model ){
00226 Matrix m = model_view_matrix[model_view_matrix_sp];
00227 Vector loc = m * Vector(0,0,0);
00228 float rad = model.getClipRadius();
00229
00230 double d0 = view_plane[0].distance( loc ) + rad;
00231 double d1 = view_plane[1].distance( loc ) + rad;
00232 double d2 = view_plane[2].distance( loc ) + rad;
00233 double d3 = view_plane[3].distance( loc ) + rad;
00234 double d4 = view_plane[4].distance( loc ) + rad;
00235 double d5 = view_plane[5].distance( loc ) + rad;
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 if( d0 < 0 ) return true;
00248 if( d1 < 0 ) return true;
00249 if( d2 < 0 ) return true;
00250 if( d3 < 0 ) return true;
00251 if( d4 < 0 ) return true;
00252 if( d5 < 0 ) return true;
00253 return false;
00254 }
00255
00256
00258 Matrix Camera::getFrustumMatrix( const float left, const float right, const float bottom, const float top, const float nearval, const float farval ) const {
00259 float x, y, a, b, c, d;
00260 Matrix frustum_matrix;
00261
00262 x = (nearval + nearval) / (right - left );
00263 y = (nearval + nearval) / (top - bottom );
00264 a = (right + left ) / (right - left );
00265 b = (top + bottom ) / (top - bottom );
00266 c = -(farval + nearval) / (farval - nearval);
00267 d = -(2 * farval * nearval) / (farval - nearval);
00268
00269 # define M(row,col) frustum_matrix.m[col][row]
00270 M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0;
00271 M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0;
00272 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
00273 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
00274 # undef M
00275
00276 return frustum_matrix;
00277 }
00278
00279
00281 Matrix Camera::getPerspectiveMatrix( const float fovy, const float aspect, const float zNear, const float zFar ) const {
00282 float xmin, xmax, ymin, ymax;
00283
00284 ymax = zNear * tan( fovy * M_PI / 360.0 );
00285 ymin = -ymax;
00286 xmin = ymin * aspect;
00287 xmax = ymax * aspect;
00288
00289 return getFrustumMatrix( xmin, xmax, ymin, ymax, zNear, zFar );
00290 }
00291
00292
00294 Matrix Camera::getPickMatrix( const IntVector2 &pick_pos, const IntVector2 &pick_size, const IntRect &viewport ) const {
00295 Matrix pick_matrix;
00296
00297 Vector2 scale = viewport.getSize() / pick_size;
00298
00299
00300 Vector2 offset = viewport.min - pick_pos;
00301 Vector2 translate = (viewport.getSize() + offset + offset) / pick_size;
00302
00303
00304
00305 # define M(row,col) pick_matrix.m[col][row]
00306 M(0, 0) = scale[0];
00307 M(0, 1) = 0;
00308 M(0, 2) = 0;
00309 M(0, 3) = translate[0];
00310 M(1, 0) = 0;
00311 M(1, 1) = scale[1];
00312 M(1, 2) = 0;
00313 M(1, 3) = translate[1];
00314 M(2, 0) = 0;
00315 M(2, 1) = 0;
00316 M(2, 2) = 1;
00317 M(2, 3) = 0;
00318 M(3, 0) = 0;
00319 M(3, 1) = 0;
00320 M(3, 2) = 0;
00321 M(3, 3) = 1;
00322 # undef M
00323
00324 return pick_matrix;
00325 }
00326
00327
00329 void Camera::updatePlanes(){
00330 Matrix m = projection_matrix;
00331 m.transpose();
00332 Vector4 v1 = m.transformVector4( Vector4(-1, 0, 0, 1 ) );
00333 Vector4 v2 = m.transformVector4( Vector4( 1, 0, 0, 1 ) );
00334 Vector4 v3 = m.transformVector4( Vector4( 0,-1, 0, 1 ) );
00335 Vector4 v4 = m.transformVector4( Vector4( 0, 1, 0, 1 ) );
00336 Vector4 v5 = m.transformVector4( Vector4( 0, 0,-1, 1 ) );
00337 Vector4 v6 = m.transformVector4( Vector4( 0, 0, 1, 1 ) );
00338 v1 /= sqrt( v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2] );
00339 v2 /= sqrt( v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2] );
00340 v3 /= sqrt( v3[0] * v3[0] + v3[1] * v3[1] + v3[2] * v3[2] );
00341 v4 /= sqrt( v4[0] * v4[0] + v4[1] * v4[1] + v4[2] * v4[2] );
00342 v5 /= sqrt( v5[0] * v5[0] + v5[1] * v5[1] + v5[2] * v5[2] );
00343 v6 /= sqrt( v6[0] * v6[0] + v6[1] * v6[1] + v6[2] * v6[2] );
00344 view_plane[0] = v1;
00345 view_plane[1] = v2;
00346 view_plane[2] = v3;
00347 view_plane[3] = v4;
00348 view_plane[4] = v5;
00349 view_plane[5] = v6;
00350 }
00351
00352
00353 void Camera::updateFrustum(){
00354 float proj[16];
00355 float modl[16];
00356 float clip[16];
00357 float t;
00358
00359 glGetFloatv( GL_PROJECTION_MATRIX, proj );
00360 glGetFloatv( GL_MODELVIEW_MATRIX, modl );
00361
00362
00363 clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
00364 clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
00365 clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
00366 clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];
00367
00368 clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
00369 clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
00370 clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
00371 clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];
00372
00373 clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
00374 clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
00375 clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
00376 clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];
00377
00378 clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
00379 clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
00380 clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
00381 clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
00382
00383
00384
00385 frustum[0][0] = clip[ 3] - clip[ 0];
00386 frustum[0][1] = clip[ 7] - clip[ 4];
00387 frustum[0][2] = clip[11] - clip[ 8];
00388 frustum[0][3] = clip[15] - clip[12];
00389
00390
00391 t = (float) sqrt( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] );
00392 frustum[0][0] /= t;
00393 frustum[0][1] /= t;
00394 frustum[0][2] /= t;
00395 frustum[0][3] /= t;
00396
00397
00398
00399 frustum[1][0] = clip[ 3] + clip[ 0];
00400 frustum[1][1] = clip[ 7] + clip[ 4];
00401 frustum[1][2] = clip[11] + clip[ 8];
00402 frustum[1][3] = clip[15] + clip[12];
00403
00404
00405 t = (float) sqrt( frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2] );
00406 frustum[1][0] /= t;
00407 frustum[1][1] /= t;
00408 frustum[1][2] /= t;
00409 frustum[1][3] /= t;
00410
00411
00412
00413 frustum[2][0] = clip[ 3] + clip[ 1];
00414 frustum[2][1] = clip[ 7] + clip[ 5];
00415 frustum[2][2] = clip[11] + clip[ 9];
00416 frustum[2][3] = clip[15] + clip[13];
00417
00418
00419 t = (float) sqrt( frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2] );
00420 frustum[2][0] /= t;
00421 frustum[2][1] /= t;
00422 frustum[2][2] /= t;
00423 frustum[2][3] /= t;
00424
00425
00426
00427 frustum[3][0] = clip[ 3] - clip[ 1];
00428 frustum[3][1] = clip[ 7] - clip[ 5];
00429 frustum[3][2] = clip[11] - clip[ 9];
00430 frustum[3][3] = clip[15] - clip[13];
00431
00432
00433 t = (float) sqrt( frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2] );
00434 frustum[3][0] /= t;
00435 frustum[3][1] /= t;
00436 frustum[3][2] /= t;
00437 frustum[3][3] /= t;
00438
00439
00440
00441 frustum[4][0] = clip[ 3] - clip[ 2];
00442 frustum[4][1] = clip[ 7] - clip[ 6];
00443 frustum[4][2] = clip[11] - clip[10];
00444 frustum[4][3] = clip[15] - clip[14];
00445
00446
00447 t = (float) sqrt( frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2] );
00448 frustum[4][0] /= t;
00449 frustum[4][1] /= t;
00450 frustum[4][2] /= t;
00451 frustum[4][3] /= t;
00452
00453
00454
00455 frustum[5][0] = clip[ 3] + clip[ 2];
00456 frustum[5][1] = clip[ 7] + clip[ 6];
00457 frustum[5][2] = clip[11] + clip[10];
00458 frustum[5][3] = clip[15] + clip[14];
00459
00460
00461 t = (float) sqrt( frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2] );
00462 frustum[5][0] /= t;
00463 frustum[5][1] /= t;
00464 frustum[5][2] /= t;
00465 frustum[5][3] /= t;
00466 }
00467
00468
00473 bool Camera::cullPoint( const Vector &v ) const {
00474 for( int p = 0; p < 6; p++ ){
00475 if( frustum[p][0] * v[0] + frustum[p][1] * v[1] + frustum[p][2] * v[2] + frustum[p][3] <= 0 ){
00476 return false;
00477 }
00478 }
00479 return true;
00480 }
00481
00482
00483
00484
00485
00486
00487 bool Camera::cullSphere( const Vector &v, float radius ) const {
00488 for( int p=0; p<6; p++ ){
00489 if( frustum[p][0] * v[0] + frustum[p][1] * v[1] + frustum[p][2] * v[2] + frustum[p][3] <= -radius ){
00490 return false;
00491 }
00492 }
00493 return true;
00494 }
00495
00496
00501 bool Camera::cullAABox( const Vector &pos, const Vector &size ){
00502 for( int p=0; p<6; p++ ){
00503 Vector min = pos - size;
00504 Vector max = pos + size;
00505 if( frustum[p][0] * min[0] + frustum[p][1] * min[1] + frustum[p][2] * min[2] + frustum[p][3] > 0 ) continue;
00506 if( frustum[p][0] * max[0] + frustum[p][1] * min[1] + frustum[p][2] * min[2] + frustum[p][3] > 0 ) continue;
00507 if( frustum[p][0] * min[0] + frustum[p][1] * max[1] + frustum[p][2] * min[2] + frustum[p][3] > 0 ) continue;
00508 if( frustum[p][0] * max[0] + frustum[p][1] * max[1] + frustum[p][2] * min[2] + frustum[p][3] > 0 ) continue;
00509 if( frustum[p][0] * min[0] + frustum[p][1] * min[1] + frustum[p][2] * max[2] + frustum[p][3] > 0 ) continue;
00510 if( frustum[p][0] * max[0] + frustum[p][1] * min[1] + frustum[p][2] * max[2] + frustum[p][3] > 0 ) continue;
00511 if( frustum[p][0] * min[0] + frustum[p][1] * max[1] + frustum[p][2] * max[2] + frustum[p][3] > 0 ) continue;
00512 if( frustum[p][0] * max[0] + frustum[p][1] * max[1] + frustum[p][2] * max[2] + frustum[p][3] > 0 ) continue;
00513 return false;
00514 }
00515 return true;
00516 }
00517
00518
00519 };
00520 };
00521