QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgs3danimationsettings.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgs3danimationsettings.cpp
3 --------------------------------------
4 Date : July 2018
5 Copyright : (C) 2018 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include <QDomDocument>
19#include <QEasingCurve>
20#include <QString>
21
22using namespace Qt::StringLiterals;
23
25
27{
28 return mKeyframes.isEmpty() ? 0 : mKeyframes.constLast().time;
29}
30
32{
33 if ( mKeyframes.isEmpty() )
34 return Keyframe();
35
36 if ( time < mKeyframes.constFirst().time )
37 {
38 return mKeyframes.first();
39 }
40 else if ( time >= mKeyframes.constLast().time )
41 {
42 return mKeyframes.last();
43 }
44 else
45 {
46 // TODO: make easing curves configurable.
47 // QEasingCurve is probably not flexible enough, we may need more granular
48 // control with Bezier curves to allow smooth transition at keyframes
49
50 for ( int i = 0; i < mKeyframes.size() - 1; i++ )
51 {
52 const Keyframe &k0 = mKeyframes.at( i );
53 const Keyframe &k1 = mKeyframes.at( i + 1 );
54 if ( time >= k0.time && time <= k1.time )
55 {
56 const float ip = ( time - k0.time ) / ( k1.time - k0.time );
57 const float eIp = mEasingCurve.valueForProgress( ip );
58 const float eIip = 1.0f - eIp;
59
60 Keyframe kf;
61 kf.time = time;
62 kf.point.set( k0.point.x() * eIip + k1.point.x() * eIp, k0.point.y() * eIip + k1.point.y() * eIp, k0.point.z() * eIip + k1.point.z() * eIp );
63 kf.dist = k0.dist * eIip + k1.dist * eIp;
64 kf.pitch = k0.pitch * eIip + k1.pitch * eIp;
65
66 // always use shorter angle
67 float yaw0 = fmod( k0.yaw, 360 ), yaw1 = fmod( k1.yaw, 360 );
68 if ( std::abs( yaw0 - yaw1 ) > 180 )
69 {
70 if ( yaw0 < yaw1 )
71 yaw0 += 360;
72 else
73 yaw1 += 360;
74 }
75
76 kf.yaw = yaw0 * eIip + yaw1 * eIp;
77 return kf;
78 }
79 }
80 }
81 Q_ASSERT( false );
82 return Keyframe();
83}
84
85void Qgs3DAnimationSettings::readXml( const QDomElement &elem )
86{
87 mEasingCurve = QEasingCurve( ( QEasingCurve::Type ) elem.attribute( u"interpolation"_s, u"0"_s ).toInt() );
88
89 mKeyframes.clear();
90
91 const QDomElement elemKeyframes = elem.firstChildElement( u"keyframes"_s );
92 QDomElement elemKeyframe = elemKeyframes.firstChildElement( u"keyframe"_s );
93 while ( !elemKeyframe.isNull() )
94 {
95 Keyframe kf;
96 kf.time = elemKeyframe.attribute( u"time"_s ).toFloat();
97 kf.point.set( elemKeyframe.attribute( u"x"_s ).toDouble(), elemKeyframe.attribute( u"y"_s ).toDouble(), elemKeyframe.attribute( u"z"_s ).toDouble() );
98 kf.dist = elemKeyframe.attribute( u"dist"_s ).toFloat();
99 kf.pitch = elemKeyframe.attribute( u"pitch"_s ).toFloat();
100 kf.yaw = elemKeyframe.attribute( u"yaw"_s ).toFloat();
101 mKeyframes.append( kf );
102 elemKeyframe = elemKeyframe.nextSiblingElement( u"keyframe"_s );
103 }
104}
105
106QDomElement Qgs3DAnimationSettings::writeXml( QDomDocument &doc ) const
107{
108 QDomElement elem = doc.createElement( u"animation3d"_s );
109 elem.setAttribute( u"interpolation"_s, mEasingCurve.type() );
110
111 QDomElement elemKeyframes = doc.createElement( u"keyframes"_s );
112
113 for ( const Keyframe &keyframe : mKeyframes )
114 {
115 QDomElement elemKeyframe = doc.createElement( u"keyframe"_s );
116 elemKeyframe.setAttribute( u"time"_s, keyframe.time );
117 elemKeyframe.setAttribute( u"x"_s, keyframe.point.x() );
118 elemKeyframe.setAttribute( u"y"_s, keyframe.point.y() );
119 elemKeyframe.setAttribute( u"z"_s, keyframe.point.z() );
120 elemKeyframe.setAttribute( u"dist"_s, keyframe.dist );
121 elemKeyframe.setAttribute( u"pitch"_s, keyframe.pitch );
122 elemKeyframe.setAttribute( u"yaw"_s, keyframe.yaw );
123 elemKeyframes.appendChild( elemKeyframe );
124 }
125
126 elem.appendChild( elemKeyframes );
127
128 return elem;
129}
QDomElement writeXml(QDomDocument &doc) const
Writes configuration to a DOM element, to be used later with readXml().
Keyframe interpolate(float time) const
Interpolates camera position and rotation at the given point in time.
float duration() const
Returns duration of the whole animation in seconds.
void readXml(const QDomElement &elem)
Reads configuration from a DOM element previously written by writeXml().
double y() const
Returns Y coordinate.
Definition qgsvector3d.h:52
double z() const
Returns Z coordinate.
Definition qgsvector3d.h:54
double x() const
Returns X coordinate.
Definition qgsvector3d.h:50
void set(double x, double y, double z)
Sets vector coordinates.
Definition qgsvector3d.h:75
float pitch
Tilt of the camera in degrees (0 = looking from the top, 90 = looking from the side,...
float yaw
Horizontal rotation around the focal point in degrees.
QgsVector3D point
Point towards which the camera is looking in 3D map coords.
float time
Relative time of the keyframe in seconds.
float dist
Distance of the camera from the focal point.