Опубликован: 08.07.2007 | Уровень: специалист | Доступ: платный
Лекция 6:

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

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >

Вывод трехмерных объектов

В первую очередь при визуализации трехмерных объектов, необходимо изменить формат вершины и набор FVF флагов.

C++
struct VERTEX3D
{
    FLOAT x, y, z;
    …
};
VERTEX3D data[];

#define MY_FVF (D3DFVF_XYZ | …);
Pascal
type
  Vertex3D = packed record
      x, y, z: Single;
      …
  end;

const
  MY_FVF = D3DFVF_XYZ or …;

var 
  data: array of Vertex3D;

Единственное отличие от двумерного случая будет заключаться в наличии операций с матрицами для преобразования объектов. Функции для визуализации трехмерных объектов будут такими же, какие мы использовали в двумерном случае: DrawPrimitive, DrawPrimitiveUP, DrawIndexedPrimitive, DrawIndexedPrimitiveUP. В качестве примера разберем построение, вращающего вокруг одной из координатных осей, цветного треугольника. Запишем шаги, которые мы должны проделать.

  1. Определение формата вершин треугольника и набор FVF флагов;
  2. Заполнение массива вершин данными;
  3. Установка видовой и проекционной матриц;
  4. Установка мировой матрицы (поворот вокруг оси) и вывод примитива.

Приведем программные строки для каждого шага алгоритма.

C++
struct VERTEX3D
{
    FLOAT x, y, z;
    DWORD color;
};
#define MY_FVF (D3DFVF_XYZ | D3DFVF_DIFFUSE);
...
VERTEX3D points[3] = {
        { -1.0f,-1.0f, 0.0f, 0x00ff0000, },
        {  0.0f, 1.0f, 0.0f, 0x0000ff00, },
        {  1.0f,-1.0f, 0.0f, 0x000000ff, }
}
...
D3DXMATRIX matWorld, matView, matProj;

D3DXMatrixLookAtLH( &matView,  &D3DXVECTOR3 ( 0.0f, 0.0f,-5.0f ),
                               &D3DXVECTOR3 ( 0.0f, 0.0f, 0.0f ),
                               &D3DXVECTOR3 ( 0.0f, 1.0f, 0.0f ) );
device->SetTransform( D3DTS_VIEW, &matView );

D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 
  100.0f );
device->SetTransform( D3DTS_PROJECTION, &matProj );
...
D3DXMatrixRotationY( &matWorld, angle );
device->SetTransform( D3DTS_WORLD, &matWorld );

device->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
Pascal
type
  Vertex3D = packed record
      x, y, z: Single;
      color: DWORD;
  end;

const
  MY_FVF = D3DFVF_XYZ or D3DFVF_DIFFUSE;

var 
  points: array [0..2] of Vertex3D = (
   (x: -1; y: -1; z: 0; color: $000000ff),
   (x:  0; y:  1; z: 0; color: $0000ff00),
   (x:  1; y: -1; z: 0; color: $00ff0000)
  );

  matWorld, matView, matProj: TD3DMatrix;
...


D3DXMatrixLookAtLH(matView,
                   D3DXVector3(0,0,-5),
                   D3DXVector3(0,0,0),
                   D3DXVector3(0,1,0));
device.SetTransform(D3DTS_VIEW, matView);

D3DXMatrixPerspectiveFovLH(matProj, PI/4, 1, 1, 100);
device.SetTransform(D3DTS_PROJECTION, matProj);
...
D3DXMatrixRotationY(matWorld, angle);
device.SetTransform(D3DTS_WORLD, matWorld);
device.DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

Ниже приведен пример нескольких кадров из анимации.


Библиотека Direct3D располагает механизмом отсечения граней. Идея заключается в том, что можно указать порядок обхода вершин треугольника (по часовой или против часовой стрелки) и отключить вывод тех граней, которые перечислены, например, по часовой стрелке. По умолчанию механизм отсечения граней отключен, т.е. воспроизводятся обе стороны примитива. Программно отключение "задних" сторон примитива реализуется через вызов метода SetRenderState(D3DRS_CULLMODE, <значение>) интерфейса IDirect3DDevice9. В качестве второго параметра может выступать одна из трех констант: D3DCULL_NONE – механизм отбраковки граней выключен;

D3DCULL_CW – отбраковываются грани, вершины которых перечислены по часовой стрелке;

D3DCULL_CCW – отбраковываются грани, вершины которых перечислены против часовой стрелки.

Так, на представленном ниже рисунке грань (треугольник) задается перечислением своих вершин: v0, v1, v2по часовой стрелке; v0, v2, v1 – против часовой стрелки.

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >
Денис Баканов
Денис Баканов
Россия, г. Кострома
Паулус Шеетекела
Паулус Шеетекела
Россия, ТГТУ, 2010