QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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,
60 k0.point.y() * eIip + k1.point.y() * eIp,
61 k0.point.z() * eIip + k1.point.z() * eIp );
62 kf.dist = k0.dist * eIip + k1.dist * eIp;
63 kf.pitch = k0.pitch * eIip + k1.pitch * eIp;
64
65 // always use shorter angle
66 float yaw0 = fmod( k0.yaw, 360 ), yaw1 = fmod( k1.yaw, 360 );
67 if ( std::abs( yaw0 - yaw1 ) > 180 )
68 {
69 if ( yaw0 < yaw1 )
70 yaw0 += 360;
71 else
72 yaw1 += 360;
73 }
74
75 kf.yaw = yaw0 * eIip + yaw1 * eIp;
76 return kf;
77 }
78 }
79 }
80 Q_ASSERT( false );
81 return Keyframe();
82}
83
84void Qgs3DAnimationSettings::readXml( const QDomElement &elem )
85{
86 mEasingCurve = QEasingCurve( ( QEasingCurve::Type ) elem.attribute( QStringLiteral( "interpolation" ), QStringLiteral( "0" ) ).toInt() );
87
88 mKeyframes.clear();
89
90 const QDomElement elemKeyframes = elem.firstChildElement( QStringLiteral( "keyframes" ) );
91 QDomElement elemKeyframe = elemKeyframes.firstChildElement( QStringLiteral( "keyframe" ) );
92 while ( !elemKeyframe.isNull() )
93 {
94 Keyframe kf;
95 kf.time = elemKeyframe.attribute( QStringLiteral( "time" ) ).toFloat();
96 kf.point.set( elemKeyframe.attribute( QStringLiteral( "x" ) ).toDouble(),
97 elemKeyframe.attribute( QStringLiteral( "y" ) ).toDouble(),
98 elemKeyframe.attribute( QStringLiteral( "z" ) ).toDouble() );
99 kf.dist = elemKeyframe.attribute( QStringLiteral( "dist" ) ).toFloat();
100 kf.pitch = elemKeyframe.attribute( QStringLiteral( "pitch" ) ).toFloat();
101 kf.yaw = elemKeyframe.attribute( QStringLiteral( "yaw" ) ).toFloat();
102 mKeyframes.append( kf );
103 elemKeyframe = elemKeyframe.nextSiblingElement( QStringLiteral( "keyframe" ) );
104 }
105}
106
107QDomElement Qgs3DAnimationSettings::writeXml( QDomDocument &doc ) const
108{
109 QDomElement elem = doc.createElement( QStringLiteral( "animation3d" ) );
110 elem.setAttribute( QStringLiteral( "interpolation" ), mEasingCurve.type() );
111
112 QDomElement elemKeyframes = doc.createElement( QStringLiteral( "keyframes" ) );
113
114 for ( const Keyframe &keyframe : mKeyframes )
115 {
116 QDomElement elemKeyframe = doc.createElement( QStringLiteral( "keyframe" ) );
117 elemKeyframe.setAttribute( QStringLiteral( "time" ), keyframe.time );
118 elemKeyframe.setAttribute( QStringLiteral( "x" ), keyframe.point.x() );
119 elemKeyframe.setAttribute( QStringLiteral( "y" ), keyframe.point.y() );
120 elemKeyframe.setAttribute( QStringLiteral( "z" ), keyframe.point.z() );
121 elemKeyframe.setAttribute( QStringLiteral( "dist" ), keyframe.dist );
122 elemKeyframe.setAttribute( QStringLiteral( "pitch" ), keyframe.pitch );
123 elemKeyframe.setAttribute( QStringLiteral( "yaw" ), keyframe.yaw );
124 elemKeyframes.appendChild( elemKeyframe );
125 }
126
127 elem.appendChild( elemKeyframes );
128
129 return elem;
130}
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:51
double z() const
Returns Z coordinate.
Definition: qgsvector3d.h:53
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:49
void set(double x, double y, double z)
Sets vector coordinates.
Definition: qgsvector3d.h:56
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.