Класс Timing — это таймер с некоторыми дополнительными функциями. Он должен уметь получать системное время, иметь счетчик кадров, сохранять момент окончания последнего кадра и длительность этого кадра. Кроме того, он должен обслуживать сам себя, то есть содержать методы инициализации счетчиков, их обновления и очистки памяти. И еще — таймер должен быть единственным, поэтому в мы поместим конструкторы класса в закрытую область.
Вот, что получается в результате:
struct TimingData
{
unsigned frameNumber;
unsigned lastFrameTimestamp;
unsigned lastFrameDuration;
static TimingData& get();
static unsigned getTime();
static void update();
static void init();
static void deinit();
private:
// Создавать экземпляры этого класса нужно с помощью get().
TimingData() {}
TimingData(const TimingData &) {}
};
А вот как это реализовано
#include <sys/time.h> /* gettimeofday, timeval */
#include <cstdio> /* NULL */
#include "timing.h"
// Возвращает текущее время в мс,
// опирается на системную функцию gettimeofday().
unsigned systemTime()
{
struct timeval t;
gettimeofday(&t, NULL);
return (unsigned)(t.tv_sec * 1000 + t.tv_usec / 1000);
}
unsigned TimingData::getTime()
{
return systemTime();
}
// Глобальная переменная, хранящая данные о времени моделирования
static TimingData *timingData = NULL;
TimingData& TimingData::get()
{
return (TimingData&) *timingData;
}
// Обновляет данные о времени.
// Должна вызываться для каждого кадра
void TimingData::update()
{
if (!timingData) return;
// Увеличиваем счетчик кадров
timingData->frameNumber++;
// Обновлеям значения длительности последнего кадра и
// момента, когда он закончился (в мс)
unsigned thisTime = systemTime();
timingData->lastFrameDuration = thisTime -
timingData->lastFrameTimestamp;
timingData->lastFrameTimestamp = thisTime;
}
// Инициализация данных о времени.
// Должна вызываться перед запуском цикла моделирования
void TimingData::init()
{
// Создаем структуру, хранящую информацию о времени моделирования
if (!timingData) timingData = new TimingData();
// Инициализируем его поля
timingData->frameNumber = 0;
timingData->lastFrameTimestamp = systemTime();
timingData->lastFrameDuration = 0;
}
void TimingData::deinit()
{
delete timingData;
timingData = NULL;
}
Обратите внимание на системозависимую функцию systemTime()
. Здесь мы приводим *nix-овский вариант ее реализации, в книге Миллингтона показана реализация для Windows.
Можно было бы использовать для возвращения значения времени функцию: glutGet(GLUT_ELAPSED_TIME)
. Она, как и весь GLUT, не зависит от системы. Но не хотелось использовать функцию "оконной" библиотеки в этом далеком от окон классе — вдруг нам захочется потом сменить GLUT на что-то другое.
Комментарии
comments powered by Disqus