В начале этой главы, создавая с помощью мастера 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().