# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlGraphics/Camera.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.org                                               */
    00005 /*                                                                                    */
    00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
    00007 /*  All rights reserved.                                                              */
    00008 /*                                                                                    */
    00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
    00010 /*  are permitted provided that the following conditions are met:                     */
    00011 /*                                                                                    */
    00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
    00013 /*  list of conditions and the following disclaimer.                                  */
    00014 /*                                                                                    */
    00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
    00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
    00017 /*  other materials provided with the distribution.                                   */
    00018 /*                                                                                    */
    00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
    00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
    00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
    00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
    00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
    00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
    00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
    00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
    00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
    00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
    00029 /*                                                                                    */
    00030 /**************************************************************************************/
    00031
    00032 #include <vlGraphics/Camera.hpp>
    00033 #include <vlGraphics/OpenGL.hpp>
    00034 #include <vlCore/AABB.hpp>
    00035 #include <vlCore/Log.hpp>
    00036 #include <vlCore/Say.hpp>
    00037
    00038 #undef near
    00039 #undef far
    00040
    00041 using namespace vl;
    00042
    00043 //-----------------------------------------------------------------------------
    00044 // Camera
    00045 //-----------------------------------------------------------------------------
    00046 Camera::Camera()
    00047 {
    00048   VL_DEBUG_SET_OBJECT_NAME()
    00049   mFrustum.planes().resize(6);
    00050   mFOV = 60.0;
    00051   mNearPlane = (real)0.05;
    00052   mFarPlane  = (real)10000.0;
    00053   mLeft = mRight = mTop = mBottom = -1;
    00054   mViewport = new Viewport;
    00055
    00056   mProjectionMatrix  = mat4::getPerspective(fov(), 640.0f/480.0f, nearPlane(), farPlane());
    00057   mProjectionType = PMT_PerspectiveProjection;
    00058 }
    00059 //-----------------------------------------------------------------------------
    00060 void Camera::applyModelViewMatrix(const mat4& model_matrix) const
    00061 {
    00062   /* some OpenGL drivers (ATI) require this instead of the more general (and mathematically correct) viewMatrix() */
    00063   mat4 viewm = viewMatrix();
    00064   viewm.e(3,0) = 0.0;
    00065   viewm.e(3,1) = 0.0;
    00066   viewm.e(3,2) = 0.0;
    00067   viewm.e(3,3) = 1.0;
    00068
    00069   glMatrixMode(GL_MODELVIEW);
    00070 #if 0
    00071   VL_glLoadMatrix( viewm.ptr() );
    00072   VL_glMultMatrix( matrix.ptr() );
    00073 #elif 0
    00074   viewm = viewm * matrix;
    00075   VL_glLoadMatrix( viewm.ptr() );
    00076 #else
    00077   VL_glLoadMatrix( (viewm * model_matrix).ptr() );
    00078 #endif
    00079 }
    00080 //-----------------------------------------------------------------------------
    00081 void Camera::applyProjMatrix() const
    00082 {
    00083   // projection matrix
    00084   glMatrixMode( GL_PROJECTION );
    00085   VL_glLoadMatrix( projectionMatrix().ptr() );
    00086 }
    00087 //-----------------------------------------------------------------------------
    00088 void Camera::applyViewMatrix() const
    00089 {
    00090   /* some OpenGL drivers (ATI) require this instead of the more general (and mathematically correct) viewMatrix() */
    00091   mat4 viewm = viewMatrix();
    00092   viewm.e(3,0) = 0.0;
    00093   viewm.e(3,1) = 0.0;
    00094   viewm.e(3,2) = 0.0;
    00095   viewm.e(3,3) = 1.0;
    00096   glMatrixMode(GL_MODELVIEW);
    00097   VL_glLoadMatrix( viewm.ptr() );
    00098 }
    00099 //-----------------------------------------------------------------------------
    00100 void Camera::computeNearFarOptimizedProjMatrix(const Sphere& scene_bounding_sphere)
    00101 {
    00102   // near/far clipping planes optimization
    00103   if (!scene_bounding_sphere.isNull())
    00104   {
    00105     // transform the sphere in camera coordinates
    00106     Sphere camera_sphere;
    00107     scene_bounding_sphere.transformed(camera_sphere, viewMatrix());
    00108
    00109     // visible objects are in the negative z, but we need a positive distance for the near and far clipping planes
    00110     mNearPlane = -(camera_sphere.center().z() + camera_sphere.radius());
    00111     mFarPlane  = -(camera_sphere.center().z() - camera_sphere.radius());
    00112
    00113     // clamp to positive epsilon: can't let near and far clipping planes go behind the camera!
    00114     real epsilon = camera_sphere.radius() / 1000.0f;
    00115     mFarPlane  = max(mFarPlane,  epsilon * 2); // alway more than the near
    00116     mNearPlane = max(mNearPlane, epsilon * 1);
    00117
    00118     switch(projectionMatrixType())
    00119     {
    00120     case PMT_OrthographicProjection: setProjectionOrtho(mLeft, mRight, mBottom, mTop, mNearPlane, mFarPlane);
    00121       break;
    00122     case PMT_PerspectiveProjection:  setProjectionPerspective();
    00123       break;
    00124
    00125     // we cannot do this: if we change the near plane we have to recompute also left, right, bottom and top!
    00126     // case PMT_PerspectiveProjectionFrustum: setProjectionFrustum(mLeft, mRight, mBottom, mTop, mNearPlane, mFarPlane);
    00127     //   break;
    00128
    00129     default:
    00130       Log::bug("Camera::computeNearFarOptimizedProjMatrix() called on unsupported projection type.\n");
    00131     }
    00132   }
    00133 }
    00134 //-----------------------------------------------------------------------------
    00135 void Camera::adjustView(const AABB& aabb, const vec3& dir, const vec3& up, real bias)
    00136 {
    00137   VL_CHECK(bias >= 0)
    00138   VL_CHECK(!aabb.isNull())
    00139   if (bias < 0)
    00140     vl::Log::bug("Camera::adjustView(): 'bias' must be >= 0.\n");
    00141
    00142   vec3 center = aabb.center();
    00143
    00144   Sphere sphere(aabb);
    00145   const vec3& C = modelingMatrix().getT();
    00146   const vec3& V = -modelingMatrix().getZ();
    00147   const real  R = sphere.radius();
    00148
    00149   // extract the frustum planes based on the current view and projection matrices
    00150   mat4 viewproj = projectionMatrix() * viewMatrix();
    00151   Frustum frustum; frustum.planes().resize(6);
    00152   extractPlanes( &frustum.planes()[0], viewproj );
    00153   // iterate over left/right/top/bottom clipping planes. the planes are in world coords.
    00154   real max_t = 0;
    00155   for(int i=0; i<4; ++i)
    00156   {
    00157     const vec3& O = frustum.plane(i).origin() * frustum.plane(i).normal();
    00158     const vec3& N = frustum.plane(i).normal();
    00159     real t = - (R + dot(O,N) - dot(C,N)) / dot(N,V);
    00160     VL_CHECK(t>=0)
    00161     if (t > max_t)
    00162       max_t = t;
    00163   }
    00164   real dist = max_t;
    00165   mat4 m = mat4::getLookAt(center+dir*dist*bias,center,up);
    00166   setViewMatrix(m);
    00167 }
    00168 //-----------------------------------------------------------------------------
    00169 void Camera::computeFrustumPlanes()
    00170 {
    00171   // build modelview matrix
    00172   mat4 viewproj = projectionMatrix() * viewMatrix();
    00173   // frustum plane extraction
    00174   mFrustum.planes().resize(6);
    00175   extractPlanes( &mFrustum.planes()[0], viewproj );
    00176 }
    00177 //-----------------------------------------------------------------------------
    00178 void Camera::setProjectionFrustum(real left, real right, real bottom, real top, real near, real far)
    00179 {
    00180   // see http://www.opengl.org/resources/faq/technical/transformations.htm
    00181   setFOV( 2.0f*atan((top-bottom)*0.5f/near) );
    00182   setNearPlane(near);
    00183   setFarPlane(far);
    00184   setProjectionMatrix(mat4::getFrustum(left, right, bottom, top, near, far), PMT_PerspectiveProjectionFrustum);
    00185 }
    00186 //-----------------------------------------------------------------------------
    00187 void Camera::setProjectionPerspective(real fov, real near, real far)
    00188 {
    00189   setFOV(fov);
    00190   setNearPlane(near);
    00191   setFarPlane(far);
    00192   setProjectionMatrix(mat4::getPerspective(fov, aspectRatio(), near, far), PMT_PerspectiveProjection);
    00193 }
    00194 //-----------------------------------------------------------------------------
    00195 void Camera::setProjectionPerspective()
    00196 {
    00197   setProjectionMatrix(mat4::getPerspective(fov(), aspectRatio(), nearPlane(), farPlane()), PMT_PerspectiveProjection);
    00198 }
    00199 //-----------------------------------------------------------------------------
    00200 void Camera::setProjectionOrtho()
    00201 {
    00202   mLeft   = 0;
    00203   mRight  = (real)mViewport->width();
    00204   mBottom = 0;
    00205   mTop    = (real)mViewport->height();
    00206   mFOV = -1;
    00207   setProjectionMatrix( mat4::getOrtho( mLeft, mRight, mBottom, mTop, mNearPlane, mFarPlane), PMT_OrthographicProjection );
    00208 }
    00209 //-----------------------------------------------------------------------------
    00210 void Camera::setProjectionOrtho(real left, real right, real bottom, real top, real znear, real zfar)
    00211 {
    00212   mLeft   = left;
    00213   mRight  = right;
    00214   mBottom = bottom;
    00215   mTop    = top;
    00216   mFOV = -1;
    00217   mNearPlane = znear;
    00218   mFarPlane  = zfar;
    00219   setProjectionMatrix( mat4::getOrtho( mLeft, mRight, mBottom, mTop, mNearPlane, mFarPlane), PMT_OrthographicProjection );
    00220 }
    00221 //-----------------------------------------------------------------------------
    00222 void Camera::setProjectionOrtho(real offset)
    00223 {
    00224   mLeft   = offset;
    00225   mRight  = viewport()->width() + offset;
    00226   mBottom = offset;
    00227   mTop    = viewport()->height() + offset;
    00228   mFOV = -1;
    00229   mNearPlane = -1;
    00230   mFarPlane  = +1;
    00231   setProjectionMatrix( mat4::getOrtho( mLeft, mRight, mBottom, mTop, mNearPlane, mFarPlane), PMT_OrthographicProjection );
    00232 }
    00233 //-----------------------------------------------------------------------------
    00234 void Camera::setViewMatrixLookAt( const vec3& eye, const vec3& at, const vec3& up)
    00235 {
    00236   // note: this sets both the local matrix and the view matrix
    00237   setViewMatrix( mat4::getLookAt(eye, at, up) );
    00238 }
    00239 //-----------------------------------------------------------------------------
    00240 void Camera::getViewMatrixAsLookAt( vec3& eye, vec3& at, vec3& up, vec3& right) const
    00241 {
    00242   mModelingMatrix.getAsLookAtModeling(eye, at, up, right);
    00243 }
    00244 //-----------------------------------------------------------------------------
    00245 bool Camera::project(const vec4& in, vec4& out) const
    00246 {
    00247   out = mProjectionMatrix * mViewMatrix * in;
    00248
    00249   if (out.w() == 0.0f)
    00250     return false;
    00251
    00252   out.x() /= out.w();
    00253   out.y() /= out.w();
    00254   out.z() /= out.w();
    00255
    00256   // map to range 0-1
    00257   out.x() = out.x() * 0.5f + 0.5f;
    00258   out.y() = out.y() * 0.5f + 0.5f;
    00259   out.z() = out.z() * 0.5f + 0.5f;
    00260
    00261   // map to viewport
    00262   out.x() = out.x() * mViewport->width()  + mViewport->x();
    00263   out.y() = out.y() * mViewport->height() + mViewport->y();
    00264   return true;
    00265 }
    00266 //-----------------------------------------------------------------------------
    00267 bool Camera::unproject(const vec3& win, vec4& out) const
    00268 {
    00269     vec4 v;
    00270     v.x() = win.x();
    00271     v.y() = win.y();
    00272     v.z() = win.z();
    00273     v.w() = 1.0;
    00274
    00275     // map from viewport to 0-1
    00276     v.x() = (v.x() - mViewport->x()) / mViewport->width();
    00277     v.y() = (v.y() - mViewport->y()) / mViewport->height();
    00278
    00279     // map to range -1 to 1
    00280     v.x() = v.x() * 2.0f - 1.0f;
    00281     v.y() = v.y() * 2.0f - 1.0f;
    00282     v.z() = v.z() * 2.0f - 1.0f;
    00283
    00284     real det=0;
    00285     mat4 inverse = (mProjectionMatrix * mViewMatrix).getInverse(&det);
    00286     if (!det)
    00287       return false;
    00288
    00289     v = inverse * v;
    00290     if (v.w() == 0.0)
    00291       return false;
    00292
    00293     out = v / v.w();
    00294     return true;
    00295 }
    00296 //-----------------------------------------------------------------------------
    00297 bool Camera::unproject(std::vector<vec3>& win) const
    00298 {
    00299   real det=0;
    00300   mat4 inverse = (mProjectionMatrix * mViewMatrix).getInverse(&det);
    00301   if (!det)
    00302     return false;
    00303
    00304   bool ok = true;
    00305   for(unsigned i=0; i<win.size(); ++i)
    00306   {
    00307     vec4 v;
    00308     v = vec4( win[i], 1.0 );
    00309
    00310     // map from viewport to 0-1
    00311     v.x() = (v.x() - mViewport->x()) / mViewport->width();
    00312     v.y() = (v.y() - mViewport->y()) / mViewport->height();
    00313
    00314     // map to range -1 to 1
    00315     v.x() = v.x() * 2.0f - 1.0f;
    00316     v.y() = v.y() * 2.0f - 1.0f;
    00317     v.z() = v.z() * 2.0f - 1.0f;
    00318
    00319     v = inverse * v;
    00320     if (v.w() == 0.0)
    00321     {
    00322       ok = false;
    00323       continue;
    00324     }
    00325
    00326     v = v / v.w();
    00327     win[i] = v.xyz();
    00328   }
    00329   return ok;
    00330 }
    00331 //-----------------------------------------------------------------------------
    00332 Ray Camera::computeRay(int winx, int winy)
    00333 {
    00334   vl::vec4 out;
    00335   if (!unproject( vl::vec3((real)winx,(real)winy,0), out ))
    00336     return Ray();
    00337   else
    00338   {
    00339     vl::Ray ray;
    00340     ray.setOrigin(out.xyz());
    00341     ray.setDirection( (out.xyz() - modelingMatrix().getT()).normalize() );
    00342     return ray;
    00343   }
    00344 }
    00345 //-----------------------------------------------------------------------------
    00346 Frustum Camera::computeRayFrustum(int winx, int winy)
    00347 {
    00348   /*
    00349       n3
    00350     D-----C
    00351     |     |
    00352   n4|  O  |n2
    00353     |     |
    00354     A-----B
    00355       n1
    00356   */
    00357   // compute the frustum passing through the adjacent pixels
    00358   vl::vec4 A1,B1,C1,D1;
    00359   vl::vec4 A2,B2,C2,D2;
    00360   unproject( vl::vec3((real)winx-1,(real)winy-1,0),    A1 );
    00361   unproject( vl::vec3((real)winx+1,(real)winy-1,0),    B1 );
    00362   unproject( vl::vec3((real)winx+1,(real)winy+1,0),    C1 );
    00363   unproject( vl::vec3((real)winx-1,(real)winy+1,0),    D1 );
    00364   unproject( vl::vec3((real)winx-1,(real)winy-1,0.1f), A2 );
    00365   unproject( vl::vec3((real)winx+1,(real)winy-1,0.1f), B2 );
    00366   unproject( vl::vec3((real)winx+1,(real)winy+1,0.1f), C2 );
    00367   unproject( vl::vec3((real)winx-1,(real)winy+1,0.1f), D2 );
    00368
    00369   vec3 n1 = -cross(A2.xyz()-A1.xyz(),B1.xyz()-A1.xyz());
    00370   vec3 n2 = -cross(B2.xyz()-B1.xyz(),C1.xyz()-B1.xyz());
    00371   vec3 n3 = -cross(C2.xyz()-C1.xyz(),D1.xyz()-C1.xyz());
    00372   vec3 n4 = -cross(D2.xyz()-D1.xyz(),A1.xyz()-D1.xyz());
    00373   Frustum frustum;
    00374   frustum.planes().push_back( Plane( A1.xyz(), n1 ) );
    00375   frustum.planes().push_back( Plane( B1.xyz(), n2 ) );
    00376   frustum.planes().push_back( Plane( C1.xyz(), n3 ) );
    00377   frustum.planes().push_back( Plane( D1.xyz(), n4 ) );
    00378   return frustum;
    00379 }
    00380 //-----------------------------------------------------------------------------

Visualization Library v2011.09.1162 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu Jan 26 2012 00:43:36.
Permission is granted to use this page to write and publish articles regarding Visualization Library.