Класс 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