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

3.6. Примеры приложений: треугольники, кубы, чайники, D3DXCreate*

В сопроводительных файлах, которые вы можете загрузить с веб-сайта этой книги, посвященный данной главе каталог содержит четыре приложения.

Давайте кратко обсудим реализацию примера Cube. Остальные примеры вы можете изучить самостоятельно.

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


Рис. 3.4. Окно приложения Cube

Рис. 3.4. Окно приложения Cube


Сперва мы объявляем две глобальных переменных, которые будут хранить данные вершин и индексов нашего куба:

IDirect3DVertexBuffer9* VB = 0;
IDirect3DIndexBuffer9*  IB = 0;

Кроме того, мы объявляем две глобальных константы, задающих разрешение экрана:

const int Width  = 800;
const int Height = 600;

Затем мы описываем структуру для хранения данных вершин и приводим описание настраиваемого формата вершин для этой структуры. В данном примере структура данных вершины содержит только информацию о местоположении вершины:

struct Vertex
{
     Vertex(){}
     Vertex(float x, float y, float z)
     {
          _x = x; _y = y; _z = z;
     }
     float _x, _y, _z;
     static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZ;

Давайте перейдем к функциям, образующим каркас приложения. Функция Setup создает буфер вершин и буфер индексов, блокирует их, записывает в буфер вершин данные образующих куб вершин, а в буфер индексов — индексы, описывающие образующие куб треугольники. Затем камера отодвигается на несколько единиц назад, чтобы мы могли увидеть куб, расположенный в начале мировой системы координат. После этого устанавливается преобразование проекции. В самом конце мы включаем каркасный режим визуализации:

bool Setup()
{
     // Создание буфера вершин и буфера индексов
     Device->CreateVertexBuffer(
                   8 * sizeof(Vertex),
                   D3DUSAGE_WRITEONLY,
                   Vertex::FVF,
                   D3DPOOL_MANAGED,
                   &VB,
                   0);

     Device->CreateIndexBuffer(
                   36 * sizeof(WORD),
                   D3DUSAGE_WRITEONLY,
                   D3DFMT_INDEX16,
                   D3DPOOL_MANAGED,
                   &IB,
                   0);

     // Заполнение буферов данными куба
     Vertex* vertices;
     VB->Lock(0, 0, (void**)&vertices, 0);

     // Вершины единичного куба
     vertices[0] = Vertex(-1.0f, -1.0f, -1.0f);
     vertices[1] = Vertex(-1.0f,  1.0f, -1.0f);
     vertices[2] = Vertex( 1.0f,  1.0f, -1.0f);
     vertices[3] = Vertex( 1.0f, -1.0f, -1.0f);
     vertices[4] = Vertex(-1.0f, -1.0f,  1.0f);
     vertices[5] = Vertex(-1.0f,  1.0f,  1.0f);
     vertices[6] = Vertex( 1.0f,  1.0f,  1.0f);
     vertices[7] = Vertex( 1.0f, -1.0f,  1.0f);

     VB->Unlock();

     // Описание образующих куб треугольников
     WORD* indices = 0;
     IB->Lock(0, 0, (void**)&indices, 0);

     // передняя грань
     indices[0]  = 0; indices[1]  = 1; indices[2]  = 2;
     indices[3]  = 0; indices[4]  = 2; indices[5]  = 3;

     // задняя грань
     indices[6]  = 4; indices[7]  = 6; indices[8]  = 5;
     indices[9]  = 4; indices[10] = 7; indices[11] = 6;

     // левая грань
     indices[12] = 4; indices[13] = 5; indices[14] = 1;
     indices[15] = 4; indices[16] = 1; indices[17] = 0;

     // правая грань
     indices[18] = 3; indices[19] = 2; indices[20] = 6;
     indices[21] = 3; indices[22] = 6; indices[23] = 7;

     // верх
     indices[24] = 1; indices[25] = 5; indices[26] = 6;
     indices[27] = 1; indices[28] = 6; indices[29] = 2;

     // низ
     indices[30] = 4; indices[31] = 0; indices[32] = 3;
     indices[33] = 4; indices[34] = 3; indices[35] = 7;

     IB->Unlock();

     // размещение и ориентация камеры
     D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
     D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
     D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
     D3DXMATRIX V;
     D3DXMatrixLookAtLH(&V, &position, &target, &up);

     Device->SetTransform(D3DTS_VIEW, &V);

     // установка матрицы проекции
     D3DXMATRIX proj;
     D3DXMatrixPerspectiveFovLH(
             &proj,
             D3DX_PI * 0.5f, // 90 градусов
             (float)Width / (float)Height,
             1.0f,
             1000.0f);
     Device->SetTransform(D3DTS_PROJECTION, &proj);

     // установка режима визуализации
     Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

     return true;
}

У метода Display две задачи: он должен обновлять сцену и затем визуализировать ее. Поскольку мы хотим, чтобы куб вращался, нам надо в каждом кадре увеличивать угол, определяющий насколько повернут куб. Из-за того, что угол в каждом кадре немного увеличивается, куб в каждом кадре чуть больше повернут, и в результате кажется, что он вращается. Обратите внимание, что для ориентации куба мы применяем мировое преобразование. Затем мы рисуем куб с помощью метода IDirect3DDevice9::DrawIndexedPrimitive.

bool Display(float timeDelta)
{
     if( Device )
     {
          //
          // вращение куба:
          //
          D3DXMATRIX Rx, Ry;

          // поворот на 45 градусов вокруг оси X
          D3DXMatrixRotationX(&Rx, 3.14f / 4.0f);

          // увеличение угла поворота вокруг оси Y в каждом кадре
          static float y = 0.0f;
          D3DXMatrixRotationY(&Ry, y);
          y += timeDelta;

          // сброс угла поворота, если он достиг 2*PI
          if( y >= 6.28f )
               y = 0.0f;

          // комбинация поворотов
          D3DXMATRIX p = Rx * Ry;

          Device->SetTransform(D3DTS_WORLD, &p);

          //
          // рисование сцены:
          //
          Device->Clear(0, 0,
                D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
                0xffffffff, 1.0f, 0);
          Device->BeginScene();

          Device->SetStreamSource(0, VB, 0, sizeof(Vertex));
          Device->SetIndices(IB);
          Device->SetFVF(Vertex::FVF);
          Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
                                              0, 0, 8, 0, 12);

          Device->EndScene();
          Device->Present(0, 0, 0, 0);
     }
     return true;
}

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

void Cleanup()
{
     d3d::Release<IDirect3DVertexBuffer9*>(VB);
     d3d::Release<IDirect3DIndexBuffer9*>(IB);
}

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

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