10 февраля 2010 в 20:48
Уроки Direct3D - 2.6. Использование моделей. Mesh
До сих пор для того, чтобы создать какой-либо геометрический объект, мы выполняли некоторые стандартные действия, занимающие достаточно объемный код.
В первую очередь мы создавали флаговое описание вертекса, новый тип, соответствующий формату вертекса и сам вертексный буфер. Для более сложных моделей так же создавался индексный буфер.
Далее для отображения нашего геометрического объекта мы сообщали устройству рендера (d3dDevice), какие вертексный и индексный буферы используется, какой размер у вертекса и как его обрабатывать (флаговое описание). Дальше мы вызывали процедуру рендера с указанием с какого вертекса и индекса следует начинать вывод и сколько треугольников отображать.
Ну и, естественно, необходимо было не забыть уничтожить все ранее созданные объекты до завершения программы.
А, между прочим, создавать, отображать и уничтожать геометрические объекты можно одной командой. В Direct3D существует класс D3DXMesh, предназначенный для хранения таких объектов. Объект (экземпляр класса) можно загружать из файла, так же некоторые простые формы, такие как куб, сфера и т. п. можно генерировать.
Создадим новый проект, как обычно на основе предыдущего. Модуль modMain перепишем полностью. В разделе Declarations оставим только две общих переменных Running и FPS и добавим один объект класса D3DXMesh:
Public Running As Boolean Public FPS As Long Dim Mesh As D3DXMesh
Добавим процедуры для инициализации света и материала:
Private Sub InitLight() Dim Light As D3DLIGHT8 Light.Type = D3DLIGHT_DIRECTIONAL Light.Direction = vec3(-1, -1, 1) Light.diffuse.r = 1 Light.diffuse.g = 1 Light.diffuse.b = 1 d3dDevice.SetLight 0, Light d3dDevice.LightEnable 0, 1 End Sub Private Sub InitMaterial() Dim Mat As D3DMATERIAL8 Mat.diffuse.r = 1 Mat.diffuse.g = 1 Mat.diffuse.b = 1 Mat.Ambient = Mat.diffuse d3dDevice.SetMaterial Mat End Sub
Уже привычная инициализация трансформаций:
Private Sub InitMatrix() Dim Mtrx As D3DMATRIX D3DXMatrixIdentity Mtrx d3dDevice.SetTransform D3DTS_WORLD, Mtrx D3DXMatrixPerspectiveFovLH Mtrx, Pi / 4, frmD3D.ScaleHeight / frmD3D.ScaleWidth, 0.5, 10 d3dDevice.SetTransform D3DTS_PROJECTION, Mtrx D3DXMatrixLookAtLH Mtrx, vec3(0, 1, -3), vec3(0, 0, 0), vec3(0, 1, 0) d3dDevice.SetTransform D3DTS_VIEW, Mtrx End Sub
Процедура ClearAll будет содержать только уничтожение Mesh и D3DTerminate:
Private Sub ClearAll() Set Mesh = Nothing D3DTerminate End Sub
Создадим новую процедуру InitMesh для инициализации модели, она выполняет те же функции, которые раньше выполняла процедура InitGeometry:
Private Sub InitMesh() Set Mesh = d3dx.CreateBox(d3dDevice, 1, 1, 1, Nothing) End Sub
В этой процедуре из одной строки генерируется Box (прямоугольный параллелепипед) с размерами «1, 1, 1», то есть куб.
В процедуре Render между BeginScene и EndScene так же будет всего одна строка:
Private Sub Render() d3dDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, &H346666, 1, 0 d3dDevice.BeginScene Mesh.DrawSubset 0 d3dDevice.EndScene d3dDevice.Present ByVal 0, ByVal 0, 0, ByVal 0 End Sub
И, наконец, Sub Main:
Public Sub Main() Dim Mtrx As D3DMATRIX frmD3D.Show QFreqIni D3DInit frmD3D.hWnd InitMatrix InitMesh InitLight InitMaterial d3dDevice.SetRenderState D3DRS_CULLMODE, D3DCULL_CCW d3dDevice.SetRenderState D3DRS_ZENABLE, D3DZB_TRUE d3dDevice.SetRenderState D3DRS_LIGHTING, 1 Running = True Do While Running DoEvents D3DXMatrixRotationY Mtrx, QTime * 0.5 d3dDevice.SetTransform D3DTS_WORLD, Mtrx Render FPS = FPS + 1 Loop Unload frmD3D ClearAll End Sub
Здесь все привычно, добавился только вызов InitMesh – инициализации модели, в нашем случае куба.
Запускаем программу и видим вращающийся куб. Модель, генерируемая D3DX, содержит в формате вертекса координаты и нормаль, поэтому мы можем наблюдать эффект освещения. Обратите внимание, команда для непосредственного отображения модели Mesh.DrawSubset имеет параметр. Дело в том, что сложные модели могут состоять из нескольких частей, называемых Subset, которые можно отображать независимо друг от друга. Это сделано для того, чтобы между отображением частей можно было поменять параметры рендеринга, например, сменить материал или текстуру. Или, представьте, что наша модель – автомобиль. Если ее колеса будут отдельными частями, их можно будет вращать, меняя трансформацию мира непосредственно перед их отображением.
Познакомимся с другими примитивными формами, которые можно генерировать средствами D3DX. Заменим единственную строку в InitMesh на такую:
Set Mesh = d3dx.CreateSphere(d3dDevice, 0.6, 32, 32, Nothing)
Теперь у нас не куб, а сфера. Параметры «0.6, 32, 32» – это радиус, число «меридианов» и число «параллелей». Так же можно сгенерировать цилиндр (а мы мучались!):
Set Mesh = d3dx.CreateCylinder(d3dDevice, 0.7, 0.7, 1, 64, 1, Nothing) Тор: Set Mesh = d3dx.CreateTorus(d3dDevice, 0.2, 0.7, 32, 32, Nothing)
И, ставшую уже классической, модель чайника:
Set Mesh = d3dx.CreateTeapot(d3dDevice, Nothing)
Несколько другой синтаксис у процедуры генерации объемного текста:
d3dx.CreateText d3dDevice, frmD3D.hDC, "Test", 0.002, 0.1, Mesh, Nothing, ByVal 0
Для того, чтобы это сработало, необходимо присвоить свойству Font формы frmD3D какой-нибудь шрифт, обязательно TrueType! Этим требованиям удовлетворяет, например, шрифт Courier New, но не Courier.
комментарии отсутствуют
авторизуйтесь