Код функции CreateScene() из приложения Cube2 приведен в листинге8.2.
Листинг 8.2. Функция Cube2Win::CreateScene() |
BOOL Cube2Win::CreateScene() { //---------- СЕТКА -------- d3drm->CreateMesh(&mesh); mesh->AddGroup(12, 3, 4, vertorder, &group1); mesh->AddGroup(12, 3, 4, vertorder, &group2); mesh->SetVertices(group1, 0, 12, vertexlist); mesh->SetVertices(group2, 0, 12, vertexlist + 12); mesh->Translate(D3DVALUE(-0.5), D3DVALUE(-0.5), D3DVALUE(-0.5)); mesh->Scale(D3DVALUE(15), D3DVALUE(15), D3DVALUE(15)); //--------- ТЕКСТУРА ---------- HRSRC texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_WIN95TEXTURE), "TEXTURE"); LPDIRECT3DRMTEXTURE texture; d3drm->LoadTextureFromResource(texture_id, &texture); mesh->SetGroupTexture(group1, texture); mesh->SetGroupMapping(group1, D3DRMMAP_PERSPCORRECT); mesh->SetGroupTexture(group2, texture); mesh->SetGroupMapping(group2, D3DRMMAP_PERSPCORRECT); texture->Release(); texture = 0; //---------- ФРЕЙМ ---------- LPDIRECT3DRMFRAME meshframe; d3drm->CreateFrame(scene, &meshframe); meshframe->AddVisual(mesh); meshframe->SetRotation(scene, D3DVALUE(0), D3DVALUE(1), D3DVALUE(0), D3DVALUE(-.05)); static CallbackData cbdata; cbdata.mesh = mesh; cbdata.group1 = group1; cbdata.group2 = group2; meshframe->AddMoveCallback(UpdateCube, &cbdata); meshframe->AddMoveCallback(UpdateColors, &cbdata); meshframe->Release(); meshframe = 0; // -------- СВЕТ -------- LPDIRECT3DRMLIGHT dlight, alight; d3drm->CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, D3DVALUE(1.00), D3DVALUE(1.00), D3DVALUE(1.00), &dlight); d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(0.50), D3DVALUE(0.50), D3DVALUE(0.50), &alight); LPDIRECT3DRMFRAME lightframe; d3drm->CreateFrame(scene, &lightframe); lightframe->SetOrientation(scene, D3DVALUE(0), D3DVALUE(-1), D3DVALUE(5), D3DVALUE(0), D3DVALUE(1), D3DVALUE(0)); lightframe->AddLight(dlight); lightframe->AddLight(alight); dlight->Release(); dlight = 0; alight->Release(); alight = 0; lightframe->Release(); lightframe = 0; //------ КАМЕРА ---------- d3drm->CreateFrame(scene, &camera); camera->SetPosition(scene, D3DVALUE(0), D3DVALUE(0), D3DVALUE(-50)); d3drm->CreateViewport(device, camera, 0, 0, device->GetWidth(), device->GetHeight(), &viewport); return TRUE; } |
Функция CreateScene() выполняет следующие действия:
На первом этапе выполняется создание сетки:
d3drm->CreateMesh(&mesh); mesh->AddGroup(12, 3, 4, vertorder, &group1); mesh->AddGroup(12, 3, 4, vertorder, &group2); mesh->SetVertices(group1, 0, 12, vertexlist); mesh->SetVertices(group2, 0, 12, vertexlist + 12); mesh->Translate(D3DVALUE(-0.5), D3DVALUE(-0.5), D3DVALUE(-0.5)); mesh->Scale(D3DVALUE(15), D3DVALUE(15), D3DVALUE(15));Сначала для инициализации указателя mesh вызывается функция CreateMesh() интерфейса Direct3DRM. Затем к пустой сетке добавляются две группы граней, каждая из которых создается функцией AddGroup(). Каждая группа включает 12 вершин: 3 грани по 4 вершины в каждой. В качестве третьего аргумента функции AddGroup() используется массив vertorder. В приложении Cube массив vertorder содержал 24 элемента; в приложении Cube2 в этом массиве только 12 элементов:
unsigned vertorder[] = { 0,1,2,3,4,5,6,7,8,9,10,11 };Последний аргумент функции AddGroup() является адресом идентификатора групп граней сетки. Функция AddGroup() назначает каждой группе граней уникальное значение идентификатора.
Теперь, чтобы присвоить значения вершинам каждой группы, воспользуемся функцией SetVertices(). Первым параметром этой функции является идентификатор группы вершин. Второй аргумент — это индекс первой изменяемой вершины. Третий аргумент — число вершин, которым будут присвоены новые значения. Последний, четвертый аргумент является массивом структур D3DRMVERTEX. Обратите внимание, что для инициализации двух групп граней используется один и тот же массив структур. Во втором вызове функции SetVertices() указано смещение, приводящее к тому, что для инициализации второй группы граней используется вторая половина массива.
Затем выполняется вызов функции Translate() интерфейса Direct3DRMMesh и функции Scale(). В отличие от функций AddGroup() и SetVertices(), функции Translate() и Scale() модифицируют все входящие в сетку группы. Вызов этих функций ничем не отличается от использованного в приложении Cube.
На втором этапе выполняется создание текстуры и ее наложение на обе группы граней сетки:
HRSRC texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_WIN95TEXTURE), "TEXTURE"); LPDIRECT3DRMTEXTURE texture; d3drm->LoadTextureFromResource(texture_id, &texture); mesh->SetGroupTexture(group1, texture); mesh->SetGroupMapping(group1, D3DRMMAP_PERSPCORRECT); mesh->SetGroupTexture(group2, texture); mesh->SetGroupMapping(group2, D3DRMMAP_PERSPCORRECT); texture->Release(); texture = 0;На третьем этапе создается фрейм для сетки и устанавливаются две функции обратного вызова:
LPDIRECT3DRMFRAME meshframe; d3drm->CreateFrame(scene, &meshframe); meshframe->AddVisual(mesh); meshframe->SetRotation(scene, D3DVALUE(0), D3DVALUE(1), D3DVALUE(0), D3DVALUE(-.05)); static CallbackData cbdata; cbdata.mesh = mesh; cbdata.group1 = group1; cbdata.group2 = group2; meshframe->AddMoveCallback(UpdateCube, &cbdata); meshframe->AddMoveCallback(UpdateColors, &cbdata); meshframe->Release(); meshframe = 0;Фрейм создается функцией CreateFrame() интерфейса Direct3DRM и используется для размещения сетки. После этого фрейму назначаются атрибуты вращения.
Затем инициализируется экземпляр статической структуры CallbackData. Структура модифицирована таким образом, чтобы в ней можно было хранить идентификаторы обеих групп граней сетки.
Функция AddMoveCallback() интерфейса Direct3DRMFrame используется для установки двух функций обратного вызова: UpdateCube() и UpdateColors(). Каждая функция обратного вызова будет получать при вызове указатель на объявленную ранее статическую структуру данных. Функция UpdateCube() выполняет анимацию вершин для обоих групп граней сетки. Функция UpdateColors() выполняет анимацию цвета второй группы граней.
На двух заключительных этапах выполняется создание двух источников света и порта просмотра. В этой главе мы не будем обсуждать данные действия.