GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_camera.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
5  Copyright (C) 2009 Laurent Bauer
6  http://glc-lib.sourceforge.net
7 
8  GLC-lib is free software; you can redistribute it and/or modify
9  it under the terms of the GNU Lesser General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  GLC-lib is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License
19  along with GLC-lib; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 *****************************************************************************/
23 
25 
26 #include "glc_camera.h"
27 #include "../glc_context.h"
28 
29 #include <QtDebug>
30 
31 using namespace glc;
33 // Constructor Destructor
36 : GLC_Object("Camera")
37 , m_Eye(0,0,1)
38 , m_Target()
39 , m_VectUp(Y_AXIS)
40 , m_ModelViewMatrix()
41 , m_DefaultVectUp(Y_AXIS)
42 {
43 
44 }
45 
46 GLC_Camera::GLC_Camera(const GLC_Point3d &Eye, const GLC_Point3d &Target, const GLC_Vector3d &Up)
47 : GLC_Object("Camera")
48 , m_Eye()
49 , m_Target()
50 , m_VectUp()
51 , m_ModelViewMatrix()
52 , m_DefaultVectUp(Y_AXIS)
53 {
54  setCam(Eye, Target, Up);
55  createMatComp();
56 }
57 
58 // Copy constructor
60 : GLC_Object(cam)
61 , m_Eye(cam.m_Eye)
62 , m_Target(cam.m_Target)
63 , m_VectUp(cam.m_VectUp)
64 , m_ModelViewMatrix(cam.m_ModelViewMatrix)
65 , m_DefaultVectUp(cam.m_DefaultVectUp)
66 {
67 
68 }
69 
71 // Get Functions
73 
74 // equality operator
75 bool GLC_Camera::operator==(const GLC_Camera& cam) const
76 {
77  return (m_Eye == cam.m_Eye) && (m_Target == cam.m_Target)
78  && (m_VectUp == cam.m_VectUp) && (m_DefaultVectUp == cam.m_DefaultVectUp);
79 }
80 
81 
83 // Set Functions
86 {
87  // Map Vectors
89  invMat.invert();
90  VectOldPoss= invMat * VectOldPoss;
91  VectCurPoss= invMat * VectCurPoss;
92 
93  // Compute rotation matrix
94  const GLC_Vector3d VectAxeRot(VectCurPoss ^ VectOldPoss);
95  // Check if rotation vector is not null
96  if (!VectAxeRot.isNull())
97  { // Ok, is not null
98  const double Angle= acos(VectCurPoss * VectOldPoss);
99  const GLC_Matrix4x4 MatOrbit(VectAxeRot, Angle);
100 
101  // Camera transformation
102  m_Eye= (MatOrbit * (m_Eye - m_Target)) + m_Target;
103  m_VectUp= MatOrbit * m_VectUp;
104  createMatComp();
105  }
106 
107  return *this;
108 }
109 
111 {
112  // Vector mapping
114  invMat.invert();
115  VectDep= invMat * VectDep;
116 
117  // Camera transformation
118  m_Eye= m_Eye + VectDep;
119  m_Target= m_Target + VectDep;
120 
121  return *this;
122 }
123 
125 {
126  Q_ASSERT(factor > 0);
127  // Eye->target vector
128  GLC_Vector3d VectCam(m_Eye - m_Target);
129 
130  // Compute new vector length
131  const double Norme= VectCam.length() * 1 / factor;
132  VectCam.setLength(Norme);
133 
134  m_Eye= VectCam + m_Target;
135 
136  return *this;
137 }
138 
139 // Move camera
141 {
142  m_Eye= MatMove * m_Eye;
143  m_Target= MatMove * m_Target;
144  m_VectUp= MatMove.rotationMatrix() * m_VectUp;
145  createMatComp();
146 
147  return *this;
148 }
149 
150 // Rotate around an axis
151 GLC_Camera& GLC_Camera::rotateAround(const GLC_Vector3d& axis, const double& angle, const GLC_Point3d& point)
152 {
153  const GLC_Matrix4x4 rotationMatrix(axis, angle);
154  translate(-point);
155  move(rotationMatrix);
156  translate(point);
157 
158  return *this;
159 }
160 
161 // Rotate around camera target
162 GLC_Camera& GLC_Camera::rotateAroundTarget(const GLC_Vector3d& axis, const double& angle)
163 {
165  rotateAround(axis, angle, target);
166 
167  return *this;
168 }
169 
171 {
172  m_Eye= m_Eye + VectTrans;
173  m_Target= m_Target + VectTrans;
174 
175  return *this;
176 }
177 
179 {
180  // Old camera's vector
181  GLC_Vector3d VectOldCam(m_Eye - m_Target);
182  // New camera's vector
183  GLC_Vector3d VectCam(Eye - m_Target);
184  if ( !(VectOldCam - VectCam).isNull() )
185  {
186  VectOldCam.setLength(1);
187  VectCam.setLength(1);
188  const double Angle= acos(VectOldCam * VectCam);
189  if ( !qFuzzyCompare(Angle, 0.0) && !qFuzzyCompare(PI - Angle, 0.0))
190  {
191  const GLC_Vector3d VectAxeRot(VectOldCam ^ VectCam);
192  const GLC_Matrix4x4 MatRot(VectAxeRot, Angle);
193  m_VectUp= MatRot * m_VectUp;
194  }
195  else
196  {
197  if ( qFuzzyCompare(PI - Angle, 0.0))
198  { // Angle de 180%
199  m_VectUp.invert();
200  }
201  }
202 
203  setCam(Eye, m_Target, m_VectUp);
204  }
205 
206  return *this;
207 }
208 
210 {
211  // Old camera's vector
212  GLC_Vector3d VectOldCam(m_Eye - m_Target);
213  // New camera's vector
214  GLC_Vector3d VectCam(m_Eye - Target);
215  if ( !(VectOldCam - VectCam).isNull() )
216  {
217  VectOldCam.setLength(1);
218  VectCam.setLength(1);
219  const double Angle= acos(VectOldCam * VectCam);
220  if ( !qFuzzyCompare(Angle, 0.0) && !qFuzzyCompare(PI - Angle, 0.0))
221  {
222  const GLC_Vector3d VectAxeRot(VectOldCam ^ VectCam);
223  const GLC_Matrix4x4 MatRot(VectAxeRot, Angle);
224  m_VectUp= MatRot * m_VectUp;
225  }
226  else
227  {
228  if ( qFuzzyCompare(PI - Angle, 0.0))
229  { // Angle of 180%
230  m_VectUp.invert();
231  }
232  }
233 
234  setCam(m_Eye, Target, m_VectUp);
235  }
236 
237  return *this;
238 }
239 
241 {
242  if ( !(m_VectUp - Up).isNull() )
243  {
244  if (!qFuzzyCompare(forward().angleWithVect(Up), 0.0))
245  {
246  setCam(m_Eye, m_Target, Up);
247  }
248  }
249 
250  return *this;
251 }
252 
254 {
255  Up.setLength(1);
256 
257  const GLC_Vector3d VectCam((Eye - Target).setLength(1));
258  const double Angle= acos(VectCam * Up);
259 
260  /* m_VectUp and VectCam could not be parallel
261  * m_VectUp could not be NULL
262  * VectCam could not be NULL */
263  //Q_ASSERT((Angle > EPSILON) && ((PI - Angle) > EPSILON));
264 
265  if ( !qFuzzyCompare(Angle - (PI / 2), 0.0))
266  { // Angle not equal to 90
267  const GLC_Vector3d AxeRot(VectCam ^ Up);
268  GLC_Matrix4x4 MatRot(AxeRot, PI / 2);
269  Up= MatRot * VectCam;
270  }
271 
272  m_Eye= Eye;
273  m_Target= Target;
274  m_VectUp= Up;
275  createMatComp();
276 
277  return *this;
278 }
279 
282 {
283  m_Eye= cam.m_Eye;
284  m_Target= cam.m_Target;
285  m_VectUp= cam.m_VectUp;
287 
288  return *this;
289 }
290 
291 
293 {
294  GLC_Vector3d VectCam(forward());
295  VectCam.setLength(Longueur);
296  m_Eye= m_Target - VectCam;
297 
298  return *this;
299 }
301 {
302  GLC_Vector3d VectCam(forward());
303  VectCam.setLength(Longueur);
304  m_Target= m_Eye + VectCam;
305 
306  return *this;
307 }
308 
309 // Assignment operator
311 {
313  m_Eye= cam.m_Eye;
314  m_Target= cam.m_Target;
315  m_VectUp= cam.m_VectUp;
318 
319  return *this;
320 }
321 // almost equality (Bauer Laurent)
322 bool GLC_Camera::isAlmostEqualTo(const GLC_Camera& cam, const double distanceAccuracy) const
323 {
324  GLC_Vector3d incident1 = m_Target - m_Eye;
325  GLC_Vector3d incident2 = cam.m_Target - cam.m_Eye;
326 
327  double allowedGap = incident1.length() * distanceAccuracy;
328  GLC_Point3d left1 = incident1 ^ m_VectUp;
329  GLC_Point3d left2 = incident2 ^ cam.m_VectUp;
330 
331  return ((m_Eye - cam.m_Eye).length() < allowedGap ) && ( (m_Target - cam.m_Target).length() < allowedGap)
332  && ((left1 - left2).length() < allowedGap) ;
333 }
334 
335 // Return the standard front view form this camera
337 {
339 
341  {
342  eye.setVect(0.0, -1.0, 0.0);
343  }
344  else // Y_AXIS or X_AXIS
345  {
346  eye.setVect(0.0, 0.0, 1.0);
347  }
348  eye= eye + m_Target;
349 
350  GLC_Camera newCam(eye, m_Target, m_DefaultVectUp);
353  return newCam;
354 }
355 
356 // Return the standard rear view form this camera
358 {
360 }
361 
362 // Return the standard right view form this camera
364 {
366 
367 // Return the standard left view form this camera
369 {
371 }
372 
373 // Return the standard top view form this camera
375 {
377  eye= eye + m_Target;
378  GLC_Vector3d up;
379 
381  {
382  up.setVect(0.0, 0.0, -1.0);
383  }
384  else // Z_AXIS or X_AXIS
385  {
386  up.setVect(0.0, 1.0, 0.0);
387  }
388 
389  GLC_Camera newCam(eye, m_Target, up);
392 
393  return newCam;
394 }
395 
396 // Return the standard bottom view form this camera
398 {
399  GLC_Camera newCam(topView());
400  newCam.rotateAroundTarget(newCam.upVector(), glc::PI);
401 
402  return newCam;
403 }
404 
405 // Return the standard isoview from his camera
407 {
410  {
411  eye.setVect(-1.0, -1.0, 1.0);
412  }
413  else if (m_DefaultVectUp == glc::Y_AXIS)
414  {
415  eye.setVect(-1.0, 1.0, 1.0);
416  }
417  else
418  {
419  eye.setVect(1.0, 1.0, 1.0);
420  }
421 
422  eye= eye + m_Target;
423 
424  GLC_Camera newCam(eye, m_Target, m_DefaultVectUp);
427  return newCam;
428 }
429 
431 // OpenGL Functions
434 {
436 }
437 
439 // Private services Functions
441 
443 {
445  const GLC_Vector3d side((forward ^ m_VectUp).normalize());
446 
447  // Update camera matrix
448  m_ModelViewMatrix.setData()[0]= side.x();
449  m_ModelViewMatrix.setData()[4]= side.y();
450  m_ModelViewMatrix.setData()[8]= side.z();
451  m_ModelViewMatrix.setData()[12]= 0.0;
452 
453  // Vector Up is Y Axis
454  m_ModelViewMatrix.setData()[1]= m_VectUp.x();
455  m_ModelViewMatrix.setData()[5]= m_VectUp.y();
456  m_ModelViewMatrix.setData()[9]= m_VectUp.z();
457  m_ModelViewMatrix.setData()[13]= 0.0;
458 
459  // Vector Cam is Z axis
460  m_ModelViewMatrix.setData()[2]= - forward.x();
461  m_ModelViewMatrix.setData()[6]= - forward.y();
462  m_ModelViewMatrix.setData()[10]= - forward.z();
463  m_ModelViewMatrix.setData()[14]= 0.0;
464 
465  m_ModelViewMatrix.setData()[3]= 0.0;
466  m_ModelViewMatrix.setData()[7]= 0.0;
467  m_ModelViewMatrix.setData()[11]= 0.0;
468  m_ModelViewMatrix.setData()[15]= 1.0;
469 
470 }

©2005-2013 Laurent Ribon