QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 
16 #include "qgs3danimationsettings.h"
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  float ip = ( time - k0.time ) / ( k1.time - k0.time );
54  float eIp = mEasingCurve.valueForProgress( ip );
55  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 
84 void Qgs3DAnimationSettings::readXml( const QDomElement &elem )
85 {
86  mEasingCurve = QEasingCurve( ( QEasingCurve::Type ) elem.attribute( QStringLiteral( "interpolation" ), QStringLiteral( "0" ) ).toInt() );
87 
88  mKeyframes.clear();
89 
90  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 
107 QDomElement 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 }
qgs3danimationsettings.h
Qgs3DAnimationSettings::Keyframe
keyframe definition
Definition: qgs3danimationsettings.h:46
Qgs3DAnimationSettings::Keyframe::time
float time
Relative time of the keyframe in seconds.
Definition: qgs3danimationsettings.h:47
QgsVector3D::y
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:51
Qgs3DAnimationSettings::Keyframe::pitch
float pitch
Tilt of the camera in degrees (0 = looking from the top, 90 = looking from the side,...
Definition: qgs3danimationsettings.h:50
QgsVector3D::set
void set(double x, double y, double z)
Sets vector coordinates.
Definition: qgsvector3d.h:56
Qgs3DAnimationSettings::readXml
void readXml(const QDomElement &elem)
Reads configuration from a DOM element previously written by writeXml()
Definition: qgs3danimationsettings.cpp:84
Qgs3DAnimationSettings::writeXml
QDomElement writeXml(QDomDocument &doc) const
Writes configuration to a DOM element, to be used later with readXml()
Definition: qgs3danimationsettings.cpp:107
Qgs3DAnimationSettings::Keyframe::dist
float dist
Distance of the camera from the focal point.
Definition: qgs3danimationsettings.h:49
QgsVector3D::z
double z() const
Returns Z coordinate.
Definition: qgsvector3d.h:53
Qgs3DAnimationSettings::duration
float duration() const
Returns duration of the whole animation in seconds.
Definition: qgs3danimationsettings.cpp:23
Qgs3DAnimationSettings::Keyframe::point
QgsVector3D point
Point towards which the camera is looking in 3D world coords.
Definition: qgs3danimationsettings.h:48
Qgs3DAnimationSettings::Qgs3DAnimationSettings
Qgs3DAnimationSettings()
ctor
Qgs3DAnimationSettings::interpolate
Keyframe interpolate(float time) const
Interpolates camera position and rotation at the given point in time.
Definition: qgs3danimationsettings.cpp:28
Qgs3DAnimationSettings::Keyframe::yaw
float yaw
Horizontal rotation around the focal point in degrees.
Definition: qgs3danimationsettings.h:51
QgsVector3D::x
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:49