camera.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  Copyright (C) 2002-2014 Gilles Debunne. All rights reserved.
4 
5  This file is part of the QGLViewer library version 2.6.3.
6 
7  http://www.libqglviewer.com - contact@libqglviewer.com
8 
9  This file may be used under the terms of the GNU General Public License
10  versions 2.0 or 3.0 as published by the Free Software Foundation and
11  appearing in the LICENSE file included in the packaging of this file.
12  In addition, as a special exception, Gilles Debunne gives you certain
13  additional rights, described in the file GPL_EXCEPTION in this package.
14 
15  libQGLViewer uses dual licensing. Commercial/proprietary software must
16  purchase a libQGLViewer Commercial License.
17 
18  This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
19  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 
21 *****************************************************************************/
22 
23 #include "domUtils.h"
24 #include "camera.h"
25 #include "qglviewer.h"
26 #include "manipulatedCameraFrame.h"
27 
28 using namespace std;
29 using namespace qglviewer;
30 
38 Camera::Camera()
39  : frame_(NULL), fieldOfView_(M_PI/4.0), modelViewMatrixIsUpToDate_(false), projectionMatrixIsUpToDate_(false)
40 {
41  // #CONNECTION# Camera copy constructor
43  // Requires the interpolationKfi_
45 
46  // #CONNECTION# All these default values identical in initFromDOMElement.
47 
48  // Requires fieldOfView() to define focusDistance()
49  setSceneRadius(1.0);
50 
51  // Initial value (only scaled after this)
52  orthoCoef_ = tan(fieldOfView()/2.0);
53 
54  // Also defines the pivotPoint(), which changes orthoCoef_. Requires a frame().
55  setSceneCenter(Vec(0.0, 0.0, 0.0));
56 
57  // Requires fieldOfView() when called with ORTHOGRAPHIC. Attention to projectionMatrix_ below.
59 
60  // #CONNECTION# initFromDOMElement default values
61  setZNearCoefficient(0.005);
62  setZClippingCoefficient(sqrt(3.0));
63 
64  // Dummy values
65  setScreenWidthAndHeight(600, 400);
66 
67  // Stereo parameters
68  setIODistance(0.062);
70  // focusDistance is set from setFieldOfView()
71 
72  // #CONNECTION# Camera copy constructor
73  for (unsigned short j=0; j<16; ++j)
74  {
75  modelViewMatrix_[j] = ((j%5 == 0) ? 1.0 : 0.0);
76  // #CONNECTION# computeProjectionMatrix() is lazy and assumes 0.0 almost everywhere.
77  projectionMatrix_[j] = 0.0;
78  }
80 }
81 
87 {
88  delete frame_;
89  delete interpolationKfi_;
90 }
91 
92 
94 Camera::Camera(const Camera& camera)
95  : QObject(), frame_(NULL)
96 {
97  // #CONNECTION# Camera constructor
99  // Requires the interpolationKfi_
100  setFrame(new ManipulatedCameraFrame(*camera.frame()));
101 
102  for (unsigned short j=0; j<16; ++j)
103  {
104  modelViewMatrix_[j] = ((j%5 == 0) ? 1.0 : 0.0);
105  // #CONNECTION# computeProjectionMatrix() is lazy and assumes 0.0 almost everywhere.
106  projectionMatrix_[j] = 0.0;
107  }
108 
109  (*this)=camera;
110 }
111 
125 {
127  setFieldOfView(camera.fieldOfView());
128  setSceneRadius(camera.sceneRadius());
129  setSceneCenter(camera.sceneCenter());
132  setType(camera.type());
133 
134  // Stereo parameters
135  setIODistance(camera.IODistance());
138 
139  orthoCoef_ = camera.orthoCoef_;
141 
142  // frame_ and interpolationKfi_ pointers are not shared.
143  frame_->setReferenceFrame(NULL);
144  frame_->setPosition(camera.position());
145  frame_->setOrientation(camera.orientation());
146 
148 
149  kfi_ = camera.kfi_;
150 
153 
154  return *this;
155 }
156 
166 void Camera::setScreenWidthAndHeight(int width, int height)
167 {
168  // Prevent negative and zero dimensions that would cause divisions by zero.
169  screenWidth_ = width > 0 ? width : 1;
170  screenHeight_ = height > 0 ? height : 1;
172 }
173 
211 qreal Camera::zNear() const
212 {
213  const qreal zNearScene = zClippingCoefficient() * sceneRadius();
214  qreal z = distanceToSceneCenter() - zNearScene;
215 
216  // Prevents negative or null zNear values.
217  const qreal zMin = zNearCoefficient() * zNearScene;
218  if (z < zMin)
219  switch (type())
220  {
221  case Camera::PERSPECTIVE : z = zMin; break;
222  case Camera::ORTHOGRAPHIC : z = 0.0; break;
223  }
224  return z;
225 }
226 
236 qreal Camera::zFar() const
237 {
239 }
240 
241 
245 void Camera::setFieldOfView(qreal fov) {
246  fieldOfView_ = fov;
247  setFocusDistance(sceneRadius() / tan(fov/2.0));
249 }
250 
262 {
263  // make ORTHOGRAPHIC frustum fit PERSPECTIVE (at least in plane normal to viewDirection(), passing
264  // through RAP). Done only when CHANGING type since orthoCoef_ may have been changed with a
265  // setPivotPoint() in the meantime.
266  if ( (type == Camera::ORTHOGRAPHIC) && (type_ == Camera::PERSPECTIVE) )
267  orthoCoef_ = tan(fieldOfView()/2.0);
268  type_ = type;
270 }
271 
286 {
287  if (!mcf)
288  return;
289 
290  if (frame_) {
291  disconnect(frame_, SIGNAL(modified()), this, SLOT(onFrameModified()));
292  }
293 
294  frame_ = mcf;
296 
297  connect(frame_, SIGNAL(modified()), this, SLOT(onFrameModified()));
298  onFrameModified();
299 }
300 
304 {
305  return fabs((frame()->coordinatesOf(sceneCenter())).z);
306 }
307 
308 
324 void Camera::getOrthoWidthHeight(GLdouble& halfWidth, GLdouble& halfHeight) const
325 {
326  const qreal dist = orthoCoef_ * fabs(cameraCoordinatesOf(pivotPoint()).z);
327  //#CONNECTION# fitScreenRegion
328  halfWidth = dist * ((aspectRatio() < 1.0) ? 1.0 : aspectRatio());
329  halfHeight = dist * ((aspectRatio() < 1.0) ? 1.0/aspectRatio() : 1.0);
330 }
331 
332 
351 {
352  if (projectionMatrixIsUpToDate_) return;
353 
354  const qreal ZNear = zNear();
355  const qreal ZFar = zFar();
356 
357  switch (type())
358  {
359  case Camera::PERSPECTIVE:
360  {
361  // #CONNECTION# all non null coefficients were set to 0.0 in constructor.
362  const qreal f = 1.0/tan(fieldOfView()/2.0);
364  projectionMatrix_[5] = f;
365  projectionMatrix_[10] = (ZNear + ZFar) / (ZNear - ZFar);
366  projectionMatrix_[11] = -1.0;
367  projectionMatrix_[14] = 2.0 * ZNear * ZFar / (ZNear - ZFar);
368  projectionMatrix_[15] = 0.0;
369  // same as gluPerspective( 180.0*fieldOfView()/M_PI, aspectRatio(), zNear(), zFar() );
370  break;
371  }
373  {
374  GLdouble w, h;
375  getOrthoWidthHeight(w,h);
376  projectionMatrix_[0] = 1.0/w;
377  projectionMatrix_[5] = 1.0/h;
378  projectionMatrix_[10] = -2.0/(ZFar - ZNear);
379  projectionMatrix_[11] = 0.0;
380  projectionMatrix_[14] = -(ZFar + ZNear)/(ZFar - ZNear);
381  projectionMatrix_[15] = 1.0;
382  // same as glOrtho( -w, w, -h, h, zNear(), zFar() );
383  break;
384  }
385  }
386 
388 }
389 
401 {
402  if (modelViewMatrixIsUpToDate_) return;
403 
404  const Quaternion q = frame()->orientation();
405 
406  const qreal q00 = 2.0 * q[0] * q[0];
407  const qreal q11 = 2.0 * q[1] * q[1];
408  const qreal q22 = 2.0 * q[2] * q[2];
409 
410  const qreal q01 = 2.0 * q[0] * q[1];
411  const qreal q02 = 2.0 * q[0] * q[2];
412  const qreal q03 = 2.0 * q[0] * q[3];
413 
414  const qreal q12 = 2.0 * q[1] * q[2];
415  const qreal q13 = 2.0 * q[1] * q[3];
416 
417  const qreal q23 = 2.0 * q[2] * q[3];
418 
419  modelViewMatrix_[0] = 1.0 - q11 - q22;
420  modelViewMatrix_[1] = q01 - q23;
421  modelViewMatrix_[2] = q02 + q13;
422  modelViewMatrix_[3] = 0.0;
423 
424  modelViewMatrix_[4] = q01 + q23;
425  modelViewMatrix_[5] = 1.0 - q22 - q00;
426  modelViewMatrix_[6] = q12 - q03;
427  modelViewMatrix_[7] = 0.0;
428 
429  modelViewMatrix_[8] = q02 - q13;
430  modelViewMatrix_[9] = q12 + q03;
431  modelViewMatrix_[10] = 1.0 - q11 - q00;
432  modelViewMatrix_[11] = 0.0;
433 
434  const Vec t = q.inverseRotate(frame()->position());
435 
436  modelViewMatrix_[12] = -t.x;
437  modelViewMatrix_[13] = -t.y;
438  modelViewMatrix_[14] = -t.z;
439  modelViewMatrix_[15] = 1.0;
440 
442 }
443 
444 
463 void Camera::loadProjectionMatrix(bool reset) const
464 {
465  // WARNING: makeCurrent must be called by every calling method
466  glMatrixMode(GL_PROJECTION);
467 
468  if (reset)
469  glLoadIdentity();
470 
472 
473  glMultMatrixd(projectionMatrix_);
474 }
475 
500 void Camera::loadModelViewMatrix(bool reset) const
501 {
502  // WARNING: makeCurrent must be called by every calling method
503  glMatrixMode(GL_MODELVIEW);
505  if (reset)
506  glLoadMatrixd(modelViewMatrix_);
507  else
508  glMultMatrixd(modelViewMatrix_);
509 }
510 
536 void Camera::loadProjectionMatrixStereo(bool leftBuffer) const
537 {
538  qreal left, right, bottom, top;
539  qreal screenHalfWidth, halfWidth, side, shift, delta;
540 
541  glMatrixMode(GL_PROJECTION);
542  glLoadIdentity();
543 
544  switch (type())
545  {
546  case Camera::PERSPECTIVE:
547  // compute half width of screen,
548  // corresponding to zero parallax plane to deduce decay of cameras
549  screenHalfWidth = focusDistance() * tan(horizontalFieldOfView() / 2.0);
550  shift = screenHalfWidth * IODistance() / physicalScreenWidth();
551  // should be * current y / y total
552  // to take into account that the window doesn't cover the entire screen
553 
554  // compute half width of "view" at znear and the delta corresponding to
555  // the shifted camera to deduce what to set for asymmetric frustums
556  halfWidth = zNear() * tan(horizontalFieldOfView() / 2.0);
557  delta = shift * zNear() / focusDistance();
558  side = leftBuffer ? -1.0 : 1.0;
559 
560  left = -halfWidth + side * delta;
561  right = halfWidth + side * delta;
562  top = halfWidth / aspectRatio();
563  bottom = -top;
564  glFrustum(left, right, bottom, top, zNear(), zFar() );
565  break;
566 
568  qWarning("Camera::setProjectionMatrixStereo: Stereo not available with Ortho mode");
569  break;
570  }
571 }
572 
591 void Camera::loadModelViewMatrixStereo(bool leftBuffer) const
592 {
593  // WARNING: makeCurrent must be called by every calling method
594  glMatrixMode(GL_MODELVIEW);
595 
596  qreal halfWidth = focusDistance() * tan(horizontalFieldOfView() / 2.0);
597  qreal shift = halfWidth * IODistance() / physicalScreenWidth(); // * current window width / full screen width
598 
600  if (leftBuffer)
601  modelViewMatrix_[12] -= shift;
602  else
603  modelViewMatrix_[12] += shift;
604  glLoadMatrixd(modelViewMatrix_);
605 }
606 
621 void Camera::getProjectionMatrix(GLdouble m[16]) const
622 {
624  for (unsigned short i=0; i<16; ++i)
625  m[i] = projectionMatrix_[i];
626 }
627 
629 void Camera::getProjectionMatrix(GLfloat m[16]) const
630 {
631  static GLdouble mat[16];
632  getProjectionMatrix(mat);
633  for (unsigned short i=0; i<16; ++i)
634  m[i] = float(mat[i]);
635 }
636 
651 void Camera::getModelViewMatrix(GLdouble m[16]) const
652 {
653  // May not be needed, but easier like this.
654  // Prevents from retrieving matrix in stereo mode -> overwrites shifted value.
656  for (unsigned short i=0; i<16; ++i)
657  m[i] = modelViewMatrix_[i];
658 }
659 
660 
662 void Camera::getModelViewMatrix(GLfloat m[16]) const
663 {
664  static GLdouble mat[16];
665  getModelViewMatrix(mat);
666  for (unsigned short i=0; i<16; ++i)
667  m[i] = float(mat[i]);
668 }
669 
673 void Camera::getModelViewProjectionMatrix(GLdouble m[16]) const
674 {
675  GLdouble mv[16];
676  GLdouble proj[16];
677  getModelViewMatrix(mv);
678  getProjectionMatrix(proj);
679 
680  for (unsigned short i=0; i<4; ++i)
681  {
682  for (unsigned short j=0; j<4; ++j)
683  {
684  qreal sum = 0.0;
685  for (unsigned short k=0; k<4; ++k)
686  sum += proj[i+4*k]*mv[k+4*j];
687  m[i+4*j] = sum;
688  }
689  }
690 }
691 
693 void Camera::getModelViewProjectionMatrix(GLfloat m[16]) const
694 {
695  static GLdouble mat[16];
697  for (unsigned short i=0; i<16; ++i)
698  m[i] = float(mat[i]);
699 }
700 
705 void Camera::setSceneRadius(qreal radius)
706 {
707  if (radius <= 0.0)
708  {
709  qWarning("Scene radius must be positive - Ignoring value");
710  return;
711  }
712 
713  sceneRadius_ = radius;
715 
716  setFocusDistance(sceneRadius() / tan(fieldOfView()/2.0));
717 
718  frame()->setFlySpeed(0.01*sceneRadius());
719 }
720 
723 void Camera::setSceneBoundingBox(const Vec& min, const Vec& max)
724 {
725  setSceneCenter((min+max)/2.0);
726  setSceneRadius(0.5*(max-min).norm());
727 }
728 
729 
733 void Camera::setSceneCenter(const Vec& center)
734 {
735  sceneCenter_ = center;
738 }
739 
745 bool Camera::setSceneCenterFromPixel(const QPoint& pixel)
746 {
747  bool found;
748  Vec point = pointUnderPixel(pixel, found);
749  if (found)
750  setSceneCenter(point);
751  return found;
752 }
753 
754 #ifndef DOXYGEN
755 void Camera::setRevolveAroundPoint(const Vec& point) {
756  qWarning("setRevolveAroundPoint() is deprecated, use setPivotPoint() instead");
757  setPivotPoint(point);
758 }
759 bool Camera::setRevolveAroundPointFromPixel(const QPoint& pixel) {
760  qWarning("setRevolveAroundPointFromPixel() is deprecated, use setPivotPointFromPixel() instead");
761  return setPivotPointFromPixel(pixel);
762 }
764  qWarning("revolveAroundPoint() is deprecated, use pivotPoint() instead");
765  return pivotPoint();
766 }
767 #endif
768 
770 void Camera::setPivotPoint(const Vec& point)
771 {
772  const qreal prevDist = fabs(cameraCoordinatesOf(pivotPoint()).z);
773 
774  // If frame's RAP is set directly, projectionMatrixIsUpToDate_ should also be
775  // set to false to ensure proper recomputation of the ORTHO projection matrix.
776  frame()->setPivotPoint(point);
777 
778  // orthoCoef_ is used to compensate for changes of the pivotPoint, so that the image does
779  // not change when the pivotPoint is changed in ORTHOGRAPHIC mode.
780  const qreal newDist = fabs(cameraCoordinatesOf(pivotPoint()).z);
781  // Prevents division by zero when rap is set to camera position
782  if ((prevDist > 1E-9) && (newDist > 1E-9))
783  orthoCoef_ *= prevDist / newDist;
785 }
786 
796 bool Camera::setPivotPointFromPixel(const QPoint& pixel)
797 {
798  bool found;
799  Vec point = pointUnderPixel(pixel, found);
800  if (found)
801  setPivotPoint(point);
802  return found;
803 }
804 
819 qreal Camera::pixelGLRatio(const Vec& position) const
820 {
821  switch (type())
822  {
823  case Camera::PERSPECTIVE :
824  return 2.0 * fabs((frame()->coordinatesOf(position)).z) * tan(fieldOfView()/2.0) / screenHeight();
825  case Camera::ORTHOGRAPHIC :
826  {
827  GLdouble w, h;
828  getOrthoWidthHeight(w,h);
829  return 2.0 * h / screenHeight();
830  }
831  }
832  // Bad compilers complain
833  return 1.0;
834 }
835 
862 {
863  if (distanceToSceneCenter() > sqrt(2.0)*sceneRadius())
865  else
866  setFieldOfView(M_PI / 2.0);
867 }
868 
875 void Camera::interpolateToZoomOnPixel(const QPoint& pixel)
876 {
877  const qreal coef = 0.1;
878 
879  bool found;
880  Vec target = pointUnderPixel(pixel, found);
881 
882  if (!found)
883  return;
884 
887 
890 
891  interpolationKfi_->addKeyFrame(Frame(0.3*frame()->position() + 0.7*target, frame()->orientation()), 0.4);
892 
893  // Small hack: attach a temporary frame to take advantage of lookAt without modifying frame
894  static ManipulatedCameraFrame* tempFrame = new ManipulatedCameraFrame();
895  ManipulatedCameraFrame* const originalFrame = frame();
896  tempFrame->setPosition(coef*frame()->position() + (1.0-coef)*target);
897  tempFrame->setOrientation(frame()->orientation());
898  setFrame(tempFrame);
899  lookAt(target);
900  setFrame(originalFrame);
901 
902  interpolationKfi_->addKeyFrame(*(tempFrame), 1.0);
903 
905 }
906 
914 {
917 
920 
921  // Small hack: attach a temporary frame to take advantage of lookAt without modifying frame
922  static ManipulatedCameraFrame* tempFrame = new ManipulatedCameraFrame();
923  ManipulatedCameraFrame* const originalFrame = frame();
924  tempFrame->setPosition(frame()->position());
925  tempFrame->setOrientation(frame()->orientation());
926  setFrame(tempFrame);
927  showEntireScene();
928  setFrame(originalFrame);
929 
930  interpolationKfi_->addKeyFrame(*(tempFrame));
931 
933 }
934 
935 
942 void Camera::interpolateTo(const Frame& fr, qreal duration)
943 {
946 
949  interpolationKfi_->addKeyFrame(fr, duration);
950 
952 }
953 
954 
971 Vec Camera::pointUnderPixel(const QPoint& pixel, bool& found) const
972 {
973  float depth;
974  // Qt uses upper corner for its origin while GL uses the lower corner.
975  glReadPixels(pixel.x(), screenHeight()-1-pixel.y(), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
976  found = depth < 1.0;
977  Vec point(pixel.x(), pixel.y(), depth);
978  point = unprojectedCoordinatesOf(point);
979  return point;
980 }
981 
988 {
990 }
991 
998 {
1000 }
1001 
1008 void Camera::lookAt(const Vec& target)
1009 {
1010  setViewDirection(target - position());
1011 }
1012 
1020 void Camera::fitSphere(const Vec& center, qreal radius)
1021 {
1022  qreal distance = 0.0;
1023  switch (type())
1024  {
1025  case Camera::PERSPECTIVE :
1026  {
1027  const qreal yview = radius / sin(fieldOfView() / 2.0);
1028  const qreal xview = radius / sin(horizontalFieldOfView() / 2.0);
1029  distance = qMax(xview, yview);
1030  break;
1031  }
1032  case Camera::ORTHOGRAPHIC :
1033  {
1034  distance = ((center-pivotPoint()) * viewDirection()) + (radius / orthoCoef_);
1035  break;
1036  }
1037  }
1038  Vec newPos(center - distance * viewDirection());
1039  frame()->setPositionWithConstraint(newPos);
1040 }
1041 
1044 void Camera::fitBoundingBox(const Vec& min, const Vec& max)
1045 {
1046  qreal diameter = qMax(fabs(max[1]-min[1]), fabs(max[0]-min[0]));
1047  diameter = qMax(fabs(max[2]-min[2]), diameter);
1048  fitSphere(0.5*(min+max), 0.5*diameter);
1049 }
1050 
1058 void Camera::fitScreenRegion(const QRect& rectangle)
1059 {
1060  const Vec vd = viewDirection();
1061  const qreal distToPlane = distanceToSceneCenter();
1062  const QPoint center = rectangle.center();
1063 
1064  Vec orig, dir;
1065  convertClickToLine( center, orig, dir );
1066  Vec newCenter = orig + distToPlane / (dir*vd) * dir;
1067 
1068  convertClickToLine( QPoint(rectangle.x(), center.y()), orig, dir );
1069  const Vec pointX = orig + distToPlane / (dir*vd) * dir;
1070 
1071  convertClickToLine( QPoint(center.x(), rectangle.y()), orig, dir );
1072  const Vec pointY = orig + distToPlane / (dir*vd) * dir;
1073 
1074  qreal distance = 0.0;
1075  switch (type())
1076  {
1077  case Camera::PERSPECTIVE :
1078  {
1079  const qreal distX = (pointX-newCenter).norm() / sin(horizontalFieldOfView()/2.0);
1080  const qreal distY = (pointY-newCenter).norm() / sin(fieldOfView()/2.0);
1081  distance = qMax(distX, distY);
1082  break;
1083  }
1084  case Camera::ORTHOGRAPHIC :
1085  {
1086  const qreal dist = ((newCenter-pivotPoint()) * vd);
1087  //#CONNECTION# getOrthoWidthHeight
1088  const qreal distX = (pointX-newCenter).norm() / orthoCoef_ / ((aspectRatio() < 1.0) ? 1.0 : aspectRatio());
1089  const qreal distY = (pointY-newCenter).norm() / orthoCoef_ / ((aspectRatio() < 1.0) ? 1.0/aspectRatio() : 1.0);
1090  distance = dist + qMax(distX, distY);
1091  break;
1092  }
1093  }
1094 
1095  Vec newPos(newCenter - distance * vd);
1096  frame()->setPositionWithConstraint(newPos);
1097 }
1098 
1116 void Camera::setUpVector(const Vec& up, bool noMove)
1117 {
1118  Quaternion q(Vec(0.0, 1.0, 0.0), frame()->transformOf(up));
1119 
1120  if (!noMove)
1121  frame()->setPosition(pivotPoint() - (frame()->orientation()*q).rotate(frame()->coordinatesOf(pivotPoint())));
1122 
1123  frame()->rotate(q);
1124 
1125  // Useful in fly mode to keep the horizontal direction.
1127 }
1128 
1140 void Camera::setOrientation(qreal theta, qreal phi)
1141 {
1142  Vec axis(0.0, 1.0, 0.0);
1143  const Quaternion rot1(axis, theta);
1144  axis = Vec(-cos(theta), 0.0, sin(theta));
1145  const Quaternion rot2(axis, phi);
1146  setOrientation(rot1 * rot2);
1147 }
1148 
1151 {
1152  frame()->setOrientation(q);
1154 }
1155 
1161 void Camera::setViewDirection(const Vec& direction)
1162 {
1163  if (direction.squaredNorm() < 1E-10)
1164  return;
1165 
1166  Vec xAxis = direction ^ upVector();
1167  if (xAxis.squaredNorm() < 1E-10)
1168  {
1169  // target is aligned with upVector, this means a rotation around X axis
1170  // X axis is then unchanged, let's keep it !
1171  xAxis = frame()->inverseTransformOf(Vec(1.0, 0.0, 0.0));
1172  }
1173 
1174  Quaternion q;
1175  q.setFromRotatedBasis(xAxis, xAxis^direction, -direction);
1177 }
1178 
1179 // Compute a 3 by 3 determinant.
1180 static qreal det(qreal m00,qreal m01,qreal m02,
1181  qreal m10,qreal m11,qreal m12,
1182  qreal m20,qreal m21,qreal m22)
1183 {
1184  return m00*m11*m22 + m01*m12*m20 + m02*m10*m21 - m20*m11*m02 - m10*m01*m22 - m00*m21*m12;
1185 }
1186 
1187 // Computes the index of element [i][j] in a \c qreal matrix[3][4].
1188 static inline unsigned int ind(unsigned int i, unsigned int j)
1189 {
1190  return (i*4+j);
1191 }
1192 
1200 Vec Camera::position() const { return frame()->position(); }
1201 
1210 {
1211  return frame()->inverseTransformOf(Vec(0.0, 1.0, 0.0));
1212 }
1220 Vec Camera::viewDirection() const { return frame()->inverseTransformOf(Vec(0.0, 0.0, -1.0)); }
1221 
1229 {
1230  return frame()->inverseTransformOf(Vec(1.0, 0.0, 0.0));
1231 }
1232 
1238 
1240 void Camera::setPosition(const Vec& pos) { frame()->setPosition(pos); }
1241 
1248 Vec Camera::cameraCoordinatesOf(const Vec& src) const { return frame()->coordinatesOf(src); }
1249 
1254 Vec Camera::worldCoordinatesOf(const Vec& src) const { return frame()->inverseCoordinatesOf(src); }
1255 
1263 qreal Camera::flySpeed() const { return frame()->flySpeed(); }
1264 
1268 void Camera::setFlySpeed(qreal speed) { frame()->setFlySpeed(speed); }
1269 
1275 Vec Camera::pivotPoint() const { return frame()->pivotPoint(); }
1276 
1294 void Camera::setFromModelViewMatrix(const GLdouble* const modelViewMatrix)
1295 {
1296  // Get upper left (rotation) matrix
1297  qreal upperLeft[3][3];
1298  for (int i=0; i<3; ++i)
1299  for (int j=0; j<3; ++j)
1300  upperLeft[i][j] = modelViewMatrix[i*4+j];
1301 
1302  // Transform upperLeft into the associated Quaternion
1303  Quaternion q;
1304  q.setFromRotationMatrix(upperLeft);
1305 
1306  setOrientation(q);
1307  setPosition(-q.rotate(Vec(modelViewMatrix[12], modelViewMatrix[13], modelViewMatrix[14])));
1308 }
1309 
1332 void Camera::setFromProjectionMatrix(const qreal matrix[12])
1333 {
1334  // The 3 lines of the matrix are the normals to the planes x=0, y=0, z=0
1335  // in the camera CS. As we normalize them, we do not need the 4th coordinate.
1336  Vec line_0(matrix[ind(0,0)],matrix[ind(0,1)],matrix[ind(0,2)]);
1337  Vec line_1(matrix[ind(1,0)],matrix[ind(1,1)],matrix[ind(1,2)]);
1338  Vec line_2(matrix[ind(2,0)],matrix[ind(2,1)],matrix[ind(2,2)]);
1339 
1340  line_0.normalize();
1341  line_1.normalize();
1342  line_2.normalize();
1343 
1344  // The camera position is at (0,0,0) in the camera CS so it is the
1345  // intersection of the 3 planes. It can be seen as the kernel
1346  // of the 3x4 projection matrix. We calculate it through 4 dimensional
1347  // vectorial product. We go directly into 3D that is to say we directly
1348  // divide the first 3 coordinates by the 4th one.
1349 
1350  // We derive the 4 dimensional vectorial product formula from the
1351  // computation of a 4x4 determinant that is developped according to
1352  // its 4th column. This implies some 3x3 determinants.
1353  const Vec cam_pos = Vec(det(matrix[ind(0,1)],matrix[ind(0,2)],matrix[ind(0,3)],
1354  matrix[ind(1,1)],matrix[ind(1,2)],matrix[ind(1,3)],
1355  matrix[ind(2,1)],matrix[ind(2,2)],matrix[ind(2,3)]),
1356 
1357  -det(matrix[ind(0,0)],matrix[ind(0,2)],matrix[ind(0,3)],
1358  matrix[ind(1,0)],matrix[ind(1,2)],matrix[ind(1,3)],
1359  matrix[ind(2,0)],matrix[ind(2,2)],matrix[ind(2,3)]),
1360 
1361  det(matrix[ind(0,0)],matrix[ind(0,1)],matrix[ind(0,3)],
1362  matrix[ind(1,0)],matrix[ind(1,1)],matrix[ind(1,3)],
1363  matrix[ind(2,0)],matrix[ind(2,1)],matrix[ind(2,3)])) /
1364 
1365  (-det(matrix[ind(0,0)],matrix[ind(0,1)],matrix[ind(0,2)],
1366  matrix[ind(1,0)],matrix[ind(1,1)],matrix[ind(1,2)],
1367  matrix[ind(2,0)],matrix[ind(2,1)],matrix[ind(2,2)]));
1368 
1369  // We compute the rotation matrix column by column.
1370 
1371  // GL Z axis is front facing.
1372  Vec column_2 = -line_2;
1373 
1374  // X-axis is almost like line_0 but should be orthogonal to the Z axis.
1375  Vec column_0 = ((column_2^line_0)^column_2);
1376  column_0.normalize();
1377 
1378  // Y-axis is almost like line_1 but should be orthogonal to the Z axis.
1379  // Moreover line_1 is downward oriented as the screen CS.
1380  Vec column_1 = -((column_2^line_1)^column_2);
1381  column_1.normalize();
1382 
1383  qreal rot[3][3];
1384  rot[0][0] = column_0[0];
1385  rot[1][0] = column_0[1];
1386  rot[2][0] = column_0[2];
1387 
1388  rot[0][1] = column_1[0];
1389  rot[1][1] = column_1[1];
1390  rot[2][1] = column_1[2];
1391 
1392  rot[0][2] = column_2[0];
1393  rot[1][2] = column_2[1];
1394  rot[2][2] = column_2[2];
1395 
1396  // We compute the field of view
1397 
1398  // line_1^column_0 -> vector of intersection line between
1399  // y_screen=0 and x_camera=0 plane.
1400  // column_2*(...) -> cos of the angle between Z vector et y_screen=0 plane
1401  // * 2 -> field of view = 2 * half angle
1402 
1403  // We need some intermediate values.
1404  Vec dummy = line_1^column_0;
1405  dummy.normalize();
1406  qreal fov = acos(column_2*dummy) * 2.0;
1407 
1408  // We set the camera.
1409  Quaternion q;
1410  q.setFromRotationMatrix(rot);
1411  setOrientation(q);
1412  setPosition(cam_pos);
1413  setFieldOfView(fov);
1414 }
1415 
1416 
1417 /*
1418  // persp : projectionMatrix_[0] = f/aspectRatio();
1419 void Camera::setFromProjectionMatrix(const GLdouble* projectionMatrix)
1420 {
1421  QString message;
1422  if ((fabs(projectionMatrix[1]) > 1E-3) ||
1423  (fabs(projectionMatrix[2]) > 1E-3) ||
1424  (fabs(projectionMatrix[3]) > 1E-3) ||
1425  (fabs(projectionMatrix[4]) > 1E-3) ||
1426  (fabs(projectionMatrix[6]) > 1E-3) ||
1427  (fabs(projectionMatrix[7]) > 1E-3) ||
1428  (fabs(projectionMatrix[8]) > 1E-3) ||
1429  (fabs(projectionMatrix[9]) > 1E-3))
1430  message = "Non null coefficient in projection matrix - Aborting";
1431  else
1432  if ((fabs(projectionMatrix[11]+1.0) < 1E-5) && (fabs(projectionMatrix[15]) < 1E-5))
1433  {
1434  if (projectionMatrix[5] < 1E-4)
1435  message="Negative field of view in Camera::setFromProjectionMatrix";
1436  else
1437  setType(Camera::PERSPECTIVE);
1438  }
1439  else
1440  if ((fabs(projectionMatrix[11]) < 1E-5) && (fabs(projectionMatrix[15]-1.0) < 1E-5))
1441  setType(Camera::ORTHOGRAPHIC);
1442  else
1443  message = "Unable to determine camera type in setFromProjectionMatrix - Aborting";
1444 
1445  if (!message.isEmpty())
1446  {
1447  qWarning(message);
1448  return;
1449  }
1450 
1451  switch (type())
1452  {
1453  case Camera::PERSPECTIVE:
1454  {
1455  setFieldOfView(2.0 * atan(1.0/projectionMatrix[5]));
1456  const qreal far = projectionMatrix[14] / (2.0 * (1.0 + projectionMatrix[10]));
1457  const qreal near = (projectionMatrix[10]+1.0) / (projectionMatrix[10]-1.0) * far;
1458  setSceneRadius((far-near)/2.0);
1459  setSceneCenter(position() + (near + sceneRadius())*viewDirection());
1460  break;
1461  }
1462  case Camera::ORTHOGRAPHIC:
1463  {
1464  GLdouble w, h;
1465  getOrthoWidthHeight(w,h);
1466  projectionMatrix_[0] = 1.0/w;
1467  projectionMatrix_[5] = 1.0/h;
1468  projectionMatrix_[10] = -2.0/(ZFar - ZNear);
1469  projectionMatrix_[11] = 0.0;
1470  projectionMatrix_[14] = -(ZFar + ZNear)/(ZFar - ZNear);
1471  projectionMatrix_[15] = 1.0;
1472  // same as glOrtho( -w, w, -h, h, zNear(), zFar() );
1473  break;
1474  }
1475  }
1476 }
1477 */
1478 
1480 
1482 void Camera::getCameraCoordinatesOf(const qreal src[3], qreal res[3]) const
1483 {
1484  Vec r = cameraCoordinatesOf(Vec(src));
1485  for (int i=0; i<3; ++i)
1486  res[i] = r[i];
1487 }
1488 
1490 void Camera::getWorldCoordinatesOf(const qreal src[3], qreal res[3]) const
1491 {
1492  Vec r = worldCoordinatesOf(Vec(src));
1493  for (int i=0; i<3; ++i)
1494  res[i] = r[i];
1495 }
1496 
1502 void Camera::getViewport(GLint viewport[4]) const
1503 {
1504  viewport[0] = 0;
1505  viewport[1] = screenHeight();
1506  viewport[2] = screenWidth();
1507  viewport[3] = -screenHeight();
1508 }
1509 
1585 {
1586  GLdouble x,y,z;
1587  static GLint viewport[4];
1588  getViewport(viewport);
1589 
1590  if (frame)
1591  {
1592  const Vec tmp = frame->inverseCoordinatesOf(src);
1593  gluProject(tmp.x,tmp.y,tmp.z, modelViewMatrix_, projectionMatrix_, viewport, &x,&y,&z);
1594  }
1595  else
1596  gluProject(src.x,src.y,src.z, modelViewMatrix_, projectionMatrix_, viewport, &x,&y,&z);
1597 
1598  return Vec(x,y,z);
1599 }
1600 
1632 {
1633  GLdouble x,y,z;
1634  static GLint viewport[4];
1635  getViewport(viewport);
1636  gluUnProject(src.x,src.y,src.z, modelViewMatrix_, projectionMatrix_, viewport, &x,&y,&z);
1637  if (frame)
1638  return frame->coordinatesOf(Vec(x,y,z));
1639  else
1640  return Vec(x,y,z);
1641 }
1642 
1644 void Camera::getProjectedCoordinatesOf(const qreal src[3], qreal res[3], const Frame* frame) const
1645 {
1646  Vec r = projectedCoordinatesOf(Vec(src), frame);
1647  for (int i=0; i<3; ++i)
1648  res[i] = r[i];
1649 }
1650 
1652 void Camera::getUnprojectedCoordinatesOf(const qreal src[3], qreal res[3], const Frame* frame) const
1653 {
1654  Vec r = unprojectedCoordinatesOf(Vec(src), frame);
1655  for (int i=0; i<3; ++i)
1656  res[i] = r[i];
1657 }
1658 
1660 
1665 {
1666  if (kfi_.contains(i))
1667  return kfi_[i];
1668  else
1669  return NULL;
1670 }
1671 
1691 {
1692  if (kfi)
1693  kfi_[i] = kfi;
1694  else
1695  kfi_.remove(i);
1696 }
1697 
1710 void Camera::addKeyFrameToPath(unsigned int i)
1711 {
1712  if (!kfi_.contains(i))
1714 
1715  kfi_[i]->addKeyFrame(*(frame()));
1716 }
1717 
1726 void Camera::playPath(unsigned int i)
1727 {
1728  if (kfi_.contains(i)) {
1729  if (kfi_[i]->interpolationIsStarted())
1730  kfi_[i]->stopInterpolation();
1731  else
1732  kfi_[i]->startInterpolation();
1733  }
1734 }
1735 
1741 void Camera::resetPath(unsigned int i)
1742 {
1743  if (kfi_.contains(i)) {
1744  if ((kfi_[i]->interpolationIsStarted()))
1745  kfi_[i]->stopInterpolation();
1746  else
1747  {
1748  kfi_[i]->resetInterpolation();
1749  kfi_[i]->interpolateAtTime(kfi_[i]->interpolationTime());
1750  }
1751  }
1752 }
1753 
1762 void Camera::deletePath(unsigned int i)
1763 {
1764  if (kfi_.contains(i))
1765  {
1766  kfi_[i]->stopInterpolation();
1767  delete kfi_[i];
1768  kfi_.remove(i);
1769  }
1770 }
1771 
1779 {
1780  for (QMap<unsigned int, KeyFrameInterpolator*>::ConstIterator it = kfi_.begin(), end=kfi_.end(); it != end; ++it)
1781  (it.value())->drawPath(3, 5, sceneRadius());
1782 }
1783 
1785 
1811 QDomElement Camera::domElement(const QString& name, QDomDocument& document) const
1812 {
1813  QDomElement de = document.createElement(name);
1814  QDomElement paramNode = document.createElement("Parameters");
1815  paramNode.setAttribute("fieldOfView", QString::number(fieldOfView()));
1816  paramNode.setAttribute("zNearCoefficient", QString::number(zNearCoefficient()));
1817  paramNode.setAttribute("zClippingCoefficient", QString::number(zClippingCoefficient()));
1818  paramNode.setAttribute("orthoCoef", QString::number(orthoCoef_));
1819  paramNode.setAttribute("sceneRadius", QString::number(sceneRadius()));
1820  paramNode.appendChild(sceneCenter().domElement("SceneCenter", document));
1821 
1822  switch (type())
1823  {
1824  case Camera::PERSPECTIVE : paramNode.setAttribute("Type", "PERSPECTIVE"); break;
1825  case Camera::ORTHOGRAPHIC : paramNode.setAttribute("Type", "ORTHOGRAPHIC"); break;
1826  }
1827  de.appendChild(paramNode);
1828 
1829  QDomElement stereoNode = document.createElement("Stereo");
1830  stereoNode.setAttribute("IODist", QString::number(IODistance()));
1831  stereoNode.setAttribute("focusDistance", QString::number(focusDistance()));
1832  stereoNode.setAttribute("physScreenWidth", QString::number(physicalScreenWidth()));
1833  de.appendChild(stereoNode);
1834 
1835  de.appendChild(frame()->domElement("ManipulatedCameraFrame", document));
1836 
1837  // KeyFrame paths
1838  for (QMap<unsigned int, KeyFrameInterpolator*>::ConstIterator it = kfi_.begin(), end=kfi_.end(); it != end; ++it)
1839  {
1840  QDomElement kfNode = (it.value())->domElement("KeyFrameInterpolator", document);
1841  kfNode.setAttribute("index", QString::number(it.key()));
1842  de.appendChild(kfNode);
1843  }
1844 
1845  return de;
1846 }
1847 
1869 void Camera::initFromDOMElement(const QDomElement& element)
1870 {
1871  QDomElement child=element.firstChild().toElement();
1872 
1873  QMutableMapIterator<unsigned int, KeyFrameInterpolator*> it(kfi_);
1874  while (it.hasNext()) {
1875  it.next();
1876  deletePath(it.key());
1877  }
1878 
1879  while (!child.isNull())
1880  {
1881  if (child.tagName() == "Parameters")
1882  {
1883  // #CONNECTION# Default values set in constructor
1884  setFieldOfView(DomUtils::qrealFromDom(child, "fieldOfView", M_PI/4.0));
1885  setZNearCoefficient(DomUtils::qrealFromDom(child, "zNearCoefficient", 0.005));
1886  setZClippingCoefficient(DomUtils::qrealFromDom(child, "zClippingCoefficient", sqrt(3.0)));
1887  orthoCoef_ = DomUtils::qrealFromDom(child, "orthoCoef", tan(fieldOfView()/2.0));
1888  setSceneRadius(DomUtils::qrealFromDom(child, "sceneRadius", sceneRadius()));
1889 
1891  QString type = child.attribute("Type", "PERSPECTIVE");
1892  if (type == "PERSPECTIVE") setType(Camera::PERSPECTIVE);
1893  if (type == "ORTHOGRAPHIC") setType(Camera::ORTHOGRAPHIC);
1894 
1895  QDomElement child2=child.firstChild().toElement();
1896  while (!child2.isNull())
1897  {
1898  /* Although the scene does not change when a camera is loaded, restore the saved center and radius values.
1899  Mainly useful when a the viewer is restored on startup, with possible additional cameras. */
1900  if (child2.tagName() == "SceneCenter")
1901  setSceneCenter(Vec(child2));
1902 
1903  child2 = child2.nextSibling().toElement();
1904  }
1905  }
1906 
1907  if (child.tagName() == "ManipulatedCameraFrame")
1908  frame()->initFromDOMElement(child);
1909 
1910  if (child.tagName() == "Stereo")
1911  {
1912  setIODistance(DomUtils::qrealFromDom(child, "IODist", 0.062));
1913  setFocusDistance(DomUtils::qrealFromDom(child, "focusDistance", focusDistance()));
1914  setPhysicalScreenWidth(DomUtils::qrealFromDom(child, "physScreenWidth", 0.5));
1915  }
1916 
1917  if (child.tagName() == "KeyFrameInterpolator")
1918  {
1919  unsigned int index = DomUtils::uintFromDom(child, "index", 0);
1921  if (keyFrameInterpolator(index))
1923  }
1924 
1925  child = child.nextSibling().toElement();
1926  }
1927 }
1928 
1940 void Camera::convertClickToLine(const QPoint& pixel, Vec& orig, Vec& dir) const
1941 {
1942  switch (type())
1943  {
1944  case Camera::PERSPECTIVE:
1945  orig = position();
1946  dir = Vec( ((2.0 * pixel.x() / screenWidth()) - 1.0) * tan(fieldOfView()/2.0) * aspectRatio(),
1947  ((2.0 * (screenHeight()-pixel.y()) / screenHeight()) - 1.0) * tan(fieldOfView()/2.0),
1948  -1.0 );
1949  dir = worldCoordinatesOf(dir) - orig;
1950  dir.normalize();
1951  break;
1952 
1953  case Camera::ORTHOGRAPHIC:
1954  {
1955  GLdouble w,h;
1956  getOrthoWidthHeight(w,h);
1957  orig = Vec((2.0 * pixel.x() / screenWidth() - 1.0)*w, -(2.0 * pixel.y() / screenHeight() - 1.0)*h, 0.0);
1958  orig = worldCoordinatesOf(orig);
1959  dir = viewDirection();
1960  break;
1961  }
1962  }
1963 }
1964 
1965 #ifndef DOXYGEN
1966 
1967 void Camera::drawCamera(qreal, qreal, qreal)
1968 {
1969  qWarning("drawCamera is deprecated. Use Camera::draw() instead.");
1970 }
1971 #endif
1972 
1993 void Camera::draw(bool drawFarPlane, qreal scale) const
1994 {
1995  glPushMatrix();
1996  glMultMatrixd(frame()->worldMatrix());
1997 
1998  // 0 is the upper left coordinates of the near corner, 1 for the far one
1999  Vec points[2];
2000 
2001  points[0].z = scale * zNear();
2002  points[1].z = scale * zFar();
2003 
2004  switch (type())
2005  {
2006  case Camera::PERSPECTIVE:
2007  {
2008  points[0].y = points[0].z * tan(fieldOfView()/2.0);
2009  points[0].x = points[0].y * aspectRatio();
2010 
2011  const qreal ratio = points[1].z / points[0].z;
2012 
2013  points[1].y = ratio * points[0].y;
2014  points[1].x = ratio * points[0].x;
2015  break;
2016  }
2017  case Camera::ORTHOGRAPHIC:
2018  {
2019  GLdouble hw, hh;
2020  getOrthoWidthHeight(hw, hh);
2021  points[0].x = points[1].x = scale * qreal(hw);
2022  points[0].y = points[1].y = scale * qreal(hh);
2023  break;
2024  }
2025  }
2026 
2027  const int farIndex = drawFarPlane?1:0;
2028 
2029  // Near and (optionally) far plane(s)
2030  glBegin(GL_QUADS);
2031  for (int i=farIndex; i>=0; --i)
2032  {
2033  glNormal3d(0.0f, 0.0f, (i==0)?1.0f:-1.0f);
2034  glVertex3d( points[i].x, points[i].y, -points[i].z);
2035  glVertex3d(-points[i].x, points[i].y, -points[i].z);
2036  glVertex3d(-points[i].x, -points[i].y, -points[i].z);
2037  glVertex3d( points[i].x, -points[i].y, -points[i].z);
2038  }
2039  glEnd();
2040 
2041  // Up arrow
2042  const qreal arrowHeight = 1.5 * points[0].y;
2043  const qreal baseHeight = 1.2 * points[0].y;
2044  const qreal arrowHalfWidth = 0.5 * points[0].x;
2045  const qreal baseHalfWidth = 0.3 * points[0].x;
2046 
2047  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2048  // Base
2049  glBegin(GL_QUADS);
2050  glVertex3d(-baseHalfWidth, points[0].y, -points[0].z);
2051  glVertex3d( baseHalfWidth, points[0].y, -points[0].z);
2052  glVertex3d( baseHalfWidth, baseHeight, -points[0].z);
2053  glVertex3d(-baseHalfWidth, baseHeight, -points[0].z);
2054  glEnd();
2055 
2056  // Arrow
2057  glBegin(GL_TRIANGLES);
2058  glVertex3d( 0.0, arrowHeight, -points[0].z);
2059  glVertex3d(-arrowHalfWidth, baseHeight, -points[0].z);
2060  glVertex3d( arrowHalfWidth, baseHeight, -points[0].z);
2061  glEnd();
2062 
2063  // Frustum lines
2064  switch (type())
2065  {
2066  case Camera::PERSPECTIVE :
2067  glBegin(GL_LINES);
2068  glVertex3d(0.0, 0.0, 0.0);
2069  glVertex3d( points[farIndex].x, points[farIndex].y, -points[farIndex].z);
2070  glVertex3d(0.0, 0.0, 0.0);
2071  glVertex3d(-points[farIndex].x, points[farIndex].y, -points[farIndex].z);
2072  glVertex3d(0.0, 0.0, 0.0);
2073  glVertex3d(-points[farIndex].x, -points[farIndex].y, -points[farIndex].z);
2074  glVertex3d(0.0, 0.0, 0.0);
2075  glVertex3d( points[farIndex].x, -points[farIndex].y, -points[farIndex].z);
2076  glEnd();
2077  break;
2078  case Camera::ORTHOGRAPHIC :
2079  if (drawFarPlane)
2080  {
2081  glBegin(GL_LINES);
2082  glVertex3d( points[0].x, points[0].y, -points[0].z);
2083  glVertex3d( points[1].x, points[1].y, -points[1].z);
2084  glVertex3d(-points[0].x, points[0].y, -points[0].z);
2085  glVertex3d(-points[1].x, points[1].y, -points[1].z);
2086  glVertex3d(-points[0].x, -points[0].y, -points[0].z);
2087  glVertex3d(-points[1].x, -points[1].y, -points[1].z);
2088  glVertex3d( points[0].x, -points[0].y, -points[0].z);
2089  glVertex3d( points[1].x, -points[1].y, -points[1].z);
2090  glEnd();
2091  }
2092  }
2093 
2094  glPopMatrix();
2095 }
2096 
2097 
2121 void Camera::getFrustumPlanesCoefficients(GLdouble coef[6][4]) const
2122 {
2123  // Computed once and for all
2124  const Vec pos = position();
2125  const Vec viewDir = viewDirection();
2126  const Vec up = upVector();
2127  const Vec right = rightVector();
2128  const qreal posViewDir = pos * viewDir;
2129 
2130  static Vec normal[6];
2131  static GLdouble dist[6];
2132 
2133  switch (type())
2134  {
2135  case Camera::PERSPECTIVE :
2136  {
2137  const qreal hhfov = horizontalFieldOfView() / 2.0;
2138  const qreal chhfov = cos(hhfov);
2139  const qreal shhfov = sin(hhfov);
2140  normal[0] = - shhfov * viewDir;
2141  normal[1] = normal[0] + chhfov * right;
2142  normal[0] = normal[0] - chhfov * right;
2143 
2144  normal[2] = -viewDir;
2145  normal[3] = viewDir;
2146 
2147  const qreal hfov = fieldOfView() / 2.0;
2148  const qreal chfov = cos(hfov);
2149  const qreal shfov = sin(hfov);
2150  normal[4] = - shfov * viewDir;
2151  normal[5] = normal[4] - chfov * up;
2152  normal[4] = normal[4] + chfov * up;
2153 
2154  for (int i=0; i<2; ++i)
2155  dist[i] = pos * normal[i];
2156  for (int j=4; j<6; ++j)
2157  dist[j] = pos * normal[j];
2158 
2159  // Natural equations are:
2160  // dist[0,1,4,5] = pos * normal[0,1,4,5];
2161  // dist[2] = (pos + zNear() * viewDir) * normal[2];
2162  // dist[3] = (pos + zFar() * viewDir) * normal[3];
2163 
2164  // 2 times less computations using expanded/merged equations. Dir vectors are normalized.
2165  const qreal posRightCosHH = chhfov * pos * right;
2166  dist[0] = -shhfov * posViewDir;
2167  dist[1] = dist[0] + posRightCosHH;
2168  dist[0] = dist[0] - posRightCosHH;
2169  const qreal posUpCosH = chfov * pos * up;
2170  dist[4] = - shfov * posViewDir;
2171  dist[5] = dist[4] - posUpCosH;
2172  dist[4] = dist[4] + posUpCosH;
2173 
2174  break;
2175  }
2176  case Camera::ORTHOGRAPHIC :
2177  normal[0] = -right;
2178  normal[1] = right;
2179  normal[4] = up;
2180  normal[5] = -up;
2181 
2182  GLdouble hw, hh;
2183  getOrthoWidthHeight(hw, hh);
2184  dist[0] = (pos - hw * right) * normal[0];
2185  dist[1] = (pos + hw * right) * normal[1];
2186  dist[4] = (pos + hh * up) * normal[4];
2187  dist[5] = (pos - hh * up) * normal[5];
2188  break;
2189  }
2190 
2191  // Front and far planes are identical for both camera types.
2192  normal[2] = -viewDir;
2193  normal[3] = viewDir;
2194  dist[2] = -posViewDir - zNear();
2195  dist[3] = posViewDir + zFar();
2196 
2197  for (int i=0; i<6; ++i)
2198  {
2199  coef[i][0] = GLdouble(normal[i].x);
2200  coef[i][1] = GLdouble(normal[i].y);
2201  coef[i][2] = GLdouble(normal[i].z);
2202  coef[i][3] = dist[i];
2203  }
2204 }
2205 
2209 }
void setZClippingCoefficient(qreal coef)
Definition: camera.h:268
void setScreenWidthAndHeight(int width, int height)
Definition: camera.cpp:166
void setKeyFrameInterpolator(unsigned int i, KeyFrameInterpolator *const kfi)
Definition: camera.cpp:1690
Vec worldCoordinatesOf(const Vec &src) const
Definition: camera.cpp:1254
A keyFrame Catmull-Rom Frame interpolator.
Vec position() const
Definition: frame.cpp:537
qreal aspectRatio() const
Definition: camera.h:185
virtual QDomElement domElement(const QString &name, QDomDocument &document) const
Definition: camera.cpp:1811
virtual qreal zFar() const
Definition: camera.cpp:236
void fitSphere(const Vec &center, qreal radius)
Definition: camera.cpp:1020
The ManipulatedCameraFrame class represents a ManipulatedFrame with Camera specific mouse bindings...
virtual void drawAllPaths()
Definition: camera.cpp:1778
Vec inverseTransformOf(const Vec &src) const
Definition: frame.cpp:856
Vec revolveAroundPoint() const
Definition: camera.cpp:763
virtual void loadProjectionMatrixStereo(bool leftBuffer=true) const
Definition: camera.cpp:536
void convertClickToLine(const QPoint &pixel, Vec &orig, Vec &dir) const
Definition: camera.cpp:1940
void getModelViewProjectionMatrix(GLfloat m[16]) const
Definition: camera.cpp:693
Camera & operator=(const Camera &camera)
Definition: camera.cpp:124
void interpolateToFitScene()
Definition: camera.cpp:913
qreal fieldOfView() const
Definition: camera.h:170
void setOrientation(const Quaternion &q)
Definition: camera.cpp:1150
bool setRevolveAroundPointFromPixel(const QPoint &pixel)
Definition: camera.cpp:759
void setIODistance(qreal distance)
Definition: camera.h:455
virtual ~Camera()
Definition: camera.cpp:86
bool setPivotPointFromPixel(const QPoint &pixel)
Definition: camera.cpp:796
qreal distanceToSceneCenter() const
Definition: camera.cpp:303
static qreal det(qreal m00, qreal m01, qreal m02, qreal m10, qreal m11, qreal m12, qreal m20, qreal m21, qreal m22)
Definition: camera.cpp:1180
void addKeyFrame(const Frame &frame)
void lookAt(const Vec &target)
Definition: camera.cpp:1008
virtual void loadProjectionMatrix(bool reset=true) const
Definition: camera.cpp:463
void getProjectionMatrix(GLfloat m[16]) const
Definition: camera.cpp:629
void computeModelViewMatrix() const
Definition: camera.cpp:400
void setSceneCenter(const Vec &center)
Definition: camera.cpp:733
void onFrameModified()
Definition: camera.cpp:2206
qreal flySpeed() const
Definition: camera.cpp:1263
Vec projectedCoordinatesOf(const Vec &src, const Frame *frame=NULL) const
Definition: camera.cpp:1584
void setSceneBoundingBox(const Vec &min, const Vec &max)
Definition: camera.cpp:723
virtual void deletePath(unsigned int i)
Definition: camera.cpp:1762
void setPositionWithConstraint(Vec &position)
Definition: frame.cpp:621
GLdouble projectionMatrix_[16]
Definition: camera.h:497
virtual void loadModelViewMatrix(bool reset=true) const
Definition: camera.cpp:500
qreal squaredNorm() const
Definition: vec.h:332
Vec position() const
Definition: camera.cpp:1200
void setSceneRadius(qreal radius)
Definition: camera.cpp:705
void setFlySpeed(qreal speed)
Definition: camera.cpp:1268
void setPosition(const Vec &pos)
Definition: camera.cpp:1240
virtual void loadModelViewMatrixStereo(bool leftBuffer=true) const
Definition: camera.cpp:591
Vec rotate(const Vec &v) const
Definition: quaternion.cpp:76
void showEntireScene()
Definition: camera.cpp:987
#define M_PI
void getProjectedCoordinatesOf(const qreal src[3], qreal res[3], const Frame *frame=NULL) const
Definition: camera.cpp:1644
void getViewport(GLint viewport[4]) const
Definition: camera.cpp:1502
void setType(Type type)
Definition: camera.cpp:261
void centerScene()
Definition: camera.cpp:997
int screenWidth() const
Definition: camera.h:190
Vec pointUnderPixel(const QPoint &pixel, bool &found) const
Definition: camera.cpp:971
bool setSceneCenterFromPixel(const QPoint &pixel)
Definition: camera.cpp:745
void getFrustumPlanesCoefficients(GLdouble coef[6][4]) const
Definition: camera.cpp:2121
virtual void initFromDOMElement(const QDomElement &element)
Definition: camera.cpp:1869
Vec upVector() const
Definition: camera.cpp:1209
qreal orthoCoef_
Definition: camera.h:493
void setFromRotationMatrix(const float m[3][3])
Definition: quaternion.cpp:151
static void drawCamera(qreal scale=1.0, qreal aspectRatio=1.33, qreal fieldOfView=qreal(M_PI)/4.0)
Definition: camera.cpp:1967
void setReferenceFrame(const Frame *const refFrame)
Definition: frame.cpp:665
void computeProjectionMatrix() const
Definition: camera.cpp:350
void getModelViewMatrix(GLfloat m[16]) const
Definition: camera.cpp:662
qreal z
Definition: vec.h:81
qreal horizontalFieldOfView() const
Definition: camera.h:179
Type type() const
Definition: camera.h:158
ManipulatedCameraFrame * frame() const
Definition: camera.h:334
qreal pixelGLRatio(const Vec &position) const
Definition: camera.cpp:819
void setFOVToFitScene()
Definition: camera.cpp:861
void fitScreenRegion(const QRect &rectangle)
Definition: camera.cpp:1058
qreal y
Definition: vec.h:81
void rotate(Quaternion &q)
Definition: frame.cpp:376
qreal sceneRadius() const
Definition: camera.h:284
The Vec class represents 3D positions and 3D vectors.
Definition: vec.h:65
void setViewDirection(const Vec &direction)
Definition: camera.cpp:1161
virtual void getOrthoWidthHeight(GLdouble &halfWidth, GLdouble &halfHeight) const
Definition: camera.cpp:324
Vec rightVector() const
Definition: camera.cpp:1228
ManipulatedCameraFrame * frame_
Definition: camera.h:484
qreal zNearCoefficient() const
Definition: camera.h:210
void fitBoundingBox(const Vec &min, const Vec &max)
Definition: camera.cpp:1044
KeyFrameInterpolator * interpolationKfi_
Definition: camera.h:507
qreal fieldOfView_
Definition: camera.h:488
void projectOnLine(const Vec &origin, const Vec &direction)
Definition: frame.cpp:1133
QMap< unsigned int, KeyFrameInterpolator * > kfi_
Definition: camera.h:506
Vec cameraCoordinatesOf(const Vec &src) const
Definition: camera.cpp:1248
void getCameraCoordinatesOf(const qreal src[3], qreal res[3]) const
Definition: camera.cpp:1482
bool modelViewMatrixIsUpToDate_
Definition: camera.h:496
void interpolateToZoomOnPixel(const QPoint &pixel)
Definition: camera.cpp:875
qreal focusDistance() const
Definition: camera.h:452
static unsigned int uintFromDom(const QDomElement &e, const QString &attribute, unsigned int defValue)
Definition: domUtils.h:93
void setZNearCoefficient(qreal coef)
Definition: camera.h:266
void setPhysicalScreenWidth(qreal width)
Definition: camera.h:463
static qreal qrealFromDom(const QDomElement &e, const QString &attribute, qreal defValue)
Definition: domUtils.h:44
int screenHeight() const
Definition: camera.h:195
qreal physicalScreenWidth() const
Definition: camera.h:440
KeyFrameInterpolator * keyFrameInterpolator(unsigned int i) const
Definition: camera.cpp:1664
virtual void draw(bool drawFarPlane=true, qreal scale=1.0) const
Definition: camera.cpp:1993
Vec coordinatesOf(const Vec &src) const
Definition: frame.cpp:702
A perspective or orthographic camera.
Definition: camera.h:84
void setFrame(ManipulatedCameraFrame *const mcf)
Definition: camera.cpp:285
virtual void initFromDOMElement(const QDomElement &element)
void getWorldCoordinatesOf(const qreal src[3], qreal res[3]) const
Definition: camera.cpp:1490
The Quaternion class represents 3D rotations and orientations.
Definition: quaternion.h:66
void setFromRotatedBasis(const Vec &X, const Vec &Y, const Vec &Z)
Definition: quaternion.cpp:182
Quaternion orientation() const
Definition: frame.cpp:546
virtual void addKeyFrameToPath(unsigned int i)
Definition: camera.cpp:1710
void getUnprojectedCoordinatesOf(const qreal src[3], qreal res[3], const Frame *frame=NULL) const
Definition: camera.cpp:1652
void setOrientationWithConstraint(Quaternion &orientation)
Definition: frame.cpp:631
Vec viewDirection() const
Definition: camera.cpp:1220
virtual void resetPath(unsigned int i)
Definition: camera.cpp:1741
void interpolateTo(const Frame &fr, qreal duration)
Definition: camera.cpp:942
void setPosition(const Vec &position)
Definition: frame.cpp:443
qreal IODistance() const
Definition: camera.h:425
Quaternion orientation() const
Definition: camera.cpp:1237
void setFocusDistance(qreal distance)
Definition: camera.h:466
Vec pivotPoint() const
Definition: camera.cpp:1275
virtual void initFromDOMElement(const QDomElement &element)
void setFieldOfView(qreal fov)
Definition: camera.cpp:245
The Frame class represents a coordinate system, defined by a position and an orientation.
Definition: frame.h:121
void setRevolveAroundPoint(const Vec &point)
Definition: camera.cpp:755
void setFromModelViewMatrix(const GLdouble *const modelViewMatrix)
Definition: camera.cpp:1294
static unsigned int ind(unsigned int i, unsigned int j)
Definition: camera.cpp:1188
virtual void playPath(unsigned int i)
Definition: camera.cpp:1726
qreal normalize()
Definition: vec.h:340
void setOrientation(const Quaternion &orientation)
Definition: frame.cpp:505
void setUpVector(const Vec &up, bool noMove=true)
Definition: camera.cpp:1116
GLdouble modelViewMatrix_[16]
Definition: camera.h:495
bool projectionMatrixIsUpToDate_
Definition: camera.h:498
virtual qreal zNear() const
Definition: camera.cpp:211
Vec inverseCoordinatesOf(const Vec &src) const
Definition: frame.cpp:715
qreal sceneRadius_
Definition: camera.h:490
Vec unprojectedCoordinatesOf(const Vec &src, const Frame *frame=NULL) const
Definition: camera.cpp:1631
qreal zClippingCoefficient() const
Definition: camera.h:229
qreal x
Definition: vec.h:81
Vec sceneCenter() const
Definition: camera.h:297
void setFromProjectionMatrix(const qreal matrix[12])
Definition: camera.cpp:1332
void setPivotPoint(const Vec &point)
Definition: camera.cpp:770


octovis
Author(s): Kai M. Wurm , Armin Hornung
autogenerated on Wed Jun 5 2019 19:26:39