glc_camera.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  Copyright (C) 2009 Laurent Bauer
00006  http://glc-lib.sourceforge.net
00007 
00008  GLC-lib is free software; you can redistribute it and/or modify
00009  it under the terms of the GNU Lesser General Public License as published by
00010  the Free Software Foundation; either version 3 of the License, or
00011  (at your option) any later version.
00012 
00013  GLC-lib is distributed in the hope that it will be useful,
00014  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  GNU Lesser General Public License for more details.
00017 
00018  You should have received a copy of the GNU Lesser General Public License
00019  along with GLC-lib; if not, write to the Free Software
00020  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021 
00022 *****************************************************************************/
00023 
00025 
00026 #include "glc_camera.h"
00027 #include "../glc_context.h"
00028 
00029 #include <QtDebug>
00030 
00031 using namespace glc;
00033 // Constructor Destructor
00035 GLC_Camera::GLC_Camera()
00036 : GLC_Object("Camera")
00037 , m_Eye(0,0,1)
00038 , m_Target()
00039 , m_VectUp(Y_AXIS)
00040 , m_ModelViewMatrix()
00041 , m_DefaultVectUp(Y_AXIS)
00042 {
00043 
00044 }
00045 
00046 GLC_Camera::GLC_Camera(const GLC_Point3d &Eye, const GLC_Point3d &Target, const GLC_Vector3d &Up)
00047 : GLC_Object("Camera")
00048 , m_Eye()
00049 , m_Target()
00050 , m_VectUp()
00051 , m_ModelViewMatrix()
00052 , m_DefaultVectUp(Y_AXIS)
00053 {
00054         setCam(Eye, Target, Up);
00055         createMatComp();
00056 }
00057 
00058 // Copy constructor
00059 GLC_Camera::GLC_Camera(const GLC_Camera& cam)
00060 : GLC_Object(cam)
00061 , m_Eye(cam.m_Eye)
00062 , m_Target(cam.m_Target)
00063 , m_VectUp(cam.m_VectUp)
00064 , m_ModelViewMatrix(cam.m_ModelViewMatrix)
00065 , m_DefaultVectUp(cam.m_DefaultVectUp)
00066 {
00067 
00068 }
00069 
00071 // Get Functions
00073 
00074 // equality operator
00075 bool GLC_Camera::operator==(const GLC_Camera& cam) const
00076 {
00077         return (m_Eye == cam.m_Eye) && (m_Target == cam.m_Target)
00078                         && (m_VectUp == cam.m_VectUp) && (m_DefaultVectUp == cam.m_DefaultVectUp);
00079 }
00080 
00081 
00083 // Set Functions
00085 GLC_Camera& GLC_Camera::orbit(GLC_Vector3d VectOldPoss, GLC_Vector3d VectCurPoss)
00086 {
00087         // Map Vectors
00088         GLC_Matrix4x4 invMat(m_ModelViewMatrix);
00089         invMat.invert();
00090         VectOldPoss= invMat * VectOldPoss;
00091         VectCurPoss= invMat * VectCurPoss;
00092 
00093         // Compute rotation matrix
00094         const GLC_Vector3d VectAxeRot(VectCurPoss ^ VectOldPoss);
00095         // Check if rotation vector is not null
00096         if (!VectAxeRot.isNull())
00097         {  // Ok, is not null
00098                 const double Angle= acos(VectCurPoss * VectOldPoss);
00099                 const GLC_Matrix4x4 MatOrbit(VectAxeRot, Angle);
00100 
00101                 // Camera transformation
00102                 m_Eye= (MatOrbit * (m_Eye - m_Target)) + m_Target;
00103                 m_VectUp= MatOrbit * m_VectUp;
00104                 createMatComp();
00105         }
00106 
00107         return *this;
00108 }
00109 
00110 GLC_Camera& GLC_Camera::pan(GLC_Vector3d VectDep)
00111 {
00112         // Vector mapping
00113         GLC_Matrix4x4 invMat(m_ModelViewMatrix);
00114         invMat.invert();
00115         VectDep= invMat * VectDep;
00116 
00117         // Camera transformation
00118         m_Eye= m_Eye + VectDep;
00119         m_Target= m_Target + VectDep;
00120 
00121         return *this;
00122 }
00123 
00124 GLC_Camera& GLC_Camera::zoom(double factor)
00125 {
00126         Q_ASSERT(factor > 0);
00127         // Eye->target vector
00128         GLC_Vector3d VectCam(m_Eye - m_Target);
00129 
00130         // Compute new vector length
00131         const double Norme= VectCam.length() * 1 / factor;
00132         VectCam.setLength(Norme);
00133 
00134         m_Eye= VectCam + m_Target;
00135 
00136         return *this;
00137 }
00138 
00139 // Move camera
00140 GLC_Camera& GLC_Camera::move(const GLC_Matrix4x4 &MatMove)
00141 {
00142         m_Eye= MatMove * m_Eye;
00143         m_Target= MatMove * m_Target;
00144         m_VectUp= MatMove.rotationMatrix() * m_VectUp;
00145         createMatComp();
00146 
00147         return *this;
00148 }
00149 
00150 // Rotate around an axis
00151 GLC_Camera& GLC_Camera::rotateAround(const GLC_Vector3d& axis, const double& angle, const GLC_Point3d& point)
00152 {
00153         const GLC_Matrix4x4 rotationMatrix(axis, angle);
00154         translate(-point);
00155         move(rotationMatrix);
00156         translate(point);
00157 
00158         return *this;
00159 }
00160 
00161 // Rotate around camera target
00162 GLC_Camera& GLC_Camera::rotateAroundTarget(const GLC_Vector3d& axis, const double& angle)
00163 {
00164         GLC_Point3d target(m_Target);
00165         rotateAround(axis, angle, target);
00166 
00167         return *this;
00168 }
00169 
00170 GLC_Camera& GLC_Camera::translate(const GLC_Vector3d &VectTrans)
00171 {
00172         m_Eye= m_Eye + VectTrans;
00173         m_Target= m_Target + VectTrans;
00174 
00175         return *this;
00176 }
00177 
00178 GLC_Camera& GLC_Camera::setEyeCam(const GLC_Point3d &Eye)
00179 {
00180         // Old camera's vector
00181         GLC_Vector3d VectOldCam(m_Eye - m_Target);
00182         // New camera's vector
00183         GLC_Vector3d VectCam(Eye - m_Target);
00184         if ( !(VectOldCam - VectCam).isNull() )
00185         {
00186                 VectOldCam.setLength(1);
00187                 VectCam.setLength(1);
00188                 const double Angle= acos(VectOldCam * VectCam);
00189                 if ( !qFuzzyCompare(Angle, 0.0) && !qFuzzyCompare(PI - Angle, 0.0))
00190                 {
00191                         const GLC_Vector3d VectAxeRot(VectOldCam ^ VectCam);
00192                         const GLC_Matrix4x4 MatRot(VectAxeRot, Angle);
00193                         m_VectUp= MatRot * m_VectUp;
00194                 }
00195                 else
00196                 {
00197                         if ( qFuzzyCompare(PI - Angle, 0.0))
00198                         {       // Angle de 180%
00199                                 m_VectUp.invert();
00200                         }
00201                 }
00202 
00203                 setCam(Eye, m_Target, m_VectUp);
00204         }
00205 
00206         return *this;
00207 }
00208 
00209 GLC_Camera& GLC_Camera::setTargetCam(const GLC_Point3d &Target)
00210 {
00211         // Old camera's vector
00212         GLC_Vector3d VectOldCam(m_Eye - m_Target);
00213         // New camera's vector
00214         GLC_Vector3d VectCam(m_Eye - Target);
00215         if ( !(VectOldCam - VectCam).isNull() )
00216         {
00217                 VectOldCam.setLength(1);
00218                 VectCam.setLength(1);
00219                 const double Angle= acos(VectOldCam * VectCam);
00220                 if ( !qFuzzyCompare(Angle, 0.0) && !qFuzzyCompare(PI - Angle, 0.0))
00221                 {
00222                         const GLC_Vector3d VectAxeRot(VectOldCam ^ VectCam);
00223                         const GLC_Matrix4x4 MatRot(VectAxeRot, Angle);
00224                         m_VectUp= MatRot * m_VectUp;
00225                 }
00226                 else
00227                 {
00228                         if ( qFuzzyCompare(PI - Angle, 0.0))
00229                         {       // Angle of 180%
00230                                 m_VectUp.invert();
00231                         }
00232                 }
00233 
00234                 setCam(m_Eye, Target, m_VectUp);
00235         }
00236 
00237         return *this;
00238 }
00239 
00240 GLC_Camera& GLC_Camera::setUpCam(const GLC_Vector3d &Up)
00241 {
00242         if ( !(m_VectUp - Up).isNull() )
00243         {
00244                 if (!qFuzzyCompare(forward().angleWithVect(Up), 0.0))
00245                 {
00246                         setCam(m_Eye, m_Target, Up);
00247                 }
00248         }
00249 
00250         return *this;
00251 }
00252 
00253 GLC_Camera& GLC_Camera::setCam(GLC_Point3d Eye, GLC_Point3d Target, GLC_Vector3d Up)
00254 {
00255         Up.setLength(1);
00256 
00257         const GLC_Vector3d VectCam((Eye - Target).setLength(1));
00258         const double Angle= acos(VectCam * Up);
00259 
00260         /* m_VectUp and VectCam could not be parallel
00261          * m_VectUp could not be NULL
00262          * VectCam could not be NULL */
00263         //Q_ASSERT((Angle > EPSILON) && ((PI - Angle) > EPSILON));
00264 
00265         if ( !qFuzzyCompare(Angle - (PI / 2), 0.0))
00266         {       // Angle not equal to 90
00267                 const GLC_Vector3d AxeRot(VectCam ^ Up);
00268                 GLC_Matrix4x4 MatRot(AxeRot, PI / 2);
00269                 Up= MatRot * VectCam;
00270         }
00271 
00272         m_Eye= Eye;
00273         m_Target= Target;
00274         m_VectUp= Up;
00275         createMatComp();
00276 
00277         return *this;
00278 }
00279 
00281 GLC_Camera& GLC_Camera::setCam(const GLC_Camera& cam)
00282 {
00283         m_Eye= cam.m_Eye;
00284         m_Target= cam.m_Target;
00285         m_VectUp= cam.m_VectUp;
00286         m_ModelViewMatrix= cam.m_ModelViewMatrix;
00287 
00288         return *this;
00289 }
00290 
00291 
00292 GLC_Camera& GLC_Camera::setDistEyeTarget(double Longueur)
00293 {
00294     GLC_Vector3d VectCam(forward());
00295     VectCam.setLength(Longueur);
00296     m_Eye= m_Target - VectCam;
00297 
00298     return *this;
00299 }
00300 GLC_Camera& GLC_Camera::setDistTargetEye(double Longueur)
00301 {
00302     GLC_Vector3d VectCam(forward());
00303     VectCam.setLength(Longueur);
00304     m_Target= m_Eye + VectCam;
00305 
00306     return *this;
00307 }
00308 
00309 // Assignment operator
00310 GLC_Camera &GLC_Camera::operator=(const GLC_Camera& cam)
00311 {
00312         GLC_Object::operator=(cam);
00313         m_Eye= cam.m_Eye;
00314         m_Target= cam.m_Target;
00315         m_VectUp= cam.m_VectUp;
00316         m_ModelViewMatrix= cam.m_ModelViewMatrix;
00317         m_DefaultVectUp= cam.m_DefaultVectUp;
00318 
00319         return *this;
00320 }
00321 // almost equality (Bauer Laurent)
00322 bool GLC_Camera::isAlmostEqualTo(const GLC_Camera& cam, const double distanceAccuracy) const
00323 {
00324       GLC_Vector3d incident1 = m_Target - m_Eye;
00325       GLC_Vector3d incident2 = cam.m_Target - cam.m_Eye;
00326 
00327       double allowedGap =  incident1.length() * distanceAccuracy;
00328       GLC_Point3d left1 = incident1 ^ m_VectUp;
00329       GLC_Point3d left2 = incident2 ^ cam.m_VectUp;
00330 
00331       return ((m_Eye - cam.m_Eye).length() < allowedGap ) && ( (m_Target - cam.m_Target).length() < allowedGap)
00332                   && ((left1 - left2).length() < allowedGap) ;
00333 }
00334 
00335 // Return the standard front view form this camera
00336 GLC_Camera GLC_Camera::frontView() const
00337 {
00338         GLC_Vector3d eye;
00339 
00340         if (m_DefaultVectUp == glc::Z_AXIS)
00341         {
00342                 eye.setVect(0.0, -1.0, 0.0);
00343         }
00344         else // Y_AXIS or X_AXIS
00345         {
00346                 eye.setVect(0.0, 0.0, 1.0);
00347         }
00348         eye= eye + m_Target;
00349 
00350         GLC_Camera newCam(eye, m_Target, m_DefaultVectUp);
00351         newCam.setDistEyeTarget(distEyeTarget());
00352         newCam.setDefaultUpVector(m_DefaultVectUp);
00353         return newCam;
00354 }
00355 
00356 // Return the standard rear view form this camera
00357 GLC_Camera GLC_Camera::rearView() const
00358 {
00359         return frontView().rotateAroundTarget(m_DefaultVectUp, glc::PI);
00360 }
00361 
00362 // Return the standard right view form this camera
00363 GLC_Camera GLC_Camera::rightView() const
00364 {
00365         return frontView().rotateAroundTarget(m_DefaultVectUp, glc::PI / 2.0);}
00366 
00367 // Return the standard left view form this camera
00368 GLC_Camera GLC_Camera::leftView() const
00369 {
00370         return frontView().rotateAroundTarget(m_DefaultVectUp, - glc::PI / 2.0);
00371 }
00372 
00373 // Return the standard top view form this camera
00374 GLC_Camera GLC_Camera::topView() const
00375 {
00376         GLC_Vector3d eye= m_DefaultVectUp;
00377         eye= eye + m_Target;
00378         GLC_Vector3d up;
00379 
00380         if (m_DefaultVectUp == glc::Y_AXIS)
00381         {
00382                 up.setVect(0.0, 0.0, -1.0);
00383         }
00384         else // Z_AXIS or X_AXIS
00385         {
00386                 up.setVect(0.0, 1.0, 0.0);
00387         }
00388 
00389         GLC_Camera newCam(eye, m_Target, up);
00390         newCam.setDistEyeTarget(distEyeTarget());
00391         newCam.setDefaultUpVector(m_DefaultVectUp);
00392 
00393         return newCam;
00394 }
00395 
00396 // Return the standard bottom view form this camera
00397 GLC_Camera GLC_Camera::bottomView() const
00398 {
00399         GLC_Camera newCam(topView());
00400         newCam.rotateAroundTarget(newCam.upVector(), glc::PI);
00401 
00402         return newCam;
00403 }
00404 
00405 // Return the standard isoview from his camera
00406 GLC_Camera GLC_Camera::isoView() const
00407 {
00408         GLC_Vector3d eye;
00409         if (m_DefaultVectUp == glc::Z_AXIS)
00410         {
00411                 eye.setVect(-1.0, -1.0, 1.0);
00412         }
00413         else if (m_DefaultVectUp == glc::Y_AXIS)
00414         {
00415                 eye.setVect(-1.0, 1.0, 1.0);
00416         }
00417         else
00418         {
00419                 eye.setVect(1.0, 1.0, 1.0);
00420         }
00421 
00422         eye= eye + m_Target;
00423 
00424         GLC_Camera newCam(eye, m_Target, m_DefaultVectUp);
00425         newCam.setDistEyeTarget(distEyeTarget());
00426         newCam.setDefaultUpVector(m_DefaultVectUp);
00427         return newCam;
00428 }
00429 
00431 // OpenGL Functions
00433 void GLC_Camera::glExecute()
00434 {
00435         GLC_Context::current()->glcMultMatrix(modelViewMatrix());
00436 }
00437 
00439 // Private services Functions
00441 
00442 void GLC_Camera::createMatComp(void)
00443 {
00444         const GLC_Vector3d forward((m_Target - m_Eye).normalize());
00445         const GLC_Vector3d side((forward ^ m_VectUp).normalize());
00446 
00447         // Update camera matrix
00448         m_ModelViewMatrix.setData()[0]= side.x();
00449         m_ModelViewMatrix.setData()[4]= side.y();
00450         m_ModelViewMatrix.setData()[8]= side.z();
00451         m_ModelViewMatrix.setData()[12]= 0.0;
00452 
00453         // Vector Up is Y Axis
00454         m_ModelViewMatrix.setData()[1]= m_VectUp.x();
00455         m_ModelViewMatrix.setData()[5]= m_VectUp.y();
00456         m_ModelViewMatrix.setData()[9]= m_VectUp.z();
00457         m_ModelViewMatrix.setData()[13]= 0.0;
00458 
00459         // Vector Cam is Z axis
00460         m_ModelViewMatrix.setData()[2]= - forward.x();
00461         m_ModelViewMatrix.setData()[6]= - forward.y();
00462         m_ModelViewMatrix.setData()[10]= - forward.z();
00463         m_ModelViewMatrix.setData()[14]= 0.0;
00464 
00465         m_ModelViewMatrix.setData()[3]= 0.0;
00466         m_ModelViewMatrix.setData()[7]= 0.0;
00467         m_ModelViewMatrix.setData()[11]= 0.0;
00468         m_ModelViewMatrix.setData()[15]= 1.0;
00469 
00470 }

SourceForge.net Logo

©2005-2011 Laurent Ribon