DirectX & Visual Basic

Учебник DirectX Graphics: часть 6

<<Предыдущая часть

Использование .x файлов

Если в предыдущих программах нам надо было создать треугольник или циллиндр мы создавали его из трёхмерных вершин по определённому алгоритму. Теперь представим, что Вы пишите 3d игру, для которой нужен, например, трёхмерный самолёт. Он будет сосотоять из десятков и сотен трёхмерных вершин и написать в программе порцедуру, по вершине создающей его, будет практически невозможно. Как же поступить? В таких случаях используются файлы, в котрых сохраняются сложные трёхмерные объекты. Существует множество форматов таких файлов и, соответственно, редакторов, с ними работающих. В одном из таких редакторов, например, 3d Studio Max, Вы создаёте некий 3d объект, сохраняете его в файле *.3ds, конвертируете его с помощью специальной утилиты в файл *.x, который затем загружаете в своей программе с помощью методов класса D3DX8 . Формат файлов .x Microsoft создала специально для Direct3d. Более подробное описание формата .x Вы можете найти в DX SDK.

Утилиту, конвертирующую файлы .3ds в файлы формата .x Вы можете скачать с этого сайта.

Программа, которую мы напишем в этой части довольно сильно отличается от программы из предыдущей части. В коде модуля формы будут следующие объявления:

Dim g_DX As New DirectX8
Dim g_D3DX As New D3DX8
Dim g_D3D As Direct3D8
Dim g_D3DDevice As Direct3DDevice8
Dim g_Mesh As D3DXMesh                  ' Наш 3d объект
Dim g_MeshMaterials() As D3DMATERIAL8   ' Данные о материалах 3d объекта
Dim g_MeshTextures() As Direct3DTexture8 ' Текстуры 3d объекта
Dim g_NumMaterials As Long

Const g_pi = 3.1415

Как видите здесь нет объявления буффера трёхмерных вершин и пользовательского типа трёхмерных вершин, потому что мы их не используем. Зато здесь есть объявления 3d объекта g_Mesh; массивов g_MeshMaterials и g_MeshTextures, в которых будет содержаться информация, нужная при рендеринге 3d объекта; а также переменной g_NumMaterials, в которой будет сохраняться количество материалов 3d объекта.

Сильные изменения произошли также и в функции InitGeometry, код котрой приведён ниже:

Function InitGeometry() As Boolean
On Local Error Resume Next

Dim MtrlBuffer As D3DXBuffer
Dim i As Long

Set g_Mesh = g_D3DX.LoadMeshFromX(App.Path + "\Tiger.x", D3DXMESH_MANAGED, _
                               g_D3DDevice, Nothing, MtrlBuffer, g_NumMaterials)
If g_Mesh Is Nothing Then Exit Function

ReDim g_MeshMaterials(g_NumMaterials)
ReDim g_MeshTextures(g_NumMaterials)

Dim strTexName As String

For i = 0 To g_NumMaterials - 1
    ' Копирование материала из буффера MtrlBuffer в массив g_MeshMaterials
    g_D3DX.BufferGetMaterial MtrlBuffer, i, g_MeshMaterials(i)

    ' Установка окружающего цвета материала (D3DX этого не делает)
    g_MeshMaterials(i).Ambient = g_MeshMaterials(i).diffuse
     
    ' Создание текстуры
    strTexName =
    g_D3DX.BufferGetTextureName(MtrlBuffer,  i) If
    strTexName <>  "" Then
        Set g_MeshTextures(i) = g_D3DX.CreateTextureFromFile(g_D3DDevice, App.Path + "\" + strTexName)
    End If
Next

Set MtrlBuffer = Nothing

InitGeometry = True
End Function

Загрузка 3d объекта, или по-английски Mesh, происходит с помощью метода LoadMeshFromX объекта g_D3DX. Первый параметр метода - имя .x файла для загрузки; второй - комбинация флагов, задающих опции создания 3d объекта; третий параметр - устройство, использующуеся для рендеринга этого 3d объекта; четвёртый параметр - буффер, заполняемый данными о соседях поверхостей в 3d объекте (нами не используется); пятый параметр - буффер, заполняемый данными о текстурах и материалах 3d объекта; шестой параметр - количество частей 3d объекта (каждая часть - это набор примитивов, для которых используется один и тот же материал и одна и та же текстура).

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

Далее в цикле для каждой части 3d объекта происходит копирование материала из буффера MtrlBuffer в массив g_MeshMaterials с помощью метода BufferGetMaterial объекта g_D3DX. Кроме того происходит заполнение массива g_MeshTextures текстурами, созданными из файлов, имена которых извлекаются из буффера MtrlBuffer с помощью метода BufferGetTextureName.

В конце функции InitGeometry происходит уничтожение объекта MtrlBuffer, так как он нам больше не потребуется.

Теперь, когда 3d объект загружен вместе с материалами и тектурами осталось его только отрендерить. Это и делает изменившаяся процедура Render.

Public Sub Render()
Dim i As Long

g_D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, &HFF&, 1, 0

' Начало сцены
g_D3DDevice.BeginScene

SetupMatrices

' 3d объекты разделены на части (subsets).
' У каждой части свой материал и текстура.
' Рендеринг 3d объекта по частям в цикле:
For i = 0 To g_NumMaterials - 1
    ' Установка материала и текстуры для каждой части
    g_D3DDevice.SetMaterial g_MeshMaterials(i)
    g_D3DDevice.SetTexture 0, g_MeshTextures(i)
    ' Прорисовка части 3d объекта
    g_Mesh.DrawSubset i
Next

' Конец сцены
g_D3DDevice.EndScene

g_D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub

Думаю, всё должно быть ясно, так как процедура прокомментирована.

В процедуру SetupMatrices внесём следующие изменения:

1. Чтобы объекты сцены вращались вокруг оси OY замените строку, вращавшую объекты сцены вокруг вектора (1;1;1) , этой строкой:

D3DXMatrixRotationY matWorld, Timer / 4

2. Чтобы камера была ближе к 3d объекту замените код, изменявший матрицу обзора, этим кодом:

D3DXMatrixLookAtLH matView, vec3(0, 3, -3), _
                            vec3(0, 0, 0), _
                            vec3(0, 1, 0)

Осталось только заменить код процедуры CleanUp, которая теперь также очищает массивы g_MeshTextures и g_MeshMaterials, новым кодом:

Sub Cleanup()
    Erase g_MeshTextures
    Erase g_MeshMaterials
    
    Set g_Mesh = Nothing
    Set g_D3DDevice = Nothing
    Set g_D3D = Nothing
End Sub

Программа готова! Запустив её на выполнение, Вы можете видеть вращающегося тигра, загруженного из файла tiger.x.

Вы можете скачать архив RAR с готовым проектом (21 Кб). В архиве есть также файлы tiger.x и tiger.jpg.

Цикл статей "Учебник DirectX Graphics" закончен, но раздел "Статьи" сайта DirectX & Visual Basic будет обновляться и в дальнейшем.

Hosted by uCoz