QGIS API Documentation 3.41.0-Master (cea29feecf2)
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 <QEasingCurve>
19#include <QDomDocument>
20
22
24{
25 return mKeyframes.isEmpty() ? 0 : mKeyframes.constLast().time;
26}
27
29{
30 if ( mKeyframes.isEmpty() )
31 return Keyframe();
32
33 if ( time < mKeyframes.constFirst().time )
34 {
35 return mKeyframes.first();
36 }
37 else if ( time >= mKeyframes.constLast().time )
38 {
39 return mKeyframes.last();
40 }
41 else
42 {
43 // TODO: make easing curves configurable.
44 // QEasingCurve is probably not flexible enough, we may need more granular
45 // control with Bezier curves to allow smooth transition at keyframes
46
47 for ( int i = 0; i < mKeyframes.size() - 1; i++ )
48 {
49 const Keyframe &k0 = mKeyframes.at( i );
50 const Keyframe &k1 = mKeyframes.at( i + 1 );
51 if ( time >= k0.time && time <= k1.time )
52 {
53 const float ip = ( time - k0.time ) / ( k1.time - k0.time );
54 const float eIp = mEasingCurve.valueForProgress( ip );
55 const float eIip = 1.0f - eIp;
56
57 Keyframe kf;
58 kf.time = time;
59 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 );
60 kf.dist = k0.dist * eIip + k1.dist * eIp;
61 kf.pitch = k0.pitch * eIip + k1.pitch * eIp;
62
63 // always use shorter angle
64 float yaw0 = fmod( k0.yaw, 360 ), yaw1 = fmod( k1.yaw, 360 );
65 if ( std::abs( yaw0 - yaw1 ) > 180 )
66 {
67 if ( yaw0 < yaw1 )
68 yaw0 += 360;
69 else
70 yaw1 += 360;
71 }
72
73 kf.yaw = yaw0 * eIip + yaw1 * eIp;
74 return kf;
75 }
76 }
77 }
78 Q_ASSERT( false );
79 return Keyframe();
80}
81
82void Qgs3DAnimationSettings::readXml( const QDomElement &elem )
83{
84 mEasingCurve = QEasingCurve( ( QEasingCurve::Type ) elem.attribute( QStringLiteral( "interpolation" ), QStringLiteral( "0" ) ).toInt() );
85
86 mKeyframes.clear();
87
88 const QDomElement elemKeyframes = elem.firstChildElement( QStringLiteral( "keyframes" ) );
89 QDomElement elemKeyframe = elemKeyframes.firstChildElement( QStringLiteral( "keyframe" ) );
90 while ( !elemKeyframe.isNull() )
91 {
92 Keyframe kf;
93 kf.time = elemKeyframe.attribute( QStringLiteral( "time" ) ).toFloat();
94 kf.point.set( elemKeyframe.attribute( QStringLiteral( "x" ) ).toDouble(), elemKeyframe.attribute( QStringLiteral( "y" ) ).toDouble(), elemKeyframe.attribute( QStringLiteral( "z" ) ).toDouble() );
95 kf.dist = elemKeyframe.attribute( QStringLiteral( "dist" ) ).toFloat();
96 kf.pitch = elemKeyframe.attribute( QStringLiteral( "pitch" ) ).toFloat();
97 kf.yaw = elemKeyframe.attribute( QStringLiteral( "yaw" ) ).toFloat();
98 mKeyframes.append( kf );
99 elemKeyframe = elemKeyframe.nextSiblingElement( QStringLiteral( "keyframe" ) );
100 }
101}
102
103QDomElement Qgs3DAnimationSettings::writeXml( QDomDocument &doc ) const
104{
105 QDomElement elem = doc.createElement( QStringLiteral( "animation3d" ) );
106 elem.setAttribute( QStringLiteral( "interpolation" ), mEasingCurve.type() );
107
108 QDomElement elemKeyframes = doc.createElement( QStringLiteral( "keyframes" ) );
109
110 for ( const Keyframe &keyframe : mKeyframes )
111 {
112 QDomElement elemKeyframe = doc.createElement( QStringLiteral( "keyframe" ) );
113 elemKeyframe.setAttribute( QStringLiteral( "time" ), keyframe.time );
114 elemKeyframe.setAttribute( QStringLiteral( "x" ), keyframe.point.x() );
115 elemKeyframe.setAttribute( QStringLiteral( "y" ), keyframe.point.y() );
116 elemKeyframe.setAttribute( QStringLiteral( "z" ), keyframe.point.z() );
117 elemKeyframe.setAttribute( QStringLiteral( "dist" ), keyframe.dist );
118 elemKeyframe.setAttribute( QStringLiteral( "pitch" ), keyframe.pitch );
119 elemKeyframe.setAttribute( QStringLiteral( "yaw" ), keyframe.yaw );
120 elemKeyframes.appendChild( elemKeyframe );
121 }
122
123 elem.appendChild( elemKeyframes );
124
125 return elem;
126}
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:50
double z() const
Returns Z coordinate.
Definition qgsvector3d.h:52
double x() const
Returns X coordinate.
Definition qgsvector3d.h:48
void set(double x, double y, double z)
Sets vector coordinates.
Definition qgsvector3d.h:73
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 world coords.
float time
Relative time of the keyframe in seconds.
float dist
Distance of the camera from the focal point.