Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Initial work on animation support
- new class to store animation configuration - new class for animation configuration GUI - animation implementation using Qt3D Animation framework
- Loading branch information
Showing
10 changed files
with
489 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/*************************************************************************** | ||
qgs3danimationsettings.cpp | ||
-------------------------------------- | ||
Date : July 2018 | ||
Copyright : (C) 2018 by Martin Dobias | ||
Email : wonder dot sk at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgs3danimationsettings.h" | ||
|
||
#include <Qt3DAnimation/QKeyframeAnimation> | ||
#include <Qt3DAnimation/QAnimationGroup> | ||
|
||
Qgs3DAnimationSettings::Qgs3DAnimationSettings() | ||
{ | ||
|
||
} | ||
|
||
float Qgs3DAnimationSettings::duration() const | ||
{ | ||
return mKeyframes.isEmpty() ? 0 : mKeyframes.constLast().time; | ||
} | ||
|
||
Qt3DAnimation::QKeyframeAnimation *Qgs3DAnimationSettings::createAnimation( Qt3DCore::QNode *parent ) const | ||
{ | ||
Qt3DAnimation::QKeyframeAnimation *animation = new Qt3DAnimation::QKeyframeAnimation; | ||
|
||
QVector<float> framePositions; | ||
QVector<Qt3DCore::QTransform *> transforms; | ||
for ( const Keyframe &keyframe : mKeyframes ) | ||
{ | ||
framePositions << keyframe.time; | ||
Qt3DCore::QTransform *t = new Qt3DCore::QTransform( parent ); | ||
t->setTranslation( keyframe.position ); | ||
t->setRotation( keyframe.rotation ); | ||
transforms << t; | ||
} | ||
|
||
animation->setKeyframes( transforms ); | ||
animation->setFramePositions( framePositions ); | ||
|
||
//animation->setTarget(cam->transform()); | ||
// animation->setEasing(QEasingCurve(QEasingCurve::InOutQuad)); | ||
|
||
return animation; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/*************************************************************************** | ||
qgs3danimationsettings.h | ||
-------------------------------------- | ||
Date : July 2018 | ||
Copyright : (C) 2018 by Martin Dobias | ||
Email : wonder dot sk at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGS3DANIMATIONSETTINGS_H | ||
#define QGS3DANIMATIONSETTINGS_H | ||
|
||
#include <QVector3D> | ||
#include <QQuaternion> | ||
|
||
namespace Qt3DCore | ||
{ | ||
class QNode; | ||
} | ||
|
||
namespace Qt3DAnimation | ||
{ | ||
class QKeyframeAnimation; | ||
} | ||
|
||
/** | ||
* Class that holds information about animation in 3D view. The animation is defined | ||
* as a series of keyframes | ||
*/ | ||
class Qgs3DAnimationSettings | ||
{ | ||
public: | ||
Qgs3DAnimationSettings(); | ||
|
||
//! keyframe definition | ||
struct Keyframe | ||
{ | ||
float time; //!< Relative time of the keyframe in seconds | ||
QVector3D position; //!< Position of the camera | ||
QQuaternion rotation; //!< Rotation of the camera | ||
}; | ||
|
||
typedef QVector<Keyframe> Keyframes; | ||
|
||
void setKeyframes( const Keyframes &keyframes ) { mKeyframes = keyframes; } | ||
Keyframes keyFrames() const { return mKeyframes; } | ||
|
||
//! Returns duration of the whole animation in seconds | ||
float duration() const; | ||
|
||
//! Returns a new object that contains Qt3D animation according to the keyframes | ||
Qt3DAnimation::QKeyframeAnimation *createAnimation( Qt3DCore::QNode *parent ) const; | ||
|
||
// TODO: read/write routines | ||
|
||
private: | ||
Keyframes mKeyframes; | ||
}; | ||
|
||
#endif // QGS3DANIMATIONSETTINGS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/*************************************************************************** | ||
qgs3danimationwidget.cpp | ||
-------------------------------------- | ||
Date : July 2018 | ||
Copyright : (C) 2018 by Martin Dobias | ||
Email : wonder dot sk at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgs3danimationwidget.h" | ||
|
||
#include "qgs3danimationsettings.h" | ||
#include "qgsapplication.h" | ||
|
||
#include <Qt3DAnimation/QAnimationController> | ||
#include <Qt3DRender/QCamera> | ||
#include <QTimer> | ||
|
||
Qgs3DAnimationWidget::Qgs3DAnimationWidget( QWidget *parent ) | ||
: QWidget( parent ) | ||
{ | ||
setupUi( this ); | ||
|
||
btnAddKeyframe->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) ); | ||
btnRemoveKeyframe->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) ); | ||
btnEditKeyframe->setIcon( QIcon( QgsApplication::iconPath( "symbologyEdit.svg" ) ) ); | ||
btnPlayPause->setIcon( QIcon( QgsApplication::iconPath( "mTaskRunning.svg" ) ) ); | ||
|
||
cboKeyframe->addItem( tr( "<none>" ) ); | ||
|
||
mAnimationTimer = new QTimer( this ); | ||
mAnimationTimer->setInterval( 10 ); | ||
connect( mAnimationTimer, &QTimer::timeout, this, &Qgs3DAnimationWidget::onAnimationTimer ); | ||
|
||
mAnimationController = new Qt3DAnimation::QAnimationController( this ); | ||
|
||
btnPlayPause->setCheckable( true ); | ||
connect( btnPlayPause, &QToolButton::clicked, this, &Qgs3DAnimationWidget::onPlayPause ); | ||
|
||
connect( sliderTime, &QSlider::valueChanged, this, &Qgs3DAnimationWidget::onSliderValueChanged ); | ||
|
||
connect( cboKeyframe, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &Qgs3DAnimationWidget::onKeyframeChanged ); | ||
} | ||
|
||
void Qgs3DAnimationWidget::setCamera( Qt3DRender::QCamera *camera ) | ||
{ | ||
mCamera = camera; | ||
connect( mCamera, &Qt3DRender::QCamera::viewMatrixChanged, this, &Qgs3DAnimationWidget::onCameraViewMatrixChanged ); | ||
} | ||
|
||
void Qgs3DAnimationWidget::setAnimation( const Qgs3DAnimationSettings &animSettings ) | ||
{ | ||
// initialize GUI from the given animation | ||
cboKeyframe->clear(); | ||
cboKeyframe->addItem( tr( "<none>" ) ); | ||
for ( const Qgs3DAnimationSettings::Keyframe &keyframe : animSettings.keyFrames() ) | ||
{ | ||
cboKeyframe->addItem( QString( "%1 s" ).arg( keyframe.time ) ); | ||
int lastIndex = cboKeyframe->count() - 1; | ||
cboKeyframe->setItemData( lastIndex, keyframe.time, Qt::UserRole + 1 ); | ||
cboKeyframe->setItemData( lastIndex, keyframe.position, Qt::UserRole + 2 ); | ||
cboKeyframe->setItemData( lastIndex, keyframe.rotation, Qt::UserRole + 3 ); | ||
} | ||
|
||
initializeController( animSettings ); | ||
} | ||
|
||
void Qgs3DAnimationWidget::initializeController( const Qgs3DAnimationSettings &animSettings ) | ||
{ | ||
// set up animation in the controller | ||
Qt3DAnimation::QAnimationGroup *group = new Qt3DAnimation::QAnimationGroup; | ||
Qt3DAnimation::QKeyframeAnimation *animation = animSettings.createAnimation( nullptr ); // TODO: who deletes transforms? | ||
animation->setParent( group ); | ||
animation->setTarget( mCamera->transform() ); | ||
group->addAnimation( animation ); // does not delete animations later | ||
|
||
QVector<Qt3DAnimation::QAnimationGroup *> groups; | ||
groups << group; | ||
mAnimationController->setAnimationGroups( groups ); // does not delete groups later | ||
|
||
sliderTime->setMaximum( animSettings.duration() * 100 ); | ||
} | ||
|
||
Qgs3DAnimationSettings Qgs3DAnimationWidget::animation() const | ||
{ | ||
Qgs3DAnimationSettings animSettings; | ||
Qgs3DAnimationSettings::Keyframes keyframes; | ||
qDebug() << "---"; | ||
for ( int i = 1; i < cboKeyframe->count(); ++i ) | ||
{ | ||
Qgs3DAnimationSettings::Keyframe kf; | ||
kf.time = cboKeyframe->itemData( i, Qt::UserRole + 1 ).toFloat(); | ||
kf.position = cboKeyframe->itemData( i, Qt::UserRole + 2 ).value<QVector3D>(); | ||
kf.rotation = cboKeyframe->itemData( i, Qt::UserRole + 3 ).value<QQuaternion>(); | ||
keyframes << kf; | ||
qDebug() << "keyframe" << kf.time << kf.position << kf.rotation; | ||
} | ||
animSettings.setKeyframes( keyframes ); | ||
return animSettings; | ||
} | ||
|
||
void Qgs3DAnimationWidget::setDefaultAnimation() | ||
{ | ||
Qgs3DAnimationSettings animSettings; | ||
Qgs3DAnimationSettings::Keyframes kf; | ||
Qgs3DAnimationSettings::Keyframe f1, f2; | ||
f1.time = 0; | ||
f1.position = mCamera->transform()->translation(); | ||
f1.rotation = mCamera->transform()->rotation(); | ||
f2.time = 5; | ||
f2.position = f1.position + QVector3D( 0, 0, f1.position.z() / 2 ); | ||
f2.rotation = f1.rotation; | ||
kf << f1 << f2; | ||
animSettings.setKeyframes( kf ); | ||
|
||
setAnimation( animSettings ); | ||
} | ||
|
||
void Qgs3DAnimationWidget::onPlayPause() | ||
{ | ||
if ( mAnimationTimer->isActive() ) | ||
{ | ||
mAnimationTimer->stop(); | ||
cboKeyframe->setEnabled( true ); | ||
} | ||
else | ||
{ | ||
cboKeyframe->setCurrentIndex( 0 ); // unset active keyframe | ||
cboKeyframe->setEnabled( false ); | ||
mAnimationTimer->start(); | ||
} | ||
} | ||
|
||
void Qgs3DAnimationWidget::onAnimationTimer() | ||
{ | ||
float duration = sliderTime->maximum(); | ||
sliderTime->setValue( sliderTime->value() >= duration ? 0 : sliderTime->value() + 1 ); | ||
} | ||
|
||
void Qgs3DAnimationWidget::onSliderValueChanged() | ||
{ | ||
mAnimationController->setPosition( sliderTime->value() / 100. ); | ||
} | ||
|
||
void Qgs3DAnimationWidget::onCameraViewMatrixChanged() | ||
{ | ||
if ( cboKeyframe->currentIndex() <= 0 ) | ||
return; | ||
|
||
// update keyframe's camera position/rotation | ||
int i = cboKeyframe->currentIndex(); | ||
cboKeyframe->setItemData( i, mCamera->transform()->translation(), Qt::UserRole + 2 ); | ||
cboKeyframe->setItemData( i, mCamera->transform()->rotation(), Qt::UserRole + 3 ); | ||
|
||
initializeController( animation() ); | ||
} | ||
|
||
void Qgs3DAnimationWidget::onKeyframeChanged() | ||
{ | ||
if ( cboKeyframe->currentIndex() <= 0 ) | ||
return; | ||
|
||
// jump to the camera view of the keyframe | ||
float time = cboKeyframe->itemData( cboKeyframe->currentIndex(), Qt::UserRole + 1 ).toFloat(); | ||
sliderTime->setValue( time * 100 ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/*************************************************************************** | ||
qgs3danimationwidget.h | ||
-------------------------------------- | ||
Date : July 2018 | ||
Copyright : (C) 2018 by Martin Dobias | ||
Email : wonder dot sk at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGS3DANIMATIONWIDGET_H | ||
#define QGS3DANIMATIONWIDGET_H | ||
|
||
#include <QWidget> | ||
|
||
#include "ui_animation3dwidget.h" | ||
|
||
namespace Qt3DRender | ||
{ | ||
class QCamera; | ||
} | ||
namespace Qt3DAnimation | ||
{ | ||
class QAnimationController; | ||
} | ||
|
||
class Qgs3DAnimationSettings; | ||
|
||
class Qgs3DAnimationWidget : public QWidget, private Ui::Animation3DWidget | ||
{ | ||
Q_OBJECT | ||
public: | ||
explicit Qgs3DAnimationWidget( QWidget *parent = nullptr ); | ||
|
||
void setCamera( Qt3DRender::QCamera *camera ); | ||
|
||
void setAnimation( const Qgs3DAnimationSettings &animation ); | ||
Qgs3DAnimationSettings animation() const; | ||
|
||
void setDefaultAnimation(); | ||
|
||
signals: | ||
|
||
private slots: | ||
void onPlayPause(); | ||
void onAnimationTimer(); | ||
void onSliderValueChanged(); | ||
void onCameraViewMatrixChanged(); | ||
void onKeyframeChanged(); | ||
|
||
private: | ||
void initializeController( const Qgs3DAnimationSettings &animSettings ); | ||
|
||
private: | ||
QTimer *mAnimationTimer = nullptr; | ||
Qt3DAnimation::QAnimationController *mAnimationController = nullptr; | ||
Qt3DRender::QCamera *mCamera = nullptr; //!< Camera (not owned) | ||
}; | ||
|
||
#endif // QGS3DANIMATIONWIDGET_H |
Oops, something went wrong.