1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2013 Dennis Nienhüser <nienhueser@kde.org>
// Loosely based on MarblePhysics.cpp
//
/**
* Animated jump from a source point to a destination point, recording
* the result to a video.
*/
#include <marble/MarbleWidget.h>
#include <marble/GeoDataCoordinates.h>
#include <marble/GeoDataLineString.h>
#include <marble/RenderPlugin.h>
#include <marble/Quaternion.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <QTimeLine>
#include <qmath.h>
#include <QApplication>
#include <cstdio>
using namespace Marble;
using namespace cv;
namespace {
// Some stuff you might want to change
// The map theme in use
QString const mapTheme = "earth/mapquest-open-aerial/mapquest-open-aerial.dgml";
// Enabled plugins. Everything else will be disabled
QStringList const features = QStringList() << "stars" << "atmosphere";
// Camera starting point: Position and zoom level
GeoDataCoordinates const source( 8.40314, 49.01302, 0.0, GeoDataCoordinates::Degree);
double const sourceZoomLevel = 11;
// Camera destination point: Position and zoom level
GeoDataCoordinates const destination( -101.36631, 43.13718, 0.0, GeoDataCoordinates::Degree);
double const destinationZoomLevel = 14;
// Minimum zoom level (in the middle of the animation)
double const jumpZoomLevel = 5.5;
// Length of the video
QTimeLine timeLine( 20 * 1000 );
// Frames per second
int const fps = 30;
// Target video file name
std::string const videoFile = "marble-animated-zoom.avi";
// Video resolution
Size frameSize( 1280, 720 );
}
void interpolate( MarbleWidget* widget, qreal value )
{
GeoDataCoordinates coordinates;
qreal lon, lat;
Quaternion::slerp( source.quaternion(), destination.quaternion(), value ).getSpherical( lon, lat );
coordinates.setLongitude( lon );
coordinates.setLatitude( lat );
widget->centerOn( coordinates );
widget->setRadius( exp(jumpZoomLevel) + (value < 0.5 ? exp(sourceZoomLevel*(1.0-2*value)) : exp(destinationZoomLevel*(2*value-1.0))) );
}
void animatedFlight( MarbleWidget *mapWidget )
{
mapWidget->resize( frameSize.width, frameSize.height );
VideoWriter videoWriter( videoFile, CV_FOURCC('D','I','V','X'), fps, frameSize );
Mat buffer;
buffer.create(frameSize, CV_8UC3);
timeLine.setCurveShape( QTimeLine::EaseInOutCurve );
int const frameTime = qRound( 1000.0 / fps );
for ( int i=1; i<=timeLine.duration(); i+=frameTime ) {
printf("[%i%% done]\r", cvRound( (100.0*i)/timeLine.duration() ) );
fflush(stdout);
interpolate( mapWidget, timeLine.valueForTime( i ) );
QImage screenshot = QPixmap::grabWidget( mapWidget ).toImage().convertToFormat( QImage::Format_RGB888 );
Mat converter( frameSize, CV_8UC3 );
converter.data = screenshot.bits();
cvtColor( converter, buffer, CV_RGB2BGR );
videoWriter.write( buffer );
}
for ( int i=0; i<fps; ++i ) {
videoWriter.write( buffer ); // one second stand-still at end
}
printf("Wrote %s\n", videoFile.c_str());
}
int main(int argc, char** argv)
{
QApplication app(argc,argv);
MarbleWidget *mapWidget = new MarbleWidget;
mapWidget->setMapThemeId(mapTheme);
foreach( RenderPlugin* plugin, mapWidget->renderPlugins() ) {
if ( !features.contains( plugin->nameId() ) ) {
plugin->setEnabled( false );
}
}
animatedFlight( mapWidget );
return 0;
}
|