Функция UpdateCube() является функцией обратного вызова, которая выполняет анимацию вершин в приложении Cube. Код функции UpdateCube() выглядит так:
void CubeWin::UpdateCube(LPDIRECT3DRMFRAME frame, void* p, D3DVALUE) { CallbackData* data = (CallbackData*)p; static const D3DVALUE lim = D3DVALUE(5); static D3DVALUE control; static D3DVALUE inc = D3DVALUE(.25); static D3DRMVERTEX vert[24]; data->mesh->GetVertices(data->group, 0, 24, vert); vert[0].position.x += inc; vert[0].position.y += inc; vert[0].position.z += inc; vert[6].position.x += inc; vert[6].position.y += inc; vert[6].position.z += inc; vert[8].position.x += inc; vert[8].position.y += inc; vert[8].position.z += inc; vert[14].position.x += inc; vert[14].position.y += inc; vert[14].position.z += inc; vert[18].position.x += inc; vert[18].position.y += inc; vert[18].position.z += inc; vert[20].position.x += inc; vert[20].position.y += inc; vert[20].position.z += inc; data->mesh->SetVertices(data->group, 0, 24, vert); control += inc; if (control > lim || control < -lim) inc = -inc; static UINT delay; if (++delay < 20) return; delay = 0; LPDIRECT3DRMFRAME scene; frame->GetScene(&scene); D3DVECTOR spinvect; D3DRMVectorRandom(&spinvect); D3DVALUE spin = D3DDivide(rand() % 50 + 1, 400); frame->SetRotation(scene, spinvect.x, spinvect.y, spinvect.z, spin); }Сначала функция подготавливает указатель на структуру CallbackData:
CallbackData* data = (CallbackData*)p;Параметр p — это указатель на статическую структуру cbdata объявленную в функции CreateScene(). В то же время, переменная p объявлена в объявлении функции как указатель на void. По этой причине мы для доступа к необходимым данным будем использовать в функции обратного вызова локальный указатель data, присвоив ему приведенное к требуемому типу значение указателя p.
Затем следует объявление четырех статических переменных:
static const D3DVALUE lim = D3DVALUE(5); static D3DVALUE control; static D3DVALUE inc = D3DVALUE(.25); static D3DRMVERTEX vert[24];Переменная lim является константой, ограничивающей перемещение вершин. Переменная control используется для определения текущего местоположения анимируемых вершин. Переменная inc хранит значение на которое будет изменяться значение переменной control. И, наконец, переменная vert является массивом структур D3DRMVERTEX. Мы будем использовать ее при получении, изменении и присваивании данных вершин сетки.
Теперь для получения текущих данных вершин сетки используется функция GetVertices() интерфейса Direct3DRMMesh:
data->mesh->GetVertices(data->group, 0, 24, vert);Список аргументов функции GetVertices() аналогичен списку аргументов функции SetVertices(). Обратите внимание, что и указатель на сетку и идентификатор группы граней сетки передаются через указатель data. После вызова функции GetVertices() массив vert будет заполнен текущими параметрами вершин сетки.
Настало время изменить координаты вершин сетки:
vert[0].position.x += inc; vert[0].position.y += inc; vert[0].position.z += inc; vert[6].position.x += inc; vert[6].position.y += inc; vert[6].position.z += inc; vert[8].position.x += inc; vert[8].position.y += inc; vert[8].position.z += inc; vert[14].position.x += inc; vert[14].position.y += inc; vert[14].position.z += inc; vert[18].position.x += inc; vert[18].position.y += inc; vert[18].position.z += inc; vert[20].position.x += inc; vert[20].position.y += inc; vert[20].position.z += inc;Каждая из координат изменяется на значение, хранящееся в переменной inc. Порядок изменения координат вершин не имеет значения, поскольку все эти изменения не вступят в силу до вызова функции SetVertices():
data->mesh->SetVertices(data->group, 0, 24, vert);Функция SetVertices() изменяет сетку, присваивая ее вершинам измененные параметры.
Затем изменяется значение переменной control:
control += inc; if (control > lim || control < -lim) inc = -inc;В этом коде используется переменная lim чтобы изменять значение переменной inc если значение переменной control достигло заданного предела.
Оставшаяся часть функции UpdateCube() осуществляет периодическое изменение атрибутов вращения фрейма:
static UINT delay; if (++delay < 20) return; delay = 0; LPDIRECT3DRMFRAME scene; frame->GetScene(&scene); D3DVECTOR spinvect; D3DRMVectorRandom(&spinvect); D3DVALUE spin = D3DDivide(rand() % 50 + 1, 400); frame->SetRotation(scene, spinvect.x, spinvect.y, spinvect.z, spin);После каждых 20 обновлений экрана этот код вычисляет новые вектор и скорость вращения. Затем новые значения устанавливаются функцией SetRotation() интерфейса Direct3DRMFrame.