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

SourceForge.net Logo

©2005-2011 Laurent Ribon