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

SourceForge.net Logo

©2005 Laurent Ribon