manipulatedCameraFrame.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 "manipulatedCameraFrame.h"
25 #include "qglviewer.h"
26 
27 #include <QMouseEvent>
28 
29 using namespace qglviewer;
30 using namespace std;
31 
38  : driveSpeed_(0.0), sceneUpVector_(0.0, 1.0, 0.0), rotatesAroundUpVector_(false), zoomsOnPivotPoint_(false)
39 {
40  setFlySpeed(0.0);
42  connect(&flyTimer_, SIGNAL(timeout()), SLOT(flyUpdate()));
43 }
44 
47 {
49 
50  setFlySpeed(mcf.flySpeed());
54 
55  return *this;
56 }
57 
60  : ManipulatedFrame(mcf)
61 {
63  connect(&flyTimer_, SIGNAL(timeout()), SLOT(flyUpdate()));
64  (*this)=(mcf);
65 }
66 
68 
73 {
75 }
76 
77 #ifndef DOXYGEN
78 
81 {
82  static Vec flyDisp(0.0, 0.0, 0.0);
83  switch (action_)
84  {
86  flyDisp.z = -flySpeed();
88  break;
90  flyDisp.z = flySpeed();
92  break;
93  case QGLViewer::DRIVE:
94  flyDisp.z = flySpeed() * driveSpeed_;
96  break;
97  default:
98  break;
99  }
100 
101  // Needs to be out of the switch since ZOOM/fastDraw()/wheelEvent use this callback to trigger a final draw().
102  // #CONNECTION# wheelEvent.
103  Q_EMIT manipulated();
104 }
105 
107  qWarning("flyUpVector() is deprecated. Use sceneUpVector() instead.");
108  return sceneUpVector();
109 }
110 
112  qWarning("setFlyUpVector() is deprecated. Use setSceneUpVector() instead.");
113  setSceneUpVector(up);
114 }
115 
116 #endif
117 
121 {
122  sceneUpVector_ = inverseTransformOf(Vec(0.0, 1.0, 0.0));
123 }
124 
126 // S t a t e s a v i n g a n d r e s t o r i n g //
128 
142 QDomElement ManipulatedCameraFrame::domElement(const QString& name, QDomDocument& document) const
143 {
144  QDomElement e = ManipulatedFrame::domElement(name, document);
145  QDomElement mcp = document.createElement("ManipulatedCameraParameters");
146  mcp.setAttribute("flySpeed", QString::number(flySpeed()));
147  DomUtils::setBoolAttribute(mcp, "rotatesAroundUpVector", rotatesAroundUpVector());
148  DomUtils::setBoolAttribute(mcp, "zoomsOnPivotPoint", zoomsOnPivotPoint());
149  mcp.appendChild(sceneUpVector().domElement("sceneUpVector", document));
150  e.appendChild(mcp);
151  return e;
152 }
153 
158 void ManipulatedCameraFrame::initFromDOMElement(const QDomElement& element)
159 {
160  // No need to initialize, since default sceneUpVector and flySpeed are not meaningful.
161  // It's better to keep current ones. And it would destroy constraint() and referenceFrame().
162  // *this = ManipulatedCameraFrame();
164 
165  QDomElement child=element.firstChild().toElement();
166  while (!child.isNull())
167  {
168  if (child.tagName() == "ManipulatedCameraParameters")
169  {
170  setFlySpeed(DomUtils::qrealFromDom(child, "flySpeed", flySpeed()));
171  setRotatesAroundUpVector(DomUtils::boolFromDom(child, "rotatesAroundUpVector", false));
172  setZoomsOnPivotPoint(DomUtils::boolFromDom(child, "zoomsOnPivotPoint", false));
173 
174  QDomElement schild=child.firstChild().toElement();
175  while (!schild.isNull())
176  {
177  if (schild.tagName() == "sceneUpVector")
178  setSceneUpVector(Vec(schild));
179 
180  schild = schild.nextSibling().toElement();
181  }
182  }
183  child = child.nextSibling().toElement();
184  }
185 }
186 
187 
189 // M o u s e h a n d l i n g //
191 
192 #ifndef DOXYGEN
193 
194 void ManipulatedCameraFrame::startAction(int ma, bool withConstraint)
195 {
196  ManipulatedFrame::startAction(ma, withConstraint);
197 
198  switch (action_)
199  {
202  case QGLViewer::DRIVE:
203  flyTimer_.setSingleShot(false);
204  flyTimer_.start(10);
205  break;
206  case QGLViewer::ROTATE:
208  break;
209  default:
210  break;
211  }
212 }
213 
214 void ManipulatedCameraFrame::zoom(qreal delta, const Camera * const camera) {
215  const qreal sceneRadius = camera->sceneRadius();
216  if (zoomsOnPivotPoint_) {
217  Vec direction = position() - camera->pivotPoint();
218  if (direction.norm() > 0.02 * sceneRadius || delta > 0.0)
219  translate(delta * direction);
220  } else {
221  const qreal coef = qMax(fabs((camera->frame()->coordinatesOf(camera->pivotPoint())).z), 0.2 * sceneRadius);
222  Vec trans(0.0, 0.0, -coef * delta);
224  }
225 }
226 
227 #endif
228 
233 void ManipulatedCameraFrame::mouseMoveEvent(QMouseEvent* const event, Camera* const camera)
234 {
235  // #CONNECTION# QGLViewer::mouseMoveEvent does the update().
236  switch (action_)
237  {
239  {
240  const QPoint delta = prevPos_ - event->pos();
241  Vec trans(delta.x(), -delta.y(), 0.0);
242  // Scale to fit the screen mouse displacement
243  switch (camera->type())
244  {
245  case Camera::PERSPECTIVE :
246  trans *= 2.0 * tan(camera->fieldOfView()/2.0) *
247  fabs((camera->frame()->coordinatesOf(pivotPoint())).z) / camera->screenHeight();
248  break;
249  case Camera::ORTHOGRAPHIC :
250  {
251  GLdouble w,h;
252  camera->getOrthoWidthHeight(w, h);
253  trans[0] *= 2.0 * w / camera->screenWidth();
254  trans[1] *= 2.0 * h / camera->screenHeight();
255  break;
256  }
257  }
259  break;
260  }
261 
263  {
264  Quaternion rot = pitchYawQuaternion(event->x(), event->y(), camera);
265  rotate(rot);
266  //#CONNECTION# wheelEvent MOVE_FORWARD case
267  // actual translation is made in flyUpdate().
268  //translate(inverseTransformOf(Vec(0.0, 0.0, -flySpeed())));
269  break;
270  }
271 
273  {
274  Quaternion rot = pitchYawQuaternion(event->x(), event->y(), camera);
275  rotate(rot);
276  // actual translation is made in flyUpdate().
277  //translate(inverseTransformOf(Vec(0.0, 0.0, flySpeed())));
278  break;
279  }
280 
281  case QGLViewer::DRIVE:
282  {
283  Quaternion rot = turnQuaternion(event->x(), camera);
284  rotate(rot);
285  // actual translation is made in flyUpdate().
286  driveSpeed_ = 0.01 * (event->y() - pressPos_.y());
287  break;
288  }
289 
290  case QGLViewer::ZOOM:
291  {
292  zoom(deltaWithPrevPos(event, camera), camera);
293  break;
294  }
295 
297  {
298  Quaternion rot = pitchYawQuaternion(event->x(), event->y(), camera);
299  rotate(rot);
300  break;
301  }
302 
303  case QGLViewer::ROTATE:
304  {
305  Quaternion rot;
307  // Multiply by 2.0 to get on average about the same speed as with the deformed ball
308  qreal dx = 2.0 * rotationSensitivity() * (prevPos_.x() - event->x()) / camera->screenWidth();
309  qreal dy = 2.0 * rotationSensitivity() * (prevPos_.y() - event->y()) / camera->screenHeight();
310  if (constrainedRotationIsReversed_) dx = -dx;
311  Vec verticalAxis = transformOf(sceneUpVector_);
312  rot = Quaternion(verticalAxis, dx) * Quaternion(Vec(1.0, 0.0, 0.0), dy);
313  } else {
314  Vec trans = camera->projectedCoordinatesOf(pivotPoint());
315  rot = deformedBallQuaternion(event->x(), event->y(), trans[0], trans[1], camera);
316  }
317  //#CONNECTION# These two methods should go together (spinning detection and activation)
318  computeMouseSpeed(event);
320  spin();
321  break;
322  }
323 
325  {
326  Vec trans = camera->projectedCoordinatesOf(pivotPoint());
327 
328  const qreal angle = atan2(event->y() - trans[1], event->x() - trans[0]) - atan2(prevPos_.y()-trans[1], prevPos_.x()-trans[0]);
329 
330  Quaternion rot(Vec(0.0, 0.0, 1.0), angle);
331  //#CONNECTION# These two methods should go together (spinning detection and activation)
332  computeMouseSpeed(event);
334  spin();
336  break;
337  }
338 
339  case QGLViewer::ROLL:
340  {
341  const qreal angle = M_PI * (event->x() - prevPos_.x()) / camera->screenWidth();
342  Quaternion rot(Vec(0.0, 0.0, 1.0), angle);
343  rotate(rot);
346  break;
347  }
348 
350  {
351  Vec trans;
352  int dir = mouseOriginalDirection(event);
353  if (dir == 1)
354  trans.setValue(prevPos_.x() - event->x(), 0.0, 0.0);
355  else if (dir == -1)
356  trans.setValue(0.0, event->y() - prevPos_.y(), 0.0);
357 
358  switch (camera->type())
359  {
360  case Camera::PERSPECTIVE :
361  trans *= 2.0 * tan(camera->fieldOfView()/2.0) *
362  fabs((camera->frame()->coordinatesOf(pivotPoint())).z) / camera->screenHeight();
363  break;
364  case Camera::ORTHOGRAPHIC :
365  {
366  GLdouble w,h;
367  camera->getOrthoWidthHeight(w, h);
368  trans[0] *= 2.0 * w / camera->screenWidth();
369  trans[1] *= 2.0 * h / camera->screenHeight();
370  break;
371  }
372  }
373 
375  break;
376  }
377 
380  break;
381  }
382 
384  {
385  prevPos_ = event->pos();
387  // ZOOM_ON_REGION should not emit manipulated().
388  // prevPos_ is used to draw rectangle feedback.
389  Q_EMIT manipulated();
390  }
391 }
392 
393 
396 void ManipulatedCameraFrame::mouseReleaseEvent(QMouseEvent* const event, Camera* const camera)
397 {
399  flyTimer_.stop();
400 
402  camera->fitScreenRegion(QRect(pressPos_, event->pos()));
403 
405 }
406 
413 void ManipulatedCameraFrame::wheelEvent(QWheelEvent* const event, Camera* const camera)
414 {
415  //#CONNECTION# QGLViewer::setWheelBinding, ManipulatedFrame::wheelEvent.
416  switch (action_)
417  {
418  case QGLViewer::ZOOM:
419  {
420  zoom(wheelDelta(event), camera);
421  Q_EMIT manipulated();
422  break;
423  }
426  //#CONNECTION# mouseMoveEvent() MOVE_FORWARD case
427  translate(inverseTransformOf(Vec(0.0, 0.0, 0.2*flySpeed()*event->delta())));
428  Q_EMIT manipulated();
429  break;
430  default:
431  break;
432  }
433 
434  // #CONNECTION# startAction should always be called before
437 
438  // The wheel triggers a fastDraw. A final update() is needed after the last wheel event to
439  // polish the rendering using draw(). Since the last wheel event does not say its name, we use
440  // the flyTimer_ to trigger flyUpdate(), which emits manipulated. Two wheel events
441  // separated by more than this delay milliseconds will trigger a draw().
442  const int finalDrawAfterWheelEventDelay = 400;
443 
444  // Starts (or prolungates) the timer.
445  flyTimer_.setSingleShot(true);
446  flyTimer_.start(finalDrawAfterWheelEventDelay);
447 
448  // This could also be done *before* manipulated is emitted, so that isManipulated() returns false.
449  // But then fastDraw would not be used with wheel.
450  // Detecting the last wheel event and forcing a final draw() is done using the timer_.
452 }
453 
455 
458 {
459  return Quaternion(Vec(0.0, 1.0, 0.0), rotationSensitivity()*(prevPos_.x()-x)/camera->screenWidth());
460 }
461 
465 {
466  const Quaternion rotX(Vec(1.0, 0.0, 0.0), rotationSensitivity()*(prevPos_.y()-y)/camera->screenHeight());
467  const Quaternion rotY(transformOf(sceneUpVector()), rotationSensitivity()*(prevPos_.x()-x)/camera->screenWidth());
468  return rotY * rotX;
469 }
virtual void initFromDOMElement(const QDomElement &element)
Vec position() const
Definition: frame.cpp:537
The ManipulatedCameraFrame class represents a ManipulatedFrame with Camera specific mouse bindings...
Vec inverseTransformOf(const Vec &src) const
Definition: frame.cpp:856
A ManipulatedFrame is a Frame that can be rotated and translated using the mouse. ...
void setRotatesAroundUpVector(bool constrained)
qreal fieldOfView() const
Definition: camera.h:170
qreal norm() const
Definition: vec.h:335
virtual void mouseMoveEvent(QMouseEvent *const event, Camera *const camera)
Quaternion deformedBallQuaternion(int x, int y, qreal cx, qreal cy, const Camera *const camera)
Quaternion pitchYawQuaternion(int x, int y, const Camera *const camera)
virtual void mouseReleaseEvent(QMouseEvent *const event, Camera *const camera)
Vec projectedCoordinatesOf(const Vec &src, const Frame *frame=NULL) const
Definition: camera.cpp:1584
Vec transformOf(const Vec &src) const
Definition: frame.cpp:843
ManipulatedCameraFrame & operator=(const ManipulatedCameraFrame &mcf)
#define M_PI
int screenWidth() const
Definition: camera.h:190
qreal deltaWithPrevPos(QMouseEvent *const event, Camera *const camera) const
void setConstraint(Constraint *const constraint)
Definition: frame.h:361
qreal z
Definition: vec.h:81
Type type() const
Definition: camera.h:158
ManipulatedCameraFrame * frame() const
Definition: camera.h:334
void fitScreenRegion(const QRect &rectangle)
Definition: camera.cpp:1058
qreal y
Definition: vec.h:81
void rotate(Quaternion &q)
Definition: frame.cpp:376
void zoom(qreal delta, const Camera *const camera)
qreal sceneRadius() const
Definition: camera.h:284
The Vec class represents 3D positions and 3D vectors.
Definition: vec.h:65
virtual void getOrthoWidthHeight(GLdouble &halfWidth, GLdouble &halfHeight) const
Definition: camera.cpp:324
Quaternion turnQuaternion(int x, const Camera *const camera)
void setValue(qreal X, qreal Y, qreal Z)
Definition: vec.h:125
qreal wheelDelta(const QWheelEvent *event) const
static void setBoolAttribute(QDomElement &element, const QString &attribute, bool value)
Definition: domUtils.h:137
static qreal qrealFromDom(const QDomElement &e, const QString &attribute, qreal defValue)
Definition: domUtils.h:44
int screenHeight() const
Definition: camera.h:195
virtual QDomElement domElement(const QString &name, QDomDocument &document) const
virtual void wheelEvent(QWheelEvent *const event, Camera *const camera)
void setSpinningQuaternion(const Quaternion &spinningQuaternion)
Vec coordinatesOf(const Vec &src) const
Definition: frame.cpp:702
void computeMouseSpeed(const QMouseEvent *const e)
QGLViewer::MouseAction action_
void translate(Vec &t)
Definition: frame.cpp:335
A perspective or orthographic camera.
Definition: camera.h:84
virtual void initFromDOMElement(const QDomElement &element)
ManipulatedFrame & operator=(const ManipulatedFrame &mf)
qreal translationSensitivity() const
The Quaternion class represents 3D rotations and orientations.
Definition: quaternion.h:66
static bool boolFromDom(const QDomElement &e, const QString &attribute, bool defValue)
Definition: domUtils.h:114
virtual void startAction(int ma, bool withConstraint=true)
virtual void mouseReleaseEvent(QMouseEvent *const event, Camera *const camera)
Vec pivotPoint() const
Definition: camera.cpp:1275
int mouseOriginalDirection(const QMouseEvent *const e)
Quaternion spinningQuaternion() const
Vec localInverseTransformOf(const Vec &src) const
Definition: frame.cpp:881
virtual QDomElement domElement(const QString &name, QDomDocument &document) const
qreal x
Definition: vec.h:81
virtual void startAction(int ma, bool withConstraint=true)
void rotateAroundPoint(Quaternion &rotation, const Vec &point)
Definition: frame.cpp:414


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