Урок 8. Как рисовать точки, линии и другие 3D примитивы
Урок 8. Как рисовать точки, линии и другие 3D примитивы.
В этом уроке мы рассмотрим, как можно нарисовать простейшие примитивы (точки, линии, треугольники).
В XNA Framework, 3D примитив это специальный тип 3D объекта, который определяет, как графическое устройство интерпретирует вершины в вершинном буфере. Мы приведем пример, как использовать точки, линии и треугольники, являющиеся основой рисования на самом низком уровне.
Пометка – для простейшей отрисовки примитивов, кроме координат, вам необходимо создать экземпляр объекта BasicEffect а так же несколько матриц трансформации. Ссылки по теме How To: Use BasicEffect, и на нашем сайте - Как рисовать простые 3D-объекты с помощью BasicEffect.
Рисуем точки
1. Нужно создать список 3D вершин, которые определяют рисуемые точки.
Следующий код создает 8 точек и сохраняет их в массиве VertexPositionColor[] pointList;
1
2
3
4
5
6
7
8
9
10
pointList =new VertexPositionColor[points];for(int x =0; x < points /2; x++){for(int y =0; y <2; y++){ pointList[(x *2)+ y]=new VertexPositionColor(new Vector3(x *100, y *100, 0), Color.White);}}
Визуально точки будут выглядеть так -
На рисунке показаны 8 точек определяющих 6 треугольников нарисованных на плоскости Z (z=0). Координаты первой точки = (0,0,0). Камера размещена в точке (0,0,1) и смотрит на начало координат (0,0,0). Ортогональная проекция задана двумя точками – верхняя-левая (0,0) и нижняя-правая (800,600). Кроме этого мы используем дополнительную матрицу трансформации, которая смещает наши точки к центру экрана. Следующий код показывает создание 2-ух из 3-ех необходимых нам матриц. 3-яя матрица (мировая) для смещения точек к центру экрана создается в методе InitializeEffect()
2. Используя свойство GraphicsDevice.RenderState.PointSize установим размер выводимых точек.
В нашем примере размер равен 10. На экране вы увидите квадратные точки.
GraphicsDevice.RenderState.PointSize = 10;
3. Выводим точки на экран используя функцию GraphicsDevice.DrawUserPrimitives(..) которая в качестве первого аргумента принимает тип выводимого примитива - PrimitiveType.PointList. Тип примитива определяет как данные в переданном массиве вершин будут интерпретированы и показаны.
1
2
3
4
5
GraphicsDevice.DrawUserPrimitives<VertexPositionColor>( PrimitiveType.PointList, // тип примитива для отрисовки pointList, // массив точек0, // индекс первой используемой вершины в массиве8);// количество примитивов (точек)
Рисуем линии
1. В дополнение к списку 3D вершин точек нужно создать массив индексов для нумерации/индексации данных о вершинах.
Нижеприведенный код определяет индексы для серии линий
1
2
3
4
5
6
7
8
9
10
// массив индексов для линий lineListIndices =newshort[(points *2)-2];// заполняем индексыfor(int i =0; i < points -1; i++){ lineListIndices[i *2]=(short)(i); lineListIndices[(i *2)+1]=(short)(i +1);}
Другими словами, данный код равнозначен следующему и определяет линии соеденяющие наши точки - pointList[0] и pointList[1], pointList[1] и pointList[2], и так далее 7 линий между 8-ми точек.
2. Выводим линии на экран используя функцию GraphicsDevice.DrawUserIndexedPrimitives (..) которая в качестве первого аргумента принимает тип выводимого примитива - PrimitiveType. LineList
1
2
3
4
5
6
7
8
GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>( PrimitiveType.LineList, // тип примитива для отрисовки pointList, // массив точек0, // смещение, добавляемое для каждого индекса в индексном буфере8, // количество вершин lineListIndices, // индексный буфер соеденяющий наши точки по парам0, // первый используемый индекс7);// количество примитивов (линий)
Рисуем ленту линий (Line Strip)
1. Для определения ленты из линий нам понадобится новый массив индексов в котором последовательно будут соеденены точки из массива вершин.
Для ленты нам понадобится в двое меньше индексов так как лента подразумевает последовательно соединенные примитивы (точки).
1
2
3
4
5
6
7
8
9
// массив индексов для линий lineStripIndices =newshort[points];// заполняем индексы последовательно соеденяя одну точку за другойfor(int i =0; i < points; i++){ lineStripIndices[i]=(short)(i);}
2. Выводим ленту линий на экран используя функцию GraphicsDevice.DrawUserIndexedPrimitives (..) которая в качестве первого аргумента принимает тип выводимого примитива - PrimitiveType. LineStrip. Пометка – рисование лент обычно более эффективно чем рисование списков - с точки зрения производительности, так как индексы выводимых вершин содержат меньшее количество повторений.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
for(int i =0; i < pointList.Length; i++) pointList[i].Color= Color.Red;GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>( PrimitiveType.LineStrip, // тип примитива для отрисовки pointList, // массив точек0, // смещение, добавляемое для каждого индекса в индексном буфере8, // количество вершин для отрисовки lineStripIndices, // массив индесов (последовательность точек)0, // первый используемый индекс7);// количество примитивов (линий)for(int i =0; i < pointList.Length; i++) pointList[i].Color= Color.White;
В этом примере мы сначала устанавливаем цвет точек в красный и затем рисуем, после чего меняем цвет точек обратно. Ленты рисуются красным цветом, а списки цветом по умолчанию – белым.
Рисуем треугольники
1. Создаем новый массив индексов, в котором будет пронумерованный список треугольников, по 3 вершины на один треугольник. Массив вершин не меняем.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
triangleListIndices =newshort[(width -1)*(height -1)*6];for(int x =0; x < width -1; x++){for(int y =0; y < height -1; y++){ triangleListIndices[(x + y *(width -1))*6]=(short)(2* x); triangleListIndices[(x + y *(width -1))*6+1]=(short)(2* x +1); triangleListIndices[(x + y *(width -1))*6+2]=(short)(2* x +2); triangleListIndices[(x + y *(width -1))*6+3]=(short)(2* x +2); triangleListIndices[(x + y *(width -1))*6+4]=(short)(2* x +1); triangleListIndices[(x + y *(width -1))*6+5]=(short)(2* x +3);}}
Этот код индексирует вершины так что каждые 3 точки у нас образуют один треугольник, причем в каждом треугольнике есть общие вершины с соседним. Ниже аналог этого кода –
2. Выводим список треугольников на экран используя функцию GraphicsDevice.DrawUserIndexedPrimitives (..) которая в качестве первого аргумента принимает тип выводимого примитива - PrimitiveType.TriangleList
1
2
3
4
5
6
7
8
9
GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>( PrimitiveType.TriangleList, // тип примитива для отрисовки pointList, // массив точек0, // смещение, добавляемое для каждого индекса в индексном буфере8, // количество вершин для отрисовки triangleListIndices, // массив индесов0, // первый используемый индекс6);// количество примитивов (треугольников)
Рисуем ленту из треугольников (TriangleStrip)
1. Для ленты из треугольников мы так же используем наш старый массив вершин но создаем новый массив индексов в котором будут последовательно соеденены точки в треугольники.
1
2
3
4
5
6
7
8
// массив индексов для треугольников triangleStripIndices =newshort[points];// заполняем индексыfor(int i =0; i < points; i++){ triangleStripIndices[i]=(short)i;}
В лентах, треугольники полседовательно соеденены между собой, так что индесов нам нужно меньше – каждый полседующий треугольник использыет две вершины предидущего треугольника. Это самый эффетивный способ вывда треугольников.
2. Выводим ленту треугольников на экран используя функцию GraphicsDevice.DrawUserIndexedPrimitives (..) которая в качестве первого аргумента принимает тип выводимого примитива - PrimitiveType.TriangleStrip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for(int i =0; i < pointList.Length; i++) pointList[i].Color= Color.Red;GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>( PrimitiveType.TriangleStrip, // тип примитива для отрисовки pointList, // массив точек0, // смещение, добавляемое для каждого индекса в индексном буфере8, // количество вершин для отрисовки triangleStripIndices, // массив индесов0, // первый используемый индекс6);// количество примитивов (треугольников)for(int i =0; i < pointList.Length; i++) pointList[i].Color= Color.White;
В этом коде мы так же с начала меняем цвет вершин перед отрисовкой.
В заключение приведем схему индексации различных примитивов (еще называют топологией примитивов)
1370 Прочтений • [Урок 8. Как рисовать точки, линии и другие 3D примитивы] [08.08.2012] [Комментариев: 0]