Навигация
Категории
C++,C#,C [19]
Уроки по средам разработки приложений с использованием C,C++,C#, а также .Net, DirectX, OpenGL и других
Delphi [14]
Уроки работы в среде программирования Delphi
Basic [13]
Уроки разработки приложений в среде Basic
DirectX [8]
Уроки по работе с DirectX, включая Direct3D и другие инструменты
Web [7]
Уроки по "Веб-программированию"
JavaScript [12]
Уроки по кодингу в Java и JavaScript
XNA [9]
Статьи и уроки программирование в среде XNA C++&C#
Профиль
Статистика
Rambler's Top100

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Locations of visitors to this page
Главная » Статьи » Программирование » XNA

Урок 8. Как рисовать точки, линии и другие 3D примитивы

Урок 8. Как рисовать точки, линии и другие 3D примитивы.


В этом уроке мы рассмотрим, как можно нарисовать  простейшие примитивы (точки, линии, треугольники).  Это дословный перевод статьи из MSDN - How To: Draw Points, Lines, and Other 3D Primitives.

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

Пометка – для простейшей отрисовки примитивов, кроме координат, вам необходимо создать экземпляр объекта BasicEffect а так же несколько матриц трансформации. Ссылки по теме - How To: Use BasicEffect, и на нашем сайте - Как рисовать простые 3D-объекты с помощью BasicEffect.

Исходный код примера можно загрузить с сайта Microsoft или с нашего сайта (отличается только русскими комментариями)

Рисуем точки

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()

1
2
3
4
5
6
7
8
9
10
11
12
viewMatrix = Matrix.CreateLookAt(
new Vector3(0.0f, 0.0f, 1.0f),
Vector3.Zero,
Vector3.Up
);
 
projectionMatrix = Matrix.CreateOrthographicOffCenter(
0,
(float)GraphicsDevice.Viewport.Width,
(float)GraphicsDevice.Viewport.Height,
0,
1.0f, 1000.0f);

 



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 = new short[(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-ми точек.

lineListIndices = new short[14]{ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7 };

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 = new short[points];
 
// заполняем индексы последовательно соеденяя одну точку за другой
for (int i = 0; i < points; i++)
{
lineStripIndices[i] = (short)(i);
}
 

 


Или так –

lineStripIndices = new short[8]{ 0, 1, 2, 3, 4, 5, 6, 7 };

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 = new short[(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 точки у нас образуют один треугольник, причем в каждом треугольнике есть общие вершины с соседним. Ниже аналог этого кода –

triangleListIndices = new short[18]{ 0, 1, 2, 2, 1, 3, 2, 3, 4, 4, 3, 5, 4, 5, 6, 6, 5, 7 };

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 = new short[points];
 
// заполняем индексы
for (int i = 0; i < points; i++)
{
triangleStripIndices[i] = (short)i;
}

 



В лентах, треугольники полседовательно соеденены между собой, так что индесов нам нужно меньше – каждый полседующий треугольник использыет две вершины предидущего треугольника. Это самый эффетивный способ вывда треугольников.

Аналог кода создания индексов –

triangleStripIndices = new short[8]{ 0, 1, 2, 3, 4, 5, 6, 7 };

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;
 

 



В этом коде мы так же с начала меняем цвет вершин перед отрисовкой.

В заключение приведем схему индексации различных примитивов (еще называют топологией примитивов)



Источник: http://www.xnadev.ru/articles.php?article_id=49
Категория: XNA | Добавил: gforcer (31.01.2010) | Автор: Админ
Просмотров: 5297 | Комментарии: 2 | Теги: xna, C#, c++ | Рейтинг: 0.0/0
Всего комментариев: 1
1 Жека  
0
Здравствуйте!
А уроки будут продолжаться или это всё??

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск
Друзья сайта
Демотиваторы
Copyright Зямаев Денис © 2024