Программирование графики с использованием Direct3D

       

Использование функций обратного вызова


В начале этой главы, создавая с помощью мастера Direct3D AppWizard приложение Sample, мы указали, что хотим использовать анимированный зональный источник света. Мастер AppWizard добавил в проект код, изменяющий ориентацию источника света во время выполнения программы.

Это изменение выполняет функция обратного вызова. Функции обратного вызова — это функции, которые Direct3D вызывает каждый раз, когда собирается выполнить системное обновление. Такие функции могут применяться для изменения параметров во время выполнения программы.

Когда в функции CreateScene() мы создавали зональный источник света, мы установили для него функцию обратного вызова с именем MoveLight(). Установка функции обратного вызова выглядит следующим образом:

slightframe->AddMoveCallback(MoveLight, NULL);

Функция AddMoveCallback() — это функция интерфейса Direct3DRMFrame. Первый ее аргумент — это указатель на функцию, которая будет вызываться при каждом обновлении. Второй параметр представляет собой указатель на данные, которые будут передаваться функции обратного вызова. Эти дополнительные данные являются необязательными, поэтому мы передаем NULL.

Функция MoveLight() изменяет ориентацию зонального источника света и выглядит следующим образом:

void SampleWin::MoveLight(LPDIRECT3DRMFRAME lightframe, void*, D3DVALUE) { // перемещение прожектора над сеткой static const D3DVALUE lim = D3DVALUE(0.3); static D3DVALUE xi = D3DVALUE(0.01); static D3DVALUE yi = D3DVALUE(0.005); static D3DVALUE x, y; if (x < -LIM || x > lim) xi = -xi; if (y < -LIM || y > lim) yi = -yi; x += xi; y += yi; lightframe->SetOrientation(NULL, x, y-1, D3DVALUE(1), D3DVALUE(0), D3DVALUE(1), D3DVALUE(0)); }

Для вычисления новой ориентации источника света в функции используется простой алгоритм «подпрыгивающего мяча». Перемещение источника света ограничивается константой lim и изменяется на значения xi и yi. После вычисления новой ориентации, она назначается фрейму с помощью функции SetOrientation().


Функции обратного вызова всегда объявляются статическими, как показано ниже:

class SampleWin : public RMWin { // ... private: static void MoveLight(LPDIRECT3DRMFRAME frame, void* arg, D3DVALUE delta); // ... };

Это требование, объясняется тем, что обычные функции-члены класса требуют неявного указателя на класс. Объявление функции статической снимает это требование, но означает, что функции обратного вызова не могут обращаться к функциям-членам класса. По этой причине функция AddMoveCallback() предоставляет способ передачи дополнительных данных в функцию обратного вызова.

Функции обратного вызова, устанавливаемые с помощью AddMoveCallback() получают три параметра. Первый — это указатель на интерфейс фрейма для которого назначена данная функция обратного вызова. Второй параметр — это указатель на необязательные дополнительные данные. Третий параметр — это значение, полученное функцией Tick(). Помните, что функция Tick() может применяться для замедления и ускорения анимации в программе. Если в качестве параметра функции Tick() вы всегда используете 1.0, то можете спокойно игнорировать третий параметр.


Содержание раздела