manipulatedCameraFrame.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  Copyright (C) 2002-2013 Gilles Debunne. All rights reserved.
4 
5  This file is part of the QGLViewer library version 2.4.0.
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 #if QT_VERSION >= 0x040000
28 # include <QMouseEvent>
29 #endif
30 
31 using namespace qglviewer;
32 using namespace std;
33 
40  : driveSpeed_(0.0), flyUpVector_(0.0, 1.0, 0.0)
41 {
42  setFlySpeed(0.0);
44 
45  connect(&flyTimer_, SIGNAL(timeout()), SLOT(flyUpdate()));
46 }
47 
50 {
52 
53  setFlySpeed(mcf.flySpeed());
55 
56  return *this;
57 }
58 
61  : ManipulatedFrame(mcf)
62 {
64  connect(&flyTimer_, SIGNAL(timeout()), SLOT(flyUpdate()));
65  (*this)=(mcf);
66 }
67 
69 
74 {
76 }
77 
78 #ifndef DOXYGEN
79 
82 {
83  static Vec flyDisp(0.0, 0.0, 0.0);
84  switch (action_)
85  {
87  flyDisp.z = -flySpeed();
89  break;
91  flyDisp.z = flySpeed();
93  break;
94  case QGLViewer::DRIVE:
95  flyDisp.z = flySpeed() * driveSpeed_;
97  break;
98  default:
99  break;
100  }
101 
102  // Needs to be out of the switch since ZOOM/fastDraw()/wheelEvent use this callback to trigger a final draw().
103  // #CONNECTION# wheelEvent.
105 }
106 #endif
107 
111 {
112  flyUpVector_ = inverseTransformOf(Vec(0.0, 1.0, 0.0));
113 }
114 
116 // S t a t e s a v i n g a n d r e s t o r i n g //
118 
132 QDomElement ManipulatedCameraFrame::domElement(const QString& name, QDomDocument& document) const
133 {
134  QDomElement e = ManipulatedFrame::domElement(name, document);
135  QDomElement mcp = document.createElement("ManipulatedCameraParameters");
136  mcp.setAttribute("flySpeed", QString::number(flySpeed()));
137  mcp.appendChild(flyUpVector().domElement("flyUpVector", document));
138  e.appendChild(mcp);
139  return e;
140 }
141 
146 void ManipulatedCameraFrame::initFromDOMElement(const QDomElement& element)
147 {
148  // No need to initialize, since default flyUpVector and flySpeed are not meaningful.
149  // It's better to keep current ones. And it would destroy constraint() and referenceFrame().
150  // *this = ManipulatedCameraFrame();
152 
153  QDomElement child=element.firstChild().toElement();
154  while (!child.isNull())
155  {
156  if (child.tagName() == "ManipulatedCameraParameters")
157  {
158  setFlySpeed(DomUtils::floatFromDom(child, "flySpeed", flySpeed()));
159 
160  QDomElement schild=child.firstChild().toElement();
161  while (!schild.isNull())
162  {
163  if (schild.tagName() == "flyUpVector")
164  setFlyUpVector(Vec(schild));
165 
166  schild = schild.nextSibling().toElement();
167  }
168  }
169  child = child.nextSibling().toElement();
170  }
171 }
172 
173 
175 // M o u s e h a n d l i n g //
177 
178 #ifndef DOXYGEN
179 
180 void ManipulatedCameraFrame::startAction(int ma, bool withConstraint)
181 {
182  ManipulatedFrame::startAction(ma, withConstraint);
183 
184  switch (action_)
185  {
188  case QGLViewer::DRIVE:
189 #if QT_VERSION >= 0x040000
190  flyTimer_.setSingleShot(false);
191 #endif
192  flyTimer_.start(10);
193  break;
194  default:
195  break;
196  }
197 }
198 #endif
199 
204 void ManipulatedCameraFrame::mouseMoveEvent(QMouseEvent* const event, Camera* const camera)
205 {
206  // #CONNECTION# QGLViewer::mouseMoveEvent does the updateGL.
207  switch (action_)
208  {
210  {
211  const QPoint delta = prevPos_ - event->pos();
212  Vec trans(static_cast<float>(delta.x()), static_cast<float>(-delta.y()), 0.0);
213  // Scale to fit the screen mouse displacement
214  switch (camera->type())
215  {
216  case Camera::PERSPECTIVE :
217  trans *= 2.0 * tan(camera->fieldOfView()/2.0) *
218  fabs((camera->frame()->coordinatesOf(revolveAroundPoint())).z) / camera->screenHeight();
219  break;
220  case Camera::ORTHOGRAPHIC :
221  {
222  GLdouble w,h;
223  camera->getOrthoWidthHeight(w, h);
224  trans[0] *= 2.0 * w / camera->screenWidth();
225  trans[1] *= 2.0 * h / camera->screenHeight();
226  break;
227  }
228  }
230  break;
231  }
232 
234  {
235  Quaternion rot = pitchYawQuaternion(event->x(), event->y(), camera);
236  rotate(rot);
237  //#CONNECTION# wheelEvent MOVE_FORWARD case
238  // actual translation is made in flyUpdate().
239  //translate(inverseTransformOf(Vec(0.0, 0.0, -flySpeed())));
240  break;
241  }
242 
244  {
245  Quaternion rot = pitchYawQuaternion(event->x(), event->y(), camera);
246  rotate(rot);
247  // actual translation is made in flyUpdate().
248  //translate(inverseTransformOf(Vec(0.0, 0.0, flySpeed())));
249  break;
250  }
251 
252  case QGLViewer::DRIVE:
253  {
254  Quaternion rot = turnQuaternion(event->x(), camera);
255  rotate(rot);
256  // actual translation is made in flyUpdate().
257  driveSpeed_ = 0.01 * (event->y() - pressPos_.y());
258  break;
259  }
260 
261  case QGLViewer::ZOOM:
262  {
263  //#CONNECTION# wheelEvent() ZOOM case
264  const float coef = qMax(fabsf((camera->frame()->coordinatesOf(camera->revolveAroundPoint())).z), 0.2f*camera->sceneRadius());
265  Vec trans(0.0, 0.0, -coef * (event->y() - prevPos_.y()) / camera->screenHeight());
267  break;
268  }
269 
271  {
272  Quaternion rot = pitchYawQuaternion(event->x(), event->y(), camera);
273  rotate(rot);
274  break;
275  }
276 
277  case QGLViewer::ROTATE:
278  {
279  Vec trans = camera->projectedCoordinatesOf(revolveAroundPoint());
280  Quaternion rot = deformedBallQuaternion(event->x(), event->y(), trans[0], trans[1], camera);
281  //#CONNECTION# These two methods should go together (spinning detection and activation)
282  computeMouseSpeed(event);
284  spin();
285  break;
286  }
287 
289  {
290  Vec trans = camera->projectedCoordinatesOf(revolveAroundPoint());
291 
292  const float angle = atan2(event->y() - trans[1], event->x() - trans[0]) - atan2(prevPos_.y()-trans[1], prevPos_.x()-trans[0]);
293 
294  Quaternion rot(Vec(0.0, 0.0, 1.0), angle);
295  //#CONNECTION# These two methods should go together (spinning detection and activation)
296  computeMouseSpeed(event);
298  spin();
300  break;
301  }
302 
303  case QGLViewer::ROLL:
304  {
305  const float angle = M_PI * (event->x() - prevPos_.x()) / camera->screenWidth();
306  Quaternion rot(Vec(0.0, 0.0, 1.0), angle);
307  rotate(rot);
310  break;
311  }
312 
314  {
315  Vec trans;
316  int dir = mouseOriginalDirection(event);
317  if (dir == 1)
318  trans.setValue(static_cast<float>(prevPos_.x() - event->x()), 0.0, 0.0);
319  else if (dir == -1)
320  trans.setValue(0.0, static_cast<float>(event->y() - prevPos_.y()), 0.0);
321 
322  switch (camera->type())
323  {
324  case Camera::PERSPECTIVE :
325  trans *= 2.0 * tan(camera->fieldOfView()/2.0) *
326  fabs((camera->frame()->coordinatesOf(revolveAroundPoint())).z) / camera->screenHeight();
327  break;
328  case Camera::ORTHOGRAPHIC :
329  {
330  GLdouble w,h;
331  camera->getOrthoWidthHeight(w, h);
332  trans[0] *= 2.0 * w / camera->screenWidth();
333  trans[1] *= 2.0 * h / camera->screenHeight();
334  break;
335  }
336  }
337 
339  break;
340  }
341 
344  break;
345  }
346 
348  {
349  prevPos_ = event->pos();
351  // ZOOM_ON_REGION should not emit manipulated().
352  // prevPos_ is used to draw rectangle feedback.
354  }
355 }
356 
357 
360 void ManipulatedCameraFrame::mouseReleaseEvent(QMouseEvent* const event, Camera* const camera)
361 {
363  flyTimer_.stop();
364 
366  camera->fitScreenRegion(QRect(pressPos_, event->pos()));
367 
369 }
370 
377 void ManipulatedCameraFrame::wheelEvent(QWheelEvent* const event, Camera* const camera)
378 {
379  //#CONNECTION# QGLViewer::setWheelBinding, ManipulatedFrame::wheelEvent.
380  switch (action_)
381  {
382  case QGLViewer::ZOOM:
383  {
384  const float wheelSensitivityCoef = 8E-4f;
385  //#CONNECTION# mouseMoveEvent() ZOOM case
386  const float coef = qMax(fabsf((camera->frame()->coordinatesOf(camera->revolveAroundPoint())).z), 0.2f*camera->sceneRadius());
387  Vec trans(0.0, 0.0, coef * event->delta() * wheelSensitivity() * wheelSensitivityCoef);
390  break;
391  }
394  //#CONNECTION# mouseMoveEvent() MOVE_FORWARD case
395  translate(inverseTransformOf(Vec(0.0, 0.0, 0.2*flySpeed()*event->delta())));
397  break;
398  default:
399  break;
400  }
401 
402  // #CONNECTION# startAction should always be called before
405 
406  // The wheel triggers a fastDraw. A final updateGL is needed after the last wheel event to
407  // polish the rendering using draw(). Since the last wheel event does not say its name, we use
408  // the flyTimer_ to trigger flyUpdate(), which emits manipulated. Two wheel events
409  // separated by more than this delay milliseconds will trigger a draw().
410  const int finalDrawAfterWheelEventDelay = 400;
411 
412  // Starts (or prolungates) the timer.
413 #if QT_VERSION >= 0x040000
414  flyTimer_.setSingleShot(true);
415  flyTimer_.start(finalDrawAfterWheelEventDelay);
416 #else
417  flyTimer_.start(finalDrawAfterWheelEventDelay, true);
418 #endif
419 
420  // This could also be done *before* manipulated is emitted, so that isManipulated() returns false.
421  // But then fastDraw would not be used with wheel.
422  // Detecting the last wheel event and forcing a final draw() is done using the timer_.
424 }
425 
427 
430 {
431  return Quaternion(Vec(0.0, 1.0, 0.0), rotationSensitivity()*(prevPos_.x()-x)/camera->screenWidth());
432 }
433 
437 {
438  const Quaternion rotX(Vec(1.0, 0.0, 0.0), rotationSensitivity()*(prevPos_.y()-y)/camera->screenHeight());
439  const Quaternion rotY(transformOf(flyUpVector()), rotationSensitivity()*(prevPos_.x()-x)/camera->screenWidth());
440  return rotY * rotX;
441 }
void setValue(double X, double Y, double Z)
Definition: vec.h:129
virtual void initFromDOMElement(const QDomElement &element)
The ManipulatedCameraFrame class represents a ManipulatedFrame with Camera specific mouse bindings...
Vec inverseTransformOf(const Vec &src) const
Definition: frame.cpp:847
A ManipulatedFrame is a Frame that can be rotated and translated using the mouse. ...
virtual void mouseMoveEvent(QMouseEvent *const event, 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:1441
float translationSensitivity() const
Vec transformOf(const Vec &src) const
Definition: frame.cpp:834
ManipulatedCameraFrame & operator=(const ManipulatedCameraFrame &mcf)
#define M_PI
int screenWidth() const
Definition: camera.h:228
void setConstraint(Constraint *const constraint)
Definition: frame.h:368
Type type() const
Definition: camera.h:196
ManipulatedCameraFrame * frame() const
Definition: camera.h:372
void fitScreenRegion(const QRect &rectangle)
Definition: camera.cpp:1000
void rotate(Quaternion &q)
Definition: frame.cpp:376
The Vec class represents 3D positions and 3D vectors.
Definition: vec.h:69
double z
Definition: vec.h:85
float sceneRadius() const
Definition: camera.h:325
virtual void getOrthoWidthHeight(GLdouble &halfWidth, GLdouble &halfHeight) const
Definition: camera.cpp:301
Quaternion turnQuaternion(int x, const Camera *const camera)
Vec revolveAroundPoint() const
Definition: camera.h:361
int screenHeight() const
Definition: camera.h:233
virtual QDomElement domElement(const QString &name, QDomDocument &document) const
virtual void wheelEvent(QWheelEvent *const event, Camera *const camera)
void setSpinningQuaternion(const Quaternion &spinningQuaternion)
#define Q_EMIT
Definition: config.h:121
Vec coordinatesOf(const Vec &src) const
Definition: frame.cpp:693
#define qMax(a, b)
Definition: config.h:112
void computeMouseSpeed(const QMouseEvent *const e)
void translate(Vec &t)
Definition: frame.cpp:335
A perspective or orthographic camera.
Definition: camera.h:81
virtual void initFromDOMElement(const QDomElement &element)
ManipulatedFrame & operator=(const ManipulatedFrame &mf)
The Quaternion class represents 3D rotations and orientations.
Definition: quaternion.h:66
virtual void startAction(int ma, bool withConstraint=true)
virtual void mouseReleaseEvent(QMouseEvent *const event, Camera *const camera)
float fieldOfView() const
Definition: camera.h:208
int mouseOriginalDirection(const QMouseEvent *const e)
Quaternion deformedBallQuaternion(int x, int y, float cx, float cy, const Camera *const camera)
Quaternion spinningQuaternion() const
Vec localInverseTransformOf(const Vec &src) const
Definition: frame.cpp:872
virtual QDomElement domElement(const QString &name, QDomDocument &document) const
static float floatFromDom(const QDomElement &e, const QString &attribute, float defValue)
Definition: domUtils.h:56
virtual void startAction(int ma, bool withConstraint=true)
void rotateAroundPoint(Quaternion &rotation, const Vec &point)
Definition: frame.cpp:414
double x
Definition: vec.h:85


octovis
Author(s): Kai M. Wurm , Armin Hornung
autogenerated on Mon Jun 10 2019 14:00:25