Сцена в приложении Zoom создается функцией CreateScene(), код которой приведен в листинге 9.1.
Листинг 9.1. Функция ZoomWin::CreateScene() |
BOOL ZoomWin::CreateScene() { // ------- СЕТКА -------- D3DRMLOADRESOURCE resinfo; resinfo.hModule = NULL; resinfo.lpName = MAKEINTRESOURCE(IDR_Z_MESH); resinfo.lpType = "MESH"; d3drm->CreateMeshBuilder(&meshbuilder); meshbuilder->Load(&resinfo, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL); meshbuilder->SetColorRGB(D3DVALUE(.67), D3DVALUE(.82), D3DVALUE(.94)); ScaleMesh(meshbuilder, D3DVALUE(25)); // ------- МАТЕРИАЛ ---------- LPDIRECT3DRMMATERIAL material; d3drm->CreateMaterial(D3DVALUE(10), &material); meshbuilder->SetMaterial(material); material->Release(); material = 0; // ------ ФРЕЙМ СЕТКИ ------ LPDIRECT3DRMFRAME meshframe; d3drm->CreateFrame(scene, &meshframe); meshframe->SetRotation(scene, D3DVALUE(1), D3DVALUE(.4), D3DVALUE(0), D3DVALUE(.1)); meshframe->AddVisual(meshbuilder); meshframe->Release(); meshframe = 0; // ------- АНИМАЦИЯ -------- d3drm->CreateAnimation(&animation); animation->SetOptions(D3DRMANIMATION_SPLINEPOSITION | D3DRMANIMATION_CLOSED | D3DRMANIMATION_POSITION); animation->AddPositionKey(D3DVALUE(0), D3DVALUE(.4), D3DVALUE(0), D3DVALUE(0)); animation->AddPositionKey(D3DVALUE(24), D3DVALUE(5), D3DVALUE(0), D3DVALUE(0)); animation->AddPositionKey(D3DVALUE(49), D3DVALUE(1), D3DVALUE(0), D3DVALUE(0)); animation->AddPositionKey(D3DVALUE(74), D3DVALUE(5), D3DVALUE(0), D3DVALUE(0)); animation->AddPositionKey(D3DVALUE(99), D3DVALUE(.4), D3DVALUE(0), D3DVALUE(0)); d3drm->CreateFrame(scene, &zoomframe); animation->SetFrame(zoomframe); // --------- СВЕТ -------- LPDIRECT3DRMLIGHT dlight; d3drm->CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, D3DVALUE(1.00), D3DVALUE(1.00), D3DVALUE(1.00), &dlight); LPDIRECT3DRMLIGHT alight; d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVALUE(.40), D3DVALUE(.40), D3DVALUE(.40), &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); 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); camera->AddMoveCallback(AdjustField, NULL); return TRUE; } |
Функция CreateScene() выполняет следующие действия:
На первом этапе мы воспользуемся интерфейсом Direct3DRMMeshBuilder чтобы загрузить сетку из файла. Давайте еще раз взглянем на код:
D3DRMLOADRESOURCE resinfo; resinfo.hModule = NULL; resinfo.lpName = MAKEINTRESOURCE(IDR_Z_MESH); resinfo.lpType = "MESH"; meshbuilder->Load(&resinfo, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL); meshbuilder->SetColorRGB(D3DVALUE(.67), D3DVALUE(.82), D3DVALUE(.94)); ScaleMesh(meshbuilder, D3DVALUE(25));Структура D3DRMLOADRESOURCE используется для идентификации элемента ресурсов приложения, содержащего сетку. Член данных meshbuilder инициализируется функцией CreateMeshBuilder() интерфейса Direct3DRM. Затем вызывается функция Load(), которая и загружает сетку. Цвет сетки назначается с помощью функции SetColorRGB(). После выполнения всех этих действий сетка масштабируется до размера в 25 единиц с помощью функции ScaleMesh().
Теперь к сетке применяется материал:
LPDIRECT3DRMMATERIAL material; d3drm->CreateMaterial(D3DVALUE(10), &material); meshbuilder->SetMaterial(material); material->Release(); material = 0;Материал позволяет осуществлять точную настройку внешнегго вида сетки путем изменения интенсивности и цвета отраженного света. В данном случае мы используем материал, придающий сетке вид отполированной поверхности.
СОВЕТ | Тестирование параметров материала. Xpose — это законченная программа просмотра объектов, созданная с использованием рассмотренных в этой книге технологий. И исходный код и исполняемый файл этой программы содержатся на прилагаемом к книге CD-ROM. Самый быстрый способ познакомиться с параметрами материала и тем, какое влияние они оказывают на внешний вид сетки — провести несколько экспериментов с программой Xpose. Диалоговое окно Material Settings программы Xpose позволяет изменить параметры материала и сразу же увидеть результат. |
Для создания материала используется функция CreateMaterial() интерфейса Direct3DRM. Новый материал применяется к сетке с помощью функции SetMaterial() интерфейса Direct3DRMMeshBuilder. После выполнения этих действий локальный указатель material освобождается.
На третьем этапе создается фрейм для сетки:
LPDIRECT3DRMFRAME meshframe; d3drm->CreateFrame(scene, &meshframe); meshframe->SetRotation(scene, D3DVALUE(1), D3DVALUE(.4), D3DVALUE(0), D3DVALUE(.1)); meshframe->AddVisual(meshbuilder); meshframe->Release(); meshframe = 0;Фрейм создается функцией CreateFrame() интерфейса Direct3DRM. С помощью функции SetRotation() новому фрейму назначаются атрибуты вращения. Назначение атрибутов является единственной технологией, используемой для анимации фрейма сетки. Во время работы программы фрейм остается в начале координат (позиции по умолчанию). После того, как конструктор сеток будет присоединен к новому фрейму с помощью функции AddVisual(), указатель meshframe освобождается.
Затем конструируется анимационная последовательность, которая будет использоваться для управления полем зрения порта просмотра. Выполняющий эти действия код выглядит так:
d3drm->CreateAnimation(&animation); animation->SetOptions(D3DRMANIMATION_SPLINEPOSITION | D3DRMANIMATION_CLOSED | D3DRMANIMATION_POSITION); animation->AddPositionKey(D3DVALUE(0), D3DVALUE(.4), D3DVALUE(0), D3DVALUE(0)); animation->AddPositionKey(D3DVALUE(24), D3DVALUE(5), D3DVALUE(0), D3DVALUE(0)); animation->AddPositionKey(D3DVALUE(49), D3DVALUE(1), D3DVALUE(0), D3DVALUE(0)); animation->AddPositionKey(D3DVALUE(74), D3DVALUE(5), D3DVALUE(0), D3DVALUE(0)); animation->AddPositionKey(D3DVALUE(99), D3DVALUE(.4), D3DVALUE(0), D3DVALUE(0)); d3drm->CreateFrame(scene, &zoomframe); animation->SetFrame(zoomframe);Сначала с помощью функции CreateAnimation() интерфейса Direct3DRM создается анимация. Затем вызывается функция SetOptions() интерфейса Direct3DRMAnimation чтобы задать параметры анимации. Мы используем константу D3DRMANIMATION_SPLINEPOSITION чтобы указать, что желаем получить сплайновую анимацию (а не линейную). Этот параметр может быть изменен с помощью меню Animation приложения Zoom. Константа D3DRMANIMATION_CLOSED указывает, что анимационная последовательность должна непрерывно повторяться. Это позволяет использовать непрерывно увеличивающиеся значения времени для повторного выполнения анимационной последовательности. Константа D3DRMANIMATION_POSITION указывает, что анимационная последовательность будет изменять только местоположение объекта (мы не используем константу D3DRMANIMATION_SCALEANDROTATION поскольку, как вы вскоре увидите, мы не используем анимацию для изменения вращения или масштаба объекта).
Затем с помощью функции AddPositionKey() к анимации добавляются пять позиционных ключей. Первым аргументом функции AddPositionKey() является значение, указывающее в какой момент времени данный ключ должен вступить в действие. Оставшиеся три аргумента задают связанную с новым ключом позицию. Обратите внимание, что устанавливаемые ключи отличаются только значением координаты по оси X. Эта ось выбрана произвольно. Мы могли бы использовать оси Y или Z, поскольку мы создаем линейную, или одномерную, анимационную последовательность. Мы будем использовать в анимационной последовательности только ось X.
Затем создается фрейм с именем zoomframe. Новый фрейм присоединяется к анимационной последовательности с помощью функции SetFrame() интерфейса Direct3DRMAnimation.
Фрейм zoomframe является пустым, но он используется не так, как использовались пустые фреймы в приложениях Firefly (глава 6) или Decal (глава 5). Этот пустой фрейм не будет использоваться как родитель для других фреймов. Вместо этого он будет анимироваться созданной ранее анимационной последовательностью, а его координаты будут применяться для установки параметров поля зрения порта просмотра. Обратите внимание, что значение координаты по оси X в анимационной последовательности изменяется в диапазоне от 0.4 до 5.0. Эти значения не будут интерпретироваться как позиции. Вместо этого, они будут использоваться в качестве параметров поля зрения и передаваться в аргументах функции SetField() интерфейса Direct3DRMViewport.
Возвратимся к шести этапам работы функции CreateScene(). На пятом этапе создаются два источника света. Мы пропустим обсуждение этого этапа. Источники света были предметом обсуждения в главе 6.
На шестом, завершающем этапе, выполняется создание порта просмотра:
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->AddMoveCallback(AdjustField, NULL); return TRUE;Сначала создается и размещается фрейм camera. Затем этот фрейм передается в аргументе функции CreateViewport() интерфейса Direct3DRM. Последнее, что делает функция CreateScene() — установка функции обратного вызова AdjustField() с помощью функции AddMoveCallback(). Для установки функции обратного вызова мы используем фрейм camera, но с тем же успехом может быть использован любой другой фрейм сцены.