netlib.narod.ru< Назад | Оглавление | Далее >

Декалы

Во всех рассмотренных до данного момента демонстрационных программах текстуры назначались интерфейсу Direct3DRMMeshBuilder, а затем конструктор сеток присоединялся к фрейму функцией AddVisual() интерфейса Direct3DRMFrame.

В этом разделе мы введем и обсудим понятие декала. Декал — это текстура, которая добавляется непосредственно к сцене. Декалы в сцене выглядят точно также, как и в графическом редакторе; они не могут быть обернуты вокруг объектов сцены. Можно перемещать и масштабировать декалы, но их нельзя вращать; декалы всегда повернуты к камере своей лицевой поверхностью. Этот факт ограничивает полезность декалов, но их все равно удобно применять для добавления к сцене двумерных элементов. Например, часто в приложениях с помощью декалов изображают взрывы, поскольку использование для изображения взрывов граней и сеток требует слишком большого количества ресурсов.


СОВЕТ


О декалах. Некоторые из функций интерфейса Direct3DRMTexture используют слово «decal», и декалы реализуются с помощью интерфейса Direct3DRMTexture. Интерфейса Direct3DRMDecal не существует.


Приложение Decal

Поддержка декалов в Direct3D представлена в приложении Decal. Приложение Decal анимирует два декала, перемещая их вокруг сцены. Окно приложения Decal показано на рис. 5.7.


Рис. 5.7 Приложение Decal

Рис. 5.7. Приложение Decal


Приложение Decal демонстрирует следующие технологии:

Перед тем, как перейти к рассмотрению кода приложения Decal, следует поговорить о пустых фреймах. Пустой фрейм (dummy frame) — это фрейм, используемый только для анимации других фреймов. К пустому фрейму не присоединено никаких видимых объектов, таких как сетки или декалы, и он используется как родительский фрейм для других фреймов к которым присоединены видимые объекты.

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

Класс DecalWin

Основная функциональность приложения Decal сосредоточена в классе DecalWin:

class DecalWin : public RMWin
{
public:
    BOOL CreateScene();
protected:
    //{{AFX_MSG(DecalWin)
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

Класс DecalWin очень простой. В нем объявлена только одна функция: CreateScene(). Код класса после слова protected содержит код мастера ClassWizard, необходимый если в дальнейшем будут добавляться обработчики событий.

Функция 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. Далее в этой книге мы более подробно изучим источники света и порты просмотра.


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz