Developer Documentation
QtBaseViewerFlyAnimation.cc
1/*===========================================================================*\
2* *
3* OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39* *
40\*===========================================================================*/
41
42
43
44
45
46
47//=============================================================================
48//
49// CLASS glViewer - IMPLEMENTATION
50//
51//=============================================================================
52
53
54//== INCLUDES =================================================================
55
56#include "QtBaseViewer.hh"
57#include <QPropertyAnimation>
58
59
60//== NAMESPACES ===============================================================
61
62//== IMPLEMENTATION ==========================================================
63
64
65void glViewer::flyTo(const QPoint& _pos, bool _moveBack)
66{
68
69 size_t nodeIdx, targetIdx;
70 ACG::Vec3d hitPoint;
71
72 if (pick( ACG::SceneGraph::PICK_ANYTHING, _pos, nodeIdx, targetIdx, &hitPoint))
73 {
74 if (projectionMode_ == PERSPECTIVE_PROJECTION)
75 {
76 ACG::Vec3d eye(glstate_->eye());
77 ACG::Vec3d t = hitPoint - eye;
78 ACG::Vec3d e = eye + t * (_moveBack ? -0.5f : 0.5f);
79 flyTo(e, hitPoint, 300);
80 }
81 else
82 {
83 // Project hitpoint to get depth
84 ACG::Vec3d hitPointProjected = glstate_->project(hitPoint);
85
86 // Create projected center point with same depth as hitpoint
87 ACG::Vec3d centerPointProjected = hitPointProjected;
88
89 // Get viewport data
90 int w = 0, h = 0,left = 0, bottom = 0;
91 glstate_->get_viewport(left, bottom, w, h);
92
93 // Compute the center point. Note that the project function includes the viewport matrix.
94 // As we have different viewports for the viewer but one global coord system,
95 // we need to set the real center coordinates and therefore add the lower left corner position
96 // which is the left and bottom of the viewport
97 centerPointProjected[0] = left + glstate_->viewport_width() / 2.0 ;
98 centerPointProjected[1] = bottom + glstate_->viewport_height() / 2.0 ;
99
100 // unproject center point
101 ACG::Vec3d centerPointUnProjected = glstate_->unproject(centerPointProjected);
102
103 // translation vector to make hit point project to center point (both need same depth)
104 ACG::Vec3d t = hitPoint - centerPointUnProjected;
105
106 // Transform to correct translation vector with modelview.
108
109 // remember originalWidth
111
112 // Initialize as we start at 0.0
113 lastAnimationPos_ = 0.0;
114
115 // store the direction for the actual animation
116 flyMoveBack_ = _moveBack;
117
118 // Set the double click point as the new trackball center
119 // Rotations will use this point as the center.
120 properties_.trackballCenter( hitPoint );
121
122 // Create animation object
123 if ( flyAnimationOrthogonal_ == nullptr) {
124 flyAnimationOrthogonal_ = new QPropertyAnimation(this, "currentAnimationPosition");
125
126
127 // Range is from 0 to one, as we linearly interpolate the animation
128 flyAnimationOrthogonal_->setStartValue(0.0);
129 flyAnimationOrthogonal_->setEndValue(1.0);
130
131 // Connect signals for the animation and its end
132 connect(flyAnimationOrthogonal_, SIGNAL(valueChanged(QVariant)), this, SLOT(flyAnimationOrthogonal(QVariant)));
133 connect(flyAnimationOrthogonal_, SIGNAL(finished()), this, SLOT(flyAnimationOrthogonalFinished()));
134 }
135
136 // Set duration
137 flyAnimationOrthogonal_->setDuration(300);
138
139 // Start it
141
142 }
143 }
144}
145
147
148 const double pos = _pos.toDouble();
149
150 // compute difference
151 const double diff = pos - lastAnimationPos_;
152
153 // zoom back one frame
154 if ( flyMoveBack_ ) {
155 // Move back by factor 2
157 } else
158 // Move forward with factor 0.5
159 properties_.orthoWidth( flyOrthoWidthOriginal_ * (1.0 - 0.5 * pos ) );
160
161 // apply translation
162 translate(- flyTranslation_ * diff );
163
164 // Store our current position for next loop
165 lastAnimationPos_ = pos;
166
167 // Pick cache is definitely invalid after that
168 updatePickCache_ = true;
169
170 // update rendering
171 update();
172}
173
175
176 const double pos = _pos.toDouble();
177
178 // Animate pos from 0 to 1 so we need to calculate the difference and the resulting transformations
180 double a = (pos - lastAnimationPos_) * flyAngle_ ;
181
182 translate(t);
183
184 // Only rotate, if we have realistic values and if rotation is allowed
185 if ( allowRotation_ )
186 if (fabs(a) > FLT_MIN)
188
189 // Pick cache is definitely invalid after that
190 updatePickCache_ = true;
191
192 // Store our current position for next loop
193 lastAnimationPos_ = pos;
194
195 // update rendering
196 update();
197
198}
199
201
202 // Update the projection matrix
204
205 // Redraw scene
206 updateGL();
207
208 // Inform others that the current view has changed
209 emit viewChanged();
210
211}
212
214
215 // Update the trackball to the final position
217 properties_.trackballRadius( std::max( properties_.sceneRadius(),( flyCenter_ - flyPosition_ ).norm() * 0.9f ) );
218
219}
220
221void glViewer::flyTo(const ACG::Vec3d& _position,
222 const ACG::Vec3d& _center,
223 int _time)
224{
225 makeCurrent();
226
227 // compute rotation
230 ACG::Vec3d view =(p-c).normalize();
231 ACG::Vec3d z(0,0,1);
232
233 flyAxis_ = (z % -view).normalize();
234
235 flyAngle_ = acos(std::max(-1.0, std::min(1.0, (z | view)))) / M_PI * 180.0;
236
237 if (flyAngle_ > 175)
238 flyAxis_ = ACG::Vec3d(0,1,0);
239
240 // compute translation
241 ACG::Vec3d target = glstate_->modelview().transform_point(_center);
242 flyTranslation_ = ACG::Vec3d( -target[0], -target[1], -target[2] - (_position-_center).norm() );
243
244 // Store other values for animation
245 flyCenter_ = _center;
246 flyPosition_ = _position;
247
248 // Initialize as we start at 0.0
249 lastAnimationPos_ = 0.0;
250
251 // Create animation object
252 if ( flyAnimationPerspective_ == nullptr) {
253 flyAnimationPerspective_ = new QPropertyAnimation(this, "currentAnimationPosition");
254
255 // Range is from 0 to one, as we linearly interpolate the animation
256 flyAnimationPerspective_->setStartValue(0.0);
257 flyAnimationPerspective_->setEndValue(1.0);
258
259 // Connect signals for the animation and its end
260 connect(flyAnimationPerspective_, SIGNAL(valueChanged(QVariant)), this, SLOT(flyAnimationPerspective(QVariant)));
261 connect(flyAnimationPerspective_, SIGNAL(finished()), this, SLOT(flyAnimationPerspectiveFinished()));
262 }
263
264 // Set duration
265 flyAnimationPerspective_->setDuration(_time);
266
267 // Start it
269}
270
271
272//=============================================================================
273
274//=============================================================================
Vec3d eye() const
get eye point
Definition: GLState.cc:886
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:816
int viewport_width() const
get viewport width
Definition: GLState.hh:847
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:651
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
int viewport_height() const
get viewport height
Definition: GLState.hh:849
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
Definition: GLState.hh:841
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x',y',z',0) = A * (x,y,z,0)
VectorT< T, 3 > transform_point(const VectorT< T, 3 > &_v) const
transform point (x',y',z',1) = M * (x,y,z,1)
double orthoWidth()
Get width of the gl scene in orthogonal projection mode (defaults to 2.0)
ACG::Vec3d trackballCenter()
Get virtual trackball center (rotation center when using mouse)
double sceneRadius()
Get radius of the current scene.
double trackballRadius()
Get trackball radius (rotation sphere when using mouse)
virtual void makeCurrent()
Makes this widget the current widget for OpenGL operations.
bool pick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
bool allowRotation_
mouse interaction position
virtual void updateGL()
Redraw scene. Triggers paint event for updating the view (cf. drawNow()).
double lastAnimationPos_
The last position of the animation to compute the difference vector.
void viewChanged()
This signal is emitted whenever the view is changed by the user.
@ PERSPECTIVE_PROJECTION
perspective
void translate(const ACG::Vec3d &trans)
translate the scene and update modelview matrix
ACG::Vec3d flyPosition_
The new position after the flyTo animation.
double flyOrthoWidthOriginal_
Original orthogonal width during flyTo in orthogonal mode.
void flyAnimationPerspective(QVariant _pos)
Slot called during flyTo Animation in perspective mode.
QPropertyAnimation * flyAnimationPerspective_
The animation object for flyTo.
ACG::Vec3d flyCenter_
The new center after the flyTo animation.
QPropertyAnimation * flyAnimationOrthogonal_
The animation object for flyTo.
ACG::GLState * glstate_
Gl State.
double flyAngle_
The rotation angle (full angle) for fly to animation.
Viewer::ViewerProperties & properties_
All properties for this viewer.
ACG::Vec3d flyAxis_
The rotation axis for fly to animation.
void rotate(const ACG::Vec3d &axis, double angle)
rotate the scene (around its center) and update modelview matrix
void flyAnimationOrthogonalFinished()
Slot called when flyTo orthogonal Animation finished.
bool flyMoveBack_
Flag for fly in orthogonal mode if we move back or forward.
virtual void flyTo(const QPoint &_pos, bool _moveBack)
Animated flight to or away from a given point.
bool updatePickCache_
Should the pick cache be updated.
void flyAnimationPerspectiveFinished()
Slot called when flyTo perspective Animation finished.
void flyAnimationOrthogonal(QVariant _pos)
Slot called during flyTo Animation in orthogonal mode.
void updateProjectionMatrix(double _aspect=0.0)
updates projection matrix
ACG::Vec3d flyTranslation_
Full translation between start and ed of animation.
@ PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121