You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

151 lines
4.3 KiB

#ifndef Magnum_Timeline_h
#define Magnum_Timeline_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include <chrono>
#include "Magnum.h"
#include "magnumVisibility.h"
/** @file
* @brief Class Magnum::Timeline
*/
namespace Magnum {
/**
@brief %Timeline
Keeps track of time delta between frames and allows FPS limiting. Can be used
as source for animation speed computations.
@section Timeline-usage Basic usage
Construct the timeline on initialization so the instance is available for
whole lifetime of the application. Call start() before first draw event is
performed, after everything is properly initialized.
@note When timeline is started, it immediately starts measuring frame time.
Be prepared that time of first frame will be much longer than time of
following frames. It mainly depends on where you called start() in your
initialization routine, but can be also affected by driver- and
GPU-specific lazy texture binding, shader recompilations etc.
In your draw event implementation don't forget to call nextFrame() after
buffer swap. You can use previousFrameDuration() to compute animation speed.
Example usage (in e.g. @ref Platform::GlutApplication "GlutApplication"
subclass):
@code
MyApplication::MyApplication(...): Platform::GlutApplication(...) {
// Initialization ...
timeline.setMinimalFrameTime(1/120.0f); // 120 FPS at max
timeline.start();
}
void MyApplication::drawEvent() {
// Distance of object travelling at speed of 15 units per second
GLfloat distance = 15.0f*timeline.previousFrameDuration();
// Move object, draw ...
swapBuffers();
redraw();
timeline.nextFrame();
}
@endcode
*/
class MAGNUM_EXPORT Timeline {
public:
/**
* @brief Constructor
*
* Creates stopped timeline.
* @see start()
*/
inline constexpr explicit Timeline(): _minimalFrameTime(0), _previousFrameDuration(0), running(false) {}
/** @brief Minimal frame time (in seconds) */
inline constexpr GLfloat minimalFrameTime() const {
return _minimalFrameTime;
}
/**
* @brief Set minimal frame time
*
* Default value is 0.
* @see nextFrame()
*/
inline void setMinimalFrameTime(GLfloat seconds) {
_minimalFrameTime = seconds;
}
/**
* @brief Start timeline
*
* Sets previous frame time and duration to `0`.
* @see stop(), previousFrameDuration()
*/
void start();
/**
* @brief Stop timeline
*
* @see start(), nextFrame()
*/
void stop();
/**
* @brief Advance to next frame
*
* If current frame time is smaller than minimal frame time, pauses
* the execution for remaining time.
* @note This function does nothing if the timeline is stopped.
* @see setMinimalFrameTime(), stop()
*/
void nextFrame();
/**
* @brief Time at previous frame (in seconds)
*
* Returns time elapsed since start() was called. If the timeline is
* stopped, the function returns `0.0f`.
*/
GLfloat previousFrameTime() const;
/**
* @brief Duration of previous frame (in seconds)
*
* If the timeline is stopped, the function returns `0.0f`.
*/
inline constexpr GLfloat previousFrameDuration() const {
return _previousFrameDuration;
}
private:
std::chrono::high_resolution_clock::time_point _startTime;
std::chrono::high_resolution_clock::time_point _previousFrameTime;
GLfloat _minimalFrameTime;
GLfloat _previousFrameDuration;
bool running;
};
}
#endif