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

       

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


Функция CreateScene() приложения Spotlight отвечает за создание сеток и прожектора, а также устанавливает функцию обратного вызова, использующуюся для анимации прожектора. Код функции SpotlightWin::CreateScene() представлен в листинге6.5.

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

BOOL SpotlightWin::CreateScene() { //----- СЕТКИ -------- D3DRMLOADRESOURCE resinfo; resinfo.hModule = NULL; resinfo.lpName = MAKEINTRESOURCE(IDR_SPHEREMESH); resinfo.lpType = "MESH"; LPDIRECT3DRMMESHBUILDER builder; d3drm->CreateMeshBuilder(&builder); builder->Load(&resinfo, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL); builder->SetColorRGB(D3DVALUE(1.0), D3DVALUE(0.0), D3DVALUE(0.0)); builder->CreateMesh(&mesh1); builder->SetColorRGB(D3DVALUE(0.0), D3DVALUE(1.0), D3DVALUE(0.0)); builder->CreateMesh(&mesh2); builder->SetColorRGB(D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(1.0)); builder->CreateMesh(&mesh3); builder->Release(); builder = 0;

//----- ФРЕЙМЫ ДЛЯ СЕТОК -------- LPDIRECT3DRMFRAME frame1; d3drm->CreateFrame(scene, &frame1); frame1->SetPosition(scene, D3DVALUE(-2), D3DVALUE(0), D3DVALUE(0)); frame1->AddVisual(mesh1); frame1->Release(); frame1 = 0;

LPDIRECT3DRMFRAME frame2; d3drm->CreateFrame(scene, &frame2); frame2->SetPosition(scene, D3DVALUE(2), D3DVALUE(0), D3DVALUE(0)); frame2->AddVisual(mesh2); frame2->Release(); frame2 = 0;

LPDIRECT3DRMFRAME frame3; d3drm->CreateFrame(scene, &frame3); frame3->SetPosition(scene, D3DVALUE(0), D3DVALUE(0), D3DVALUE(2)); frame3->AddVisual(mesh3); frame3->Release(); frame3 = 0;

//------- ПРОЖЕКТОР ------ d3drm->CreateLightRGB(D3DRMLIGHT_SPOT, D3DVALUE(0.8), D3DVALUE(0.8), D3DVALUE(0.8), &spotlight); OnBeamNormal();

//------ ФРЕЙМ ПРОЖЕКТОРА -------- LPDIRECT3DRMFRAME lightframe; d3drm->CreateFrame(scene, &lightframe); lightframe->SetPosition(scene, D3DVALUE(0), D3DVALUE(10), D3DVALUE(-10)); lightframe->SetOrientation(scene, D3DVALUE(0), D3DVALUE(-1), D3DVALUE(1), D3DVALUE(0), D3DVALUE(1), D3DVALUE(0)); lightframe->AddLight(spotlight); lightframe->AddMoveCallback(MoveLight, NULL); lightframe->Release(); lightframe = 0;

//------ КАМЕРА ------ d3drm->CreateFrame(scene, &camera); camera->SetPosition(scene, D3DVALUE(0), D3DVALUE(6), D3DVALUE(-6)); camera->SetOrientation(scene, D3DVALUE(0), D3DVALUE(-1), D3DVALUE(1.1), D3DVALUE(0), D3DVALUE(1), D3DVALUE(0)); d3drm->CreateViewport(device, camera, 0, 0, device->GetWidth(), device->GetHeight(), &viewport); return TRUE; }

<
/p> Функция CreateScene() выполняет следующие действия:

  • Использует интерфейс Direct3DRMMeshBuilder для загрузки сферической сетки и создает три указателя на интерфейс Direct3DRMMesh.




  • Создает и размещает на сцене фрейм для каждой из трех сеток.


  • Создает и настраивает прожектор.


  • Создает фрейм для прожектора.


  • Создает и настраивает порт просмотра.


  • Давайте взглянем на код, реализующий первый этап:

    D3DRMLOADRESOURCE resinfo; resinfo.hModule = NULL; resinfo.lpName = MAKEINTRESOURCE(IDR_SPHEREMESH); resinfo.lpType = "MESH"; LPDIRECT3DRMMESHBUILDER builder; d3drm->CreateMeshBuilder(&builder); builder->Load(&resinfo, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL); builder->SetColorRGB(D3DVALUE(1.0), D3DVALUE(0.0), D3DVALUE(0.0)); builder->CreateMesh(&mesh1); builder->SetColorRGB(D3DVALUE(0.0), D3DVALUE(1.0), D3DVALUE(0.0)); builder->CreateMesh(&mesh2); builder->SetColorRGB(D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(1.0)); builder->CreateMesh(&mesh3); builder->Release(); builder = 0;

    В самом начале выполняется объявление и инициализация экземпляра структуры D3DRMLOADRESOURCE. Структура resinfo идентифицирует сферическую сетку, которую мы будем использовать.

    Далее объявляется указатель на интерфейс Direct3DRMMeshBuilder с именем builder. Для инициализации этого указателя вызывается функция CreateMeshBuilder() интерфейса Direct3DRM. Функция Load() применяется для загрузки сетки. Адрес подготовленной ранее структуры resinfo передается функции Load() в ее первом аргументе.

    Затем инициализируются три указателя на интерфейс Direct3DRMMesh. Каждый из них инициализируется с помощью функции CreateMesh() интерфейса Direct3DRMMeshBuilder. После каждого вызова функции CreateMesh() конструктору сеток назначается новый цвет. В результате будут созданы три сетки различных цветов, каждая из которых представлена интерфейсом Direct3DRMMesh. Сразу после создания этих трех сеток указатель builder освобождается.

    На втором этапе работы функции CreateScene() выполняется создание и размещение трех фреймов, по одному для каждой из сеток:



    LPDIRECT3DRMFRAME frame1; d3drm->CreateFrame(scene, &frame1); frame1->SetPosition(scene, D3DVALUE(-2), D3DVALUE(0), D3DVALUE(0)); frame1->AddVisual(mesh1); frame1->Release(); frame1 = 0;

    LPDIRECT3DRMFRAME frame2; d3drm->CreateFrame(scene, &frame2); frame2->SetPosition(scene, D3DVALUE(2), D3DVALUE(0), D3DVALUE(0)); frame2->AddVisual(mesh2); frame2->Release(); frame2 = 0;

    LPDIRECT3DRMFRAME frame3; d3drm->CreateFrame(scene, &frame3); frame3->SetPosition(scene, D3DVALUE(0), D3DVALUE(0), D3DVALUE(2)); frame3->AddVisual(mesh3); frame3->Release(); frame3 = 0;

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

    На третьем этапе, код которого показан ниже, создается прожектор:

    d3drm->CreateLightRGB(D3DRMLIGHT_SPOT, D3DVALUE(0.8), D3DVALUE(0.8), D3DVALUE(0.8), &spotlight); OnBeamNormal();

    Вначале для инициализации указателя spotlight вызывается функция CreateLightRGB() интерфейса Direct3DRM. Константа D3DRMLIGHT_SPOT указывает, что мы создаем прожектор. Для красной, зеленой и синей составляющих цвета мы указываем значение 0.8, чтобы цвет нашего источника света был светло-серым.

    Затем вызывается функция OnBeamNormal(), являющаяся обработчиком сообщения для пункта Normal меню Beam. Здесь мы вызываем ее для инициализации значений угла светового пятна и угла области освещенности. Чуть позже код функции OnBeamNormal() будет рассмотрен более подробно.

    На четвертом этапе создается фрейм к которому будет присоединен прожектор:

    LPDIRECT3DRMFRAME lightframe; d3drm->CreateFrame(scene, &lightframe); lightframe->SetPosition(scene, D3DVALUE(0), D3DVALUE(10), D3DVALUE(-10)); lightframe->SetOrientation(scene, D3DVALUE(0), D3DVALUE(-1), D3DVALUE(1), D3DVALUE(0), D3DVALUE(1), D3DVALUE(0)); lightframe->AddLight(spotlight); lightframe->AddMoveCallback(MoveLight, NULL); lightframe->Release(); lightframe = 0;



    Указатель lightframe инициализируется функцией CreateFrame() интерфейса Direct3DRM. Функция SetPosition() применяется, чтобы поместить фрейм в точку, расположенную на 10 единиц выше и на 10 единиц дальше начала координат. Затем вызывается функция SetOrientation(), чтобы направить фрейм на начало координат.

    После этого созданный ранее прожектор присоединяется к новому фрейму с помощью функции AddLight(). Кроме того, с помощью функции AddMoveCallback() устанавливается функция обратного вызова MoveLight(). После выполнения всех описанных действий указатель lightframe освобождается.

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

    d3drm->CreateFrame(scene, &camera); camera->SetPosition(scene, D3DVALUE(0), D3DVALUE(6), D3DVALUE(-6)); camera->SetOrientation(scene, D3DVALUE(0), D3DVALUE(-1), D3DVALUE(1.1), D3DVALUE(0), D3DVALUE(1), D3DVALUE(0)); d3drm->CreateViewport(device, camera, 0, 0, device->GetWidth(), device->GetHeight(), &viewport);

    Сначала инициализируется фрейм camera. Затем этот фрейм перемещается от начала координат на шесть единиц вверх и на шесть единиц ближе к зрителю. Функция SetOrientation() применяется, чтобы направить лицевую грань фрейма на начало координат. И, в самом конце, вызывается функция CreateViewport() интерфейса Direct3DRM для инициализации указателя viewport.


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