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

         

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


Сцена создается в функции CreateScene(). Если вы назвали проект AmbientLight, функция CreateScene() будет выглядеть подобно показанной в листинге 6.1.

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

BOOL AmbientLightWin::CreateScene() { HRESULT r; // ------ СЕТКА -------- d3drm->CreateMeshBuilder(&meshbuilder); r = meshbuilder->Load(meshname, NULL, D3DRMLOAD_FROMFILE, NULL, NULL); if (r != D3DRM_OK) { CString msg; msg.Format("Failed to load file '%s'\n", meshname); AfxMessageBox(msg); return FALSE; } ScaleMesh(meshbuilder, D3DVALUE(25)); //------- ФРЕЙМ СЕТКИ -------- LPDIRECT3DRMFRAME meshframe; d3drm->CreateFrame(scene, &meshframe); meshframe->AddVisual(meshbuilder); meshframe->SetRotation(scene, D3DVALUE(0), D3DVALUE(1), D3DVALUE(0), D3DVALUE(.1)); meshframe->Release(); meshframe = 0; // -------- РАССЕЯННЫЙ СВЕТ -------- LPDIRECT3DRMLIGHT alight; d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(1.00), D3DVALUE(1.00), D3DVALUE(1.00), &alight); scene->AddLight(alight); 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. Создание порта просмотра.

На первом этапе для загрузки сетки из файла используется интерфейс Direct3DRMMeshBuilder. Рассмотрим этот фрагмент более пристально:

d3drm->CreateMeshBuilder(&meshbuilder); r = meshbuilder->Load(meshname, NULL, D3DRMLOAD_FROMFILE, NULL, NULL); if (r != D3DRM_OK) { CString msg; msg.Format("Failed to load file '%s'\n", meshname); AfxMessageBox(msg); return FALSE; } ScaleMesh(meshbuilder, D3DVALUE(25));

Сначала с помощью функции CreateMeshBuilder() интерфейса Direct3DRM инициализируется переменная meshbuilder. Затем для загрузки файла сетки с диска вызывается функция Load() (переменная meshname хранит имя файла сетки, которое было указано при создании приложения с помощью мастера AppWizard). Если выполнение функции Load() завершается неудачей, выводится окно сообщения и возвращается значение FALSE. Если функция Load() завершилась успешно, вызывается функция ScaleMesh() для задания оптимального размера сетки.

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

LPDIRECT3DRMFRAME meshframe; d3drm->CreateFrame(scene, &meshframe); meshframe->AddVisual(meshbuilder); meshframe->SetRotation(scene, D3DVALUE(0), D3DVALUE(1), D3DVALUE(0), D3DVALUE(.1)); meshframe->Release(); meshframe = 0;

Указатель meshframe объявлен как указатель на интерфейс Direct3DRMFrame. Для создания нового фрейма применяется функция CreateFrame() интерфейса Direct3DRM. Конструктор сеток meshbuilder, созданный на предыдущем этапе, присоединяется к новому фрейму с помощью функции AddVisual().

Далее производится вызов функции SetRotation(), чтобы назначить фрейму атрибуты вращения. Фрейм будет вращаться вокруг оси Y (на это указывают первые три аргумента функции). Последний аргумент функции SetRotation() указывает, что фрейм будет поворачиваться при каждом обновлении изображения на 0.1радиан.

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

LPDIRECT3DRMLIGHT alight; d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(1.00), D3DVALUE(1.00), D3DVALUE(1.00), &alight); scene->AddLight(alight); alight->Release(); alight = 0;

Переменная alight объявляется как указатель на интерфейс Direct3DRMLight. Функция CreateLightRGB() используется для создания источника света и инициализации указателя alight. Первый аргумент функции CreateLightRGB() — это константа, которая определяет тип создаваемого источника света. Используемая здесь константа, D3DRMLIGHT_AMBIENT, является одной из пяти возможных:

  • D3DRMLIGHT_AMBIENT
  • D3DRMLIGHT_POINT
  • D3DRMLIGHT_SPOT
  • D3DRMLIGHT_DIRECTIONAL
  • D3DRMLIGHT_PARALLELPOINT

Следующие три аргумента функции CreateLightRGB() определяют цвет источника света. Использованные значения (1, 1, 1) указывают, что будет создан источник белого света, поскольку для красной, зеленой и синей составляющих заданы одинаковые, максимально возможные значения. Ниже показаны некоторые альтернативные варианты.

d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(1.00), D3DVALUE(0.00), D3DVALUE(0.00), &alight); // создает источник красного света d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(0.00), D3DVALUE(1.00), D3DVALUE(0.00), &alight); // создает источник зеленого света d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(0.00), D3DVALUE(0.00), D3DVALUE(1.00), &alight); // создает источник синего света d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(1.00), D3DVALUE(0.00), D3DVALUE(1.00), &alight); // создает источник пурпурного света d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(0.30), D3DVALUE(0.30), D3DVALUE(0.30), &alight); // создает источник темно-серого света

Если в сцене присутствует только один источник рассеянного света (что справедливо для нашей сцены), все грани в сцене будут визуализированы с использованием цвета этого источника света. Последним аргументом функции CreateLightRGB() является адрес указателя alight.

Затем новый источник света присоединяется к фрейму сцены:

scene->AddLight(alight);

Как вы увидите далее в этой главе, когда мы будем рассматривать другие типы источников света, остальные источники света не будут присоединены непосредственно к корневому фрейму сцены. Источник рассеянного света может быть присоединен к коревому фрейму потому, что на него не оказывает влияние местоположение и ориентация фрейма. Фактически, источник рассеянного света может быть присоединен к любому фрейму сцены и результат от этого не изменится.

После этого мы освобождаем указатель alight и обнуляем его:

alight->Release(); alight = 0;

Помните, что вызов функции Release() освобождает указатель, а не сам объект. Объект будет уничтожен только когда не останется ни одного указывающего на него указателя. В данном случае источник света не будет уничтожен, поскольку он был добавлен к сцене.

Четвертым и последним этапом работы функции CreateScene() является создание порта просмотра:

d3drm->CreateFrame(scene, &camera); camera->SetPosition(scene, D3DVALUE(0), D3DVALUE(0), D3DVALUE(-50)); d3drm->CreateViewport(device, camera, 0, 0, device->GetWidth(), device->GetHeight(), &viewport);

В этом фрагменте кода выполняется инициализация двух указателей: camera и viewport. Как говорилось в главе 4, эти указатели являются членами класса RMWin. Наша функция CreateScene() должна инициализировать эти указатели. Если мы не сделаем этого, выполнение приложения будет остановлено, и будет выведено сообщение об ошибке.

Указатель camera — это указатель на интерфейс Direct3DRMFrame, который инициализируется функцией CreateFrame() интерфейса Direct3DRM. Затем новый фрейм перемешается на 50 единиц от начала координат по направлению к зрителю. Это делается из-за того, что сетка, созданная на первом этапе, была помещена в начало координат (по умолчанию). Мы смещаем камеру от начала координат, чтобы объект попал в область просмотра. Затем для инициализации указателя viewport вызывается функция CreateViewport() интерфейса Direct3DRM.

Завершая работу, функция CreateScene() возвращает TRUE, чтобы сообщить об успешном выполнении всех действий. Если функция CreateScene() возвращает FALSE, работа приложения прекращается и выводится сообщение об ошибке.



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