18 января 2010 в 13:36
Уроки Direct3D - 1.6. Рисуем цилиндр.TriangleStrip
От проекта к проекту мы постепенно осваиваем приемы программирования DirectX. Как правило, каждый новый проект основывается на предыдущих, поэтому дальше я не буду комментировать все изменения и дополнения, если эти изменения и дополнения уже изучены. Если, например, в новом проекте изменена позиция наблюдателя (матрица трансформации D3DTS_VIEW), то вы можете понять это и без комментариев, так как у вас есть код всех проектов.
Представим, что нам нужно изобразить цилиндр. Естественно мы его имитируем с помощью призмы, ведь нам недоступны кривые линии. Призма, имеющая 64 боковых грани уже достаточно близко соответствует цилиндру, остановимся на этом числе граней. Каждая грань призмы – это прямоугольник, который мы можем отобразить двумя треугольниками. Итого нам нужно 128 треугольников или 128 * 3 = 384 вертекса. Согласитесь, многовато. А ведь позиции каждого вертекса совпадают с позицией еще двух вертексов, принадлежащих другим треугольникам, если мы сможем вместо трех таких вертексов использовать один – мы уменьшим размер вертексного буфера в 3 раза.
И такой способ есть, он заключается в использовании параметра D3DPT_TRIANGLESTRIP вместо D3DPT_TRIANGLELIST в методе d3dDevice.DrawPrimitive. Рассмотрим принцип его работы. Первые три вертекса из вертексного буфера, как и раньше, соответствуют первому отображаемому треугольнику, а вот следующий треугольник задан не 4-ым, 5-ым, 6-ым, а 2-ым, 3-ым, 4-ым вертексами. Только лицевой уже считается та сторона, на которой вертексы расположены против часовой стрелки. Следующий треугольник задается 3-ым, 4-ым, 5-ым вертексами, на лицевой стороне вертексы опять расположены по часовой стрелке, и так далее. Это можно изобразить так:
В результате получается лента из треугольников, где для N треугольников необходимо задать N+2 вертексов. Если наш цилиндр задать такой лентой, свернутой в кольцо, нам понадобится всего 130 вертексов.
Если непосредственно задавать 130 вертексов, это займет много страниц кода. Поэтому переделаем процедуру InitGeometry. Создадим вспомогательную функцию для задания одного вертекса:
Private Function Vertex(X As Single, Y As Single, Z As Single, C As Long) As vFormat Vertex.Pos = vec3(X, Y, Z) Vertex.Color = C End Function
А InitGeometry будет выглядеть так:
Private Sub InitGeometry() Dim n As Long Set vBuffer = d3dDevice.CreateVertexBuffer(2 * 65 * vSize, 0, vFlag, D3DPOOL_DEFAULT) For n = 0 To 64 Vert(0) = Vertex(Sin(2 * Pi * n / 64), -1, Cos(2 * Pi * n / 64), Rnd * &HFFFFFF) Vert(1) = Vertex(Sin(2 * Pi * n / 64), 1, Cos(2 * Pi * n / 64), Rnd * &HFFFFFF) D3DVertexBuffer8SetData vBuffer, vSize * 2 * n, vSize * 2, 0, Vert(0) Next n End Sub
И заменим в процедуре Render параметр D3DPT_TRIANGLELIST на D3DPT_TRIANGLESTRIP:
d3dDevice.DrawPrimitive D3DPT_TRIANGLESTRIP, 0, 128
Это означает вывод ленты из 128 треугольников из вертексного буфера, начиная с нулевого вертекса. Запускаем программу и видим разноцветный цилиндр.
комментарии отсутствуют
авторизуйтесь