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

         

Функция ShowRoom::CreateScene()


Во время конструирования сцены приложения ShowRoom, функция CreateScene() загружает 15 текстур, на каждой из которых изображена машина, повернутая под другим углом. Потом создаются сетка и плоское наложение текстуры, и первая текстура накладывается на сетку. Функция обратного вызова используется для последовательного наложения на сетку остальных текстур. Код функции CreateScene() приложения ShowRoom приведен в листинге5.7.

Листинг 5.7. Функция ShowRoomWin::CreateScene()

BOOL ShowRoomWin::CreateScene() { //-------- ТЕКСТУРЫ -------- HRSRC texture_id; int t = 0; texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE01), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE02), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE03), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE04), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE05), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE06), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE07), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE08), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE09), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE10), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE11), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE12), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE13), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE14), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE15), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture[t++]); // ------- КОНСТРУКТОР СЕТОК -------- D3DRMLOADRESOURCE resinfo; resinfo.hModule = NULL; resinfo.lpName = MAKEINTRESOURCE( IDR_BOXMESH ); resinfo.lpType = "MESH"; LPDIRECT3DRMMESHBUILDER meshbuilder; d3drm->CreateMeshBuilder(&meshbuilder); meshbuilder->Load(&resinfo, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL); meshbuilder->Scale(D3DVALUE(1), D3DVALUE(1), D3DVALUE(.1)); ScaleMesh(meshbuilder, D3DVALUE(20)); meshbuilder->SetPerspective(TRUE); meshbuilder->SetQuality(D3DRMRENDER_FLAT); meshbuilder->SetTexture(texture[0]); //--------- НАЛОЖЕНИЕ -------- D3DRMBOX box; meshbuilder->GetBox(&box); D3DVALUE width = box.max.x - box.min.x; D3DVALUE height = box.max.y - box.min.y; LPDIRECT3DRMWRAP wrap; d3drm->CreateWrap(D3DRMWRAP_FLAT, NULL, D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(0.0), // начало координат наложения D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(1.0), // ось z D3DVALUE(0.0), D3DVALUE(1.0), D3DVALUE(0.0), // ось y D3DVALUE(0.5), D3DVALUE(0.5), // начало координат D3DDivide(1,width),D3DDivide(1,height), // масштаб &wrap); wrap->Apply(meshbuilder); wrap->Release(); wrap = 0; //------- СЕТКА ------ meshbuilder->CreateMesh(&mesh); meshbuilder->Release(); meshbuilder = 0; //------- ФРЕЙМ -------- LPDIRECT3DRMFRAME meshframe; d3drm->CreateFrame(scene, &meshframe); meshframe->AddVisual(mesh); meshframe->SetRotation(scene, D3DVALUE(0), D3DVALUE(1), D3DVALUE(0), D3DVALUE(0.05)); meshframe->AddMoveCallback(UpdateTexture, NULL); meshframe->Release(); meshframe = 0; //-------- СВЕТ -------- LPDIRECT3DRMLIGHT dlight, alight; d3drm->CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, D3DVALUE(1.0), D3DVALUE(1.0), D3DVALUE(1.0), &dlight); d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(1.0), D3DVALUE(1.0), D3DVALUE(1.0), &alight); LPDIRECT3DRMFRAME lightframe; d3drm->CreateFrame(scene, &lightframe); lightframe->SetOrientation(scene, D3DVALUE(0), D3DVALUE(-1), D3DVALUE(1), D3DVALUE(0), D3DVALUE(1), D3DVALUE(0)); lightframe->AddLight(dlight); lightframe->AddLight(alight); lightframe->Release(); lightframe = 0; dlight->Release(); dlight = 0; alight->Release(); alight = 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() выполняет следующие действия:

  1. Создание пятнадцати текстур.
  2. Создание и конфигурирование конструктора сеток.
  3. Создание и применение плоского наложения текстуры.
  4. Создание интерфейса Direct3DRMMesh.
  5. Создание фрейма для сетки.
  6. Создание источника света.
  7. Создание порта просмотра.

Первая часть функции CreateScene() весьма прямолинейна (и скучна). Создаются и загружаются 15 текстур, и указатель на каждую из текстур сохраняется в массиве texture.

Затем с помощью интерфейса Direct3DRMMeshBuilder загружается сетка куба. Для масштабирования куба применяется функция Scale():

D3DRMLOADRESOURCE resinfo; resinfo.hModule = NULL; resinfo.lpName = MAKEINTRESOURCE( IDR_BOXMESH ); resinfo.lpType = "MESH"; LPDIRECT3DRMMESHBUILDER meshbuilder; d3drm->CreateMeshBuilder(&meshbuilder); meshbuilder->Load(&resinfo, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL); meshbuilder->Scale(D3DVALUE(1), D3DVALUE(1), D3DVALUE(.1)); ScaleMesh(meshbuilder, D3DVALUE(20)); meshbuilder->SetPerspective(TRUE); meshbuilder->SetQuality(D3DRMRENDER_FLAT); meshbuilder->SetTexture(texture[0]);

Это делается потому, что мы хотим для наложения текстур использовать почти плоскую прямоугольную сетку. Вместо того, чтобы создавать прямоугольную сетку, мы используем куб и масштабируем его по оси Z до одной десятой его исходного размера. Потом выполняется настройка параметров новой сетки для включения перспективной коррекции и использования при визуализации метода равномерной закраски. Первая текстура из массива texture связывается с новой сеткой.

На шаге 3 создается и применяется наложение текстуры:

D3DRMBOX box; meshbuilder->GetBox(&box); D3DVALUE width = box.max.x - box.min.x; D3DVALUE height = box.max.y - box.min.y; LPDIRECT3DRMWRAP wrap; d3drm->CreateWrap(D3DRMWRAP_FLAT, NULL, D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(0.0), // начало координат наложения D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(1.0), // ось z D3DVALUE(0.0), D3DVALUE(1.0), D3DVALUE(0.0), // ось y D3DVALUE(0.5), D3DVALUE(0.5), // начало координат D3DDivide(1,width),D3DDivide(1,height), // масштаб &wrap); wrap->Apply(meshbuilder); wrap->Release(); wrap = 0;

Плоское наложение текстуры создается таким образом, чтобы размеры текстуры в точности соответствовали сетке. Наложение текстуры применяется к конструктору сеток с помощью функции Apply().

Теперь загруженный ранее конструктор сеток используется для инициализации указателя на интерфейс Direct3DRMMesh:

meshbuilder->CreateMesh(&mesh); meshbuilder->Release(); meshbuilder = 0;

Новая сетка создается с теми же параметрами, что были у конструктора сеток.

Затем создается фрейм и сетка присоединяется к нему:

LPDIRECT3DRMFRAME meshframe; d3drm->CreateFrame(scene, &meshframe); meshframe->AddVisual(mesh); meshframe->SetRotation(scene, D3DVALUE(0), D3DVALUE(1), D3DVALUE(0), D3DVALUE(0.05)); meshframe->AddMoveCallback(UpdateTexture, NULL); meshframe->Release(); meshframe = 0;

Новому фрейму назначаются такие атрибуты вращения, чтобы он поворачивался вокруг оси Y. Кроме того, для фрейма устанавливается функция обратного вызова UpdateTexture().



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