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

         

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


В отличие от приложения Wraps, вся функциональность приложения Decal предоставляется функцией CreateScene(). Эта функция создает и настраивает декалы, источник света и порт просмотра. Поскольку анимация в приложении Decal реализуется с помощью атрибутов движения, никакие функции обратного вызова не требуются. Код функции CreateScene() представлен в листинге 5.3.

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

BOOL DecalWin::CreateScene() { //------ ДЕКАЛЫ -------- LPDIRECT3DRMTEXTURE texture1, texture2; HRSRC texture_id; texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE1), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture1); texture1->SetDecalOrigin(64, 64); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE2), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture2); texture2->SetDecalOrigin(64, 64); //-------- ФРЕЙМЫ -------- LPDIRECT3DRMFRAME dummyframe1; d3drm->CreateFrame(scene, &dummyframe1); dummyframe1->SetRotation(scene, D3DVALUE(0), D3DVALUE(1), D3DVALUE(0), D3DVALUE(0.05)); LPDIRECT3DRMFRAME dummyframe2; d3drm->CreateFrame(scene, &dummyframe2); dummyframe2->SetRotation(scene, D3DVALUE(1), D3DVALUE(0), D3DVALUE(0), D3DVALUE(-0.05)); LPDIRECT3DRMFRAME orbitframe1; d3drm->CreateFrame(dummyframe1, &orbitframe1); orbitframe1->SetPosition(dummyframe1, D3DVALUE(2), D3DVALUE(0), D3DVALUE(0)); orbitframe1->AddVisual(texture1); LPDIRECT3DRMFRAME orbitframe2; d3drm->CreateFrame(dummyframe2, &orbitframe2); orbitframe2->SetPosition(dummyframe2, D3DVALUE(0), D3DVALUE(-2), D3DVALUE(0)); orbitframe2->AddVisual(texture2); texture1->Release(); texture1 = 0; texture2->Release(); texture2 = 0; dummyframe1->Release(); dummyframe1 = 0; dummyframe2->Release(); dummyframe2 = 0; orbitframe1->Release(); orbitframe1 = 0; orbitframe2->Release(); orbitframe2 = 0; //--------- СВЕТ -------- LPDIRECT3DRMLIGHT light; d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(1.0),D3DVALUE(1.0), D3DVALUE(1.0), &light); scene->AddLight(light); light->Release(); light = 0;

//--------- ПОРТ ПРОСМОТРА -------- d3drm->CreateFrame(scene, &camera); camera->SetPosition(scene, D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(-6.0)); d3drm->CreateViewport(device, camera, 0, 0, device->GetWidth(), device->GetHeight(), &viewport); return TRUE; }

Функция CreateScene() выполняет следующие четыре действия:

  1. Создание двух текстур, которые будут использоваться в качестве декалов.
  2. Создание фреймов для двух текстур.
  3. Создание источника света.
  4. Создание порта просмотра.

Первый этап — загрузка двух текстур. Как и в большинстве демонстрационных приложений, текстуры хранятся в ресурсах в исполняемом файле приложения:

LPDIRECT3DRMTEXTURE texture1, texture2; HRSRC texture_id; texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE1), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture1); texture1->SetDecalOrigin(64, 64); texture_id = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXTURE2), "TEXTURE"); d3drm->LoadTextureFromResource(texture_id, &texture2); texture2->SetDecalOrigin(64, 64);

После загрузки каждой из текстур вызывается функция SetDecalOrigin(). Она применяется для указания точки внутри текстуры, которая будет использоваться как начало координат. По умолчанию началом координат текстуры считается верхний левый угол (x = 0, y = 0). Это означает, что при присоединении текстуры к фрейму с заданным местоположением фрейма будет совпадать верхний левый угол текстуры. В приложении Decal используются две текстуры размером 128 на 128 точек. Используя в качестве аргументов функции SetDecalOrigin() число 64, мы помещаем начало координат текстуры в ее центр.

Затем в приложении создаются фреймы (как пустые, так и фреймы для текстур):

LPDIRECT3DRMFRAME dummyframe1; d3drm->CreateFrame(scene, &dummyframe1); dummyframe1->SetRotation(scene, D3DVALUE(0), D3DVALUE(1), D3DVALUE(0), D3DVALUE(0.05)); LPDIRECT3DRMFRAME dummyframe2; d3drm->CreateFrame(scene, &dummyframe2); dummyframe2->SetRotation(scene, D3DVALUE(1), D3DVALUE(0), D3DVALUE(0), D3DVALUE(-0.05)); LPDIRECT3DRMFRAME orbitframe1; d3drm->CreateFrame(dummyframe1, &orbitframe1); orbitframe1->SetPosition(dummyframe1, D3DVALUE(2), D3DVALUE(0), D3DVALUE(0)); orbitframe1->AddVisual(texture1); LPDIRECT3DRMFRAME orbitframe2; d3drm->CreateFrame(dummyframe2, &orbitframe2); orbitframe2->SetPosition(dummyframe2, D3DVALUE(0), D3DVALUE(-2), D3DVALUE(0)); orbitframe2->AddVisual(texture2);

Для каждого пустого фрейма функцией SetRotation() задаются параметры вращения, но сами фреймы не перемещаются из своего начального местоположения (начала координат). Перемещающиеся по орбите фреймы смещаются на заданное расстояние от пустых фреймов с помощью функции SetPosition(). Обратите внимание, что пустые фреймы являются потомками фрейма scene (корня иерархии фреймов), а перемещающиеся по орбитам фреймы являются потомками своих пустых фреймов. Созданные ранее текстуры присоединяются к помещенным на орбиту фреймам функцией AddVisual(). Тот факт, что текстура присоединяется непосредственно к фрейму и делает ее декалом.

На третьем и четвертом этапе для приложения Decal создаются источник света и порт просмотра. Используемый для этого код аналогичен тому, который мы видели в приложении Jade. Далее в этой книге мы более подробно изучим источники света и порты просмотра.




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