Опубликован: 08.07.2007 | Доступ: свободный | Студентов: 1431 / 183 | Оценка: 4.43 / 4.02 | Длительность: 13:47:00
Специальности: Программист
Лекция 2:

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

< Лекция 1 || Лекция 2: 123456 || Лекция 3 >

Рассмотрим оставшиеся типы примитивов, которые имеются в наличии у библиотеки Direct3D.

  1. Вывод отрезков
    • Для построения независимых отрезков первым аргументом метода DrawPrimitiveUP необходимо указать константу D3DPT_LINELIST. При этом следует заметить, что количество выводимых примитивов (второй параметр метода) будет в два раза меньше количества точек в массиве.
    • Для построения связных отрезков первым аргументом метода DrawPrimitiveUP указывается константа D3DPT_LINESTRIP. При этом количество выводимых примитивов будет на единицу меньше количества точек в исходном массиве данных.
  2. Вывод треугольников
    • Если первым аргументом метода DrawPrimitiveUP указывается константа D3DPT_TRIANGLELIST, то каждая триада (тройка) вершин задает три вершины одного (независимого) треугольника. Количества выводимых примитивов (треугольников) будет в три раза меньше чем размер массива данных.
    • Если первым аргументом метода DrawPrimitiveUP указывается константа D3DPT_TRIANGLESTRIP, то речь идет о группе связных треугольников. Первые три вершины задают первый треугольник, вторая, третья и четвертая определяют второй треугольник, третья, четвертая и пятая – третий и т.д. В результате получается лента соприкасающихся треугольников. Следует заметить, что использование связных треугольников самый экономный и эффективный способ построений.
    • Если первым аргументом метода DrawPrimitiveUP указывается константа D3DPT_TRIANGLEFAN, то строится группа связных треугольников, но данные здесь трактуются немного иначе. Треугольники связаны подобно раскрою зонтика или веера. По такой схеме удобно строить конусы и пирамиды в пространстве, выпуклые многоугольники и эллипсы в плоскости.

Все рассмотренные шесть видов примитивов по способу их построения можно представить в виде следующего рисунка:


В предыдущих примерах фигурировали бинарные примитивы (белые фигуры на черном фоне). Чтобы окрасить примитивы нужно задать цвет каждой вершины примитива. Это проделывается в два этапа. Сначала мы должны изменить тип вершины, а затем добавить в комбинацию флагов FVF значение D3DFVF_DIFFUSE.

C++
struct MYVERTEX
{
    FLOAT x, y, z, rhw;
    DWORD color;
}

#define MY_FVF (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
Pascal
type
    MyVertex = packed record
        x, y, z, rhw: Single;
        color: DWORD;
    end;

const
      MY_FVF = D3DFVF_XYZRHW or D3DFVF_DIFFUSE;

Далее каждой вершине необходимо присвоить некоторый цвет. Это можно проделать с помощью макроса-функции D3DCOLOR_XRGB(r, g, b), где в качестве параметров передается тройка основных цветов (веса) – красного, зеленого и синего. При этом, код, отвечающий за визуализацию сцены, не претерпит никаких изменений.

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


С одной стороны данная триангуляция имеет 10 треугольников, каждый из которых содержит 3 вершины. Таким образом, для хранения 30 вершин при расходах 20 байт на каждую вершину, необходимо 600 байт машинной памяти. С другой стороны, можно хранить отдельно сами вершины и список номеров (индексов) вершин для каждого треугольника. В этом случае расходы на машинную память будут следующими: 9 вершин по 20 байт на каждую потребует 180 байт, 10 триплетов индексов вершин, например, по 2 байта на индекс потребуют 60 байт. Итого для такой организации хранения данных модели – в нашем случае триангуляции, необходимо 240 байт, что в два с половиной раза меньше чем при организации хранения вершин всех десяти треугольников. Использование дополнительного массива, который будет хранить только лишь номера вершин модели, позволит избежать повторения данных при задании вершин. Так, например, представленная триангуляция может быть описана следующим образом.


10 треугольников = {

1: (0,3,2),

2: (0,1,3),

3: (2,3,4),

4: (3,6,4),

5: (1,5,3),

6: (3,5,6),

7: (1,7,5),

8: (5,7,6),

9: (6,7,8),

10: (4,6,8)

} = 2 байта/индекс*

3 индекса*

10 треугольников =

60 байт

Программно этот подход может быть реализован с помощью вызова метода DrawIndexedPrimitiveUP интерфейса IDirect3DDevice9, который имеет 8 параметров. Первый параметр задает тип выводимых примитивов и представляет собой одну константу из уже известного набора. Второй параметр определяет минимальный вершинный индекс и, как правило, он устанавливается в значение ноль. Третий параметр определяет количество вершин в модели. Четвертый параметр задает количество выводимых примитивов. Пятый аргумент метода представляет собой указатель на массив, содержащий набор индексов. Шестой аргумент определяет формат индексных данных и может принимать два значения: D3DFMT_INDEX16 и D3DFMT_INDEX32. Т.е. под один индекс может быть отведено либо 16, либо 32 бита машинной памяти. Предпоследний, седьмой аргумент метода представляет собой указатель на массив, содержащий набор вершин модели. И последний параметр определяет количество байтов, необходимых для хранения одной вершины. Таким образом, обобщив эти строки можно записать формат вызова данного метода:

DrawIndexedPrimitiveUP(
1. тип выводимых примитивов,
2. минимальный индекс вершин,
3. количество вершин,
4. количество выводимых примитивов,
5. указатель на массив индексов,
6. формат индексов,
7. указатель на массив вершин,
8. количество байтов для хранения одной вершины
)

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

C++
struct MYVERTEX
{
    FLOAT x, y, z, rhw;
    DWORD color;
}

#define MY_FVF (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

WORD indices[] = {0,3,2, 0,1,3, 2,3,4, 3,6,4, 1,5,3, 3,5,6, 
1,7,5, 5,7,6, 6,7,8, 4,6,8};

MYVERTEX points[] = 
{
    { 119, 354, 0, 0, D3DCOLOR_XRGB(255,0,0) },
    {  47, 248, 0, 0, D3DCOLOR_XRGB(0,255,0) },
    …
}
…
device-> DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 9, 10, 
indices, D3DFMT_INDEX16, points, sizeof(MYVERTEX) );
Pascal
type
    MyVertex = packed record
        x, y, z, rhw: Single;
        color: DWORD;
    end;

const
      MY_FVF = D3DFVF_XYZRHW or D3DFVF_DIFFUSE;
      indices: array [0..29] of Word =
      (0,3,2, 0,1,3, 2,3,4, 3,6,4, 1,5,3, 3,5,6, 
1,7,5, 5,7,6, 6,7,8, 4,6,8);

var points : array [0..8] of MyVertex;
…
  points[0].x := 119;
  points[0].y := 354;
  points[0].color := D3DCOLOR_XRGB(255,0,0);
…

device.DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 9, 10, 
indices, D3DFMT_INDEX16, points, SizeOf(MyVertex));

Результат построения триангуляции "с цветом" показан на следующем рисунке.


< Лекция 1 || Лекция 2: 123456 || Лекция 3 >