camera.cpp
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // Eigen is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 3 of the License, or (at your option) any later version.
00010 //
00011 // Alternatively, you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License as
00013 // published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License and a copy of the GNU General Public License along with
00023 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00024 
00025 #include "camera.h"
00026 
00027 #include "gpuhelper.h"
00028 #include <GL/glu.h>
00029 
00030 #include "Eigen/LU"
00031 using namespace Eigen;
00032 
00033 Camera::Camera()
00034     : mViewIsUptodate(false), mProjIsUptodate(false)
00035 {
00036     mViewMatrix.setIdentity();
00037     
00038     mFovY = M_PI/3.;
00039     mNearDist = 1.;
00040     mFarDist = 50000.;
00041     
00042     mVpX = 0;
00043     mVpY = 0;
00044 
00045     setPosition(Vector3f::Constant(100.));
00046     setTarget(Vector3f::Zero());
00047 }
00048 
00049 Camera& Camera::operator=(const Camera& other)
00050 {
00051     mViewIsUptodate = false;
00052     mProjIsUptodate = false;
00053     
00054     mVpX = other.mVpX;
00055     mVpY = other.mVpY;
00056     mVpWidth = other.mVpWidth;
00057     mVpHeight = other.mVpHeight;
00058 
00059     mTarget = other.mTarget;
00060     mFovY = other.mFovY;
00061     mNearDist = other.mNearDist;
00062     mFarDist = other.mFarDist;
00063     
00064     mViewMatrix = other.mViewMatrix;
00065     mProjectionMatrix = other.mProjectionMatrix;
00066 
00067     return *this;
00068 }
00069 
00070 Camera::Camera(const Camera& other)
00071 {
00072     *this = other;
00073 }
00074 
00075 Camera::~Camera()
00076 {
00077 }
00078 
00079 
00080 void Camera::setViewport(uint offsetx, uint offsety, uint width, uint height)
00081 {
00082     mVpX = offsetx;
00083     mVpY = offsety;
00084     mVpWidth = width;
00085     mVpHeight = height;
00086     
00087     mProjIsUptodate = false;
00088 }
00089 
00090 void Camera::setViewport(uint width, uint height)
00091 {
00092     mVpWidth = width;
00093     mVpHeight = height;
00094     
00095     mProjIsUptodate = false;
00096 }
00097 
00098 void Camera::setFovY(float value)
00099 {
00100     mFovY = value;
00101     mProjIsUptodate = false;
00102 }
00103 
00104 Vector3f Camera::direction(void) const
00105 {
00106     return - (orientation() * Vector3f::UnitZ());
00107 }
00108 Vector3f Camera::up(void) const
00109 {
00110     return orientation() * Vector3f::UnitY();
00111 }
00112 Vector3f Camera::right(void) const
00113 {
00114     return orientation() * Vector3f::UnitX();
00115 }
00116 
00117 void Camera::setDirection(const Vector3f& newDirection)
00118 {
00119     // TODO implement it computing the rotation between newDirection and current dir ?
00120     Vector3f up = this->up();
00121     
00122     Matrix3f camAxes;
00123 
00124     camAxes.col(2) = (-newDirection).normalized();
00125     camAxes.col(0) = up.cross( camAxes.col(2) ).normalized();
00126     camAxes.col(1) = camAxes.col(2).cross( camAxes.col(0) ).normalized();
00127     setOrientation(Quaternionf(camAxes));
00128     
00129     mViewIsUptodate = false;
00130 }
00131 
00132 void Camera::setTarget(const Vector3f& target)
00133 {
00134     mTarget = target;
00135     if (!mTarget.isApprox(position()))
00136     {
00137         Vector3f newDirection = mTarget - position();
00138         setDirection(newDirection.normalized());
00139     }
00140 }
00141 
00142 void Camera::setPosition(const Vector3f& p)
00143 {
00144     mFrame.position = p;
00145     mViewIsUptodate = false;
00146 }
00147 
00148 void Camera::setOrientation(const Quaternionf& q)
00149 {
00150     mFrame.orientation = q;
00151     mViewIsUptodate = false;
00152 }
00153 
00154 void Camera::setFrame(const Frame& f)
00155 {
00156   mFrame = f;
00157   mViewIsUptodate = false;
00158 }
00159 
00160 void Camera::rotateAroundTarget(const Quaternionf& q)
00161 {
00162     Matrix4f mrot, mt, mtm;
00163     
00164     // update the transform matrix
00165     updateViewMatrix();
00166     Vector3f t = mViewMatrix * mTarget;
00167 
00168     mViewMatrix = Translation3f(t)
00169                 * q
00170                 * Translation3f(-t)
00171                 * mViewMatrix;
00172     
00173     Quaternionf qa(mViewMatrix.linear());
00174     qa = qa.conjugate();
00175     setOrientation(qa);
00176     setPosition(- (qa * mViewMatrix.translation()) );
00177 
00178     mViewIsUptodate = true;
00179 }
00180 
00181 void Camera::localRotate(const Quaternionf& q)
00182 {
00183     float dist = (position() - mTarget).norm();
00184     setOrientation(orientation() * q);
00185     mTarget = position() + dist * direction();
00186     mViewIsUptodate = false;
00187 }
00188 
00189 void Camera::zoom(float d)
00190 {
00191     float dist = (position() - mTarget).norm();
00192     if(dist > d)
00193     {
00194         setPosition(position() + direction() * d);
00195         mViewIsUptodate = false;
00196     }
00197 }
00198 
00199 void Camera::localTranslate(const Vector3f& t)
00200 {
00201   Vector3f trans = orientation() * t;
00202   setPosition( position() + trans );
00203   setTarget( mTarget + trans );
00204 
00205   mViewIsUptodate = false;
00206 }
00207 
00208 void Camera::updateViewMatrix(void) const
00209 {
00210     if(!mViewIsUptodate)
00211     {
00212         Quaternionf q = orientation().conjugate();
00213         mViewMatrix.linear() = q.toRotationMatrix();
00214         mViewMatrix.translation() = - (mViewMatrix.linear() * position());
00215 
00216         mViewIsUptodate = true;
00217     }
00218 }
00219 
00220 const Affine3f& Camera::viewMatrix(void) const
00221 {
00222   updateViewMatrix();
00223   return mViewMatrix;
00224 }
00225 
00226 void Camera::updateProjectionMatrix(void) const
00227 {
00228   if(!mProjIsUptodate)
00229   {
00230     mProjectionMatrix.setIdentity();
00231     float aspect = float(mVpWidth)/float(mVpHeight);
00232     float theta = mFovY*0.5;
00233     float range = mFarDist - mNearDist;
00234     float invtan = 1./tan(theta);
00235 
00236     mProjectionMatrix(0,0) = invtan / aspect;
00237     mProjectionMatrix(1,1) = invtan;
00238     mProjectionMatrix(2,2) = -(mNearDist + mFarDist) / range;
00239     mProjectionMatrix(3,2) = -1;
00240     mProjectionMatrix(2,3) = -2 * mNearDist * mFarDist / range;
00241     mProjectionMatrix(3,3) = 0;
00242     
00243     mProjIsUptodate = true;
00244   }
00245 }
00246 
00247 const Matrix4f& Camera::projectionMatrix(void) const
00248 {
00249   updateProjectionMatrix();
00250   return mProjectionMatrix;
00251 }
00252 
00253 void Camera::activateGL(void)
00254 {
00255   glViewport(vpX(), vpY(), vpWidth(), vpHeight());
00256   gpu.loadMatrix(projectionMatrix(),GL_PROJECTION);
00257   gpu.loadMatrix(viewMatrix().matrix(),GL_MODELVIEW);
00258 }
00259 
00260 
00261 Vector3f Camera::unProject(const Vector2f& uv, float depth) const
00262 {
00263     Matrix4f inv = mViewMatrix.inverse().matrix();
00264     return unProject(uv, depth, inv);
00265 }
00266 
00267 Vector3f Camera::unProject(const Vector2f& uv, float depth, const Matrix4f& invModelview) const
00268 {
00269     updateViewMatrix();
00270     updateProjectionMatrix();
00271     
00272     Vector3f a(2.*uv.x()/float(mVpWidth)-1., 2.*uv.y()/float(mVpHeight)-1., 1.);
00273     a.x() *= depth/mProjectionMatrix(0,0);
00274     a.y() *= depth/mProjectionMatrix(1,1);
00275     a.z() = -depth;
00276     // FIXME /\/|
00277     Vector4f b = invModelview * Vector4f(a.x(), a.y(), a.z(), 1.);
00278     return Vector3f(b.x(), b.y(), b.z());
00279 }


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:30:48