| Китай |
Рендеринг вращающихся кубов в DirectX
Создание вращающегося куба
Смоделируем куб, показанный на рисунке
У нашего куба будет 6 граней. Для представления каждой грани двумя треугольниками потребуется всего 12 треугольников, каждый из которых будет описываться 3 вершинами. Итого, для полного описания куба нужно задать координаты 36 вершин для аппроксимирующих треугольников.
-
В
панели Solution Explorer вызовите контекстное меню для
файла Form1.cs и выполните команду View Code
-
В
верхней части рабочей области редактора раскройте правый
список Members и позиционируйтесь на функции vb_Created(),
которую перепишите следующим
образом
void vb_Created(object sender, EventArgs e)
{
// Определить внутреннюю ссылку на вершинный буфер
VertexBuffer buffer = (VertexBuffer)sender; // Явное приведение типов
// Создать локальный массив структур непреобразованных координат
CustomVertex.PositionColored[] verts = new
CustomVertex.PositionColored[36];
// Задать параметры аппроксимирующих треугольников
// Порядок обхода вершин для лицевой стороны правый
// (по часовой стрелке), для невидимой - левый
//
// Задняя грань: треугольник 2-0-1 (невидимая сторона - обход левый)
verts[0] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Red.ToArgb());
verts[1] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Red.ToArgb());
verts[2] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Red.ToArgb());
// Задняя грань: треугольник 2-1-3 (невидимая сторона - обход левый)
verts[3] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Red.ToArgb());
verts[4] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Red.ToArgb());
verts[5] = new CustomVertex.PositionColored(1.0F, -1.0F, 1.0F, Color.Red.ToArgb());
//
// Передняя грань: треугольник 5-6-4 (лицевая сторона - обход правый)
verts[6] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Blue.ToArgb());
verts[7] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Blue.ToArgb());
verts[8] = new CustomVertex.PositionColored(-1.0F, 1.0F, -1.0F, Color.Blue.ToArgb());
// Передняя грань: треугольник 5-7-6 (лицевая сторона - обход правый)
verts[9] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Blue.ToArgb());
verts[10] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Blue.ToArgb());
verts[11] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Blue.ToArgb());
//
// Верхняя грань: треугольник 0-5-4 (лицевая сторона - обход правый)
verts[12] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Yellow.ToArgb());
verts[13] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Yellow.ToArgb());
verts[14] = new CustomVertex.PositionColored(-1.0F, 1.0F, -1.0F, Color.Yellow.ToArgb());
// Верхняя грань: треугольник 0-2-5 (лицевая сторона - обход правый)
verts[15] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Yellow.ToArgb());
verts[16] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Yellow.ToArgb());
verts[17] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Yellow.ToArgb());
//
// Нижняя грань: треугольник 1-6-7 (невидимая сторона - обход левый)
verts[18] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Black.ToArgb());
verts[19] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Black.ToArgb());
verts[20] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Black.ToArgb());
// Нижняя грань: треугольник 1-7-3 (невидимая сторона - обход левый)
verts[21] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Black.ToArgb());
verts[22] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Black.ToArgb());
verts[23] = new CustomVertex.PositionColored(1.0F, -1.0F, 1.0F, Color.Black.ToArgb());
//
// Левая грань: треугольник 0-6-1 (невидимая сторона - обход левый)
verts[24] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Gray.ToArgb());
verts[25] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Gray.ToArgb());
verts[26] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Gray.ToArgb());
// Левая грань: треугольник 0-4-6 (невидимая сторона - обход левый)
verts[27] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Gray.ToArgb());
verts[28] = new CustomVertex.PositionColored(-1.0F, 1.0F, -1.0F, Color.Gray.ToArgb());
verts[29] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Gray.ToArgb());
//
// Правая грань: треугольник 2-3-7 (лицевая сторона - обход правый)
verts[30] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Green.ToArgb());
verts[31] = new CustomVertex.PositionColored(1.0F, -1.0F, 1.0F, Color.Green.ToArgb());
verts[32] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Green.ToArgb());
// Правая грань: треугольник 2-7-5 (лицевая сторона - обход правый)
verts[33] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Green.ToArgb());
verts[34] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Green.ToArgb());
verts[35] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Green.ToArgb());
// Заполнить вершинный буфер данными треугольников
buffer.SetData(verts, 0, LockFlags.None);
}
Листинг
12.3.
Задание вершин аппроксимирующих треугольников в функции vb_Created()
Координаты вершин треугольников заданы в соответствии с рисунком. Теперь нужно привести в соответствие новой задачи и остальной код программы.
-
Через
раскрывающийся список Members найдите в функции InitializeGraphics() код
создания вершинного буфера и измените количество вершин
аппроксимирующих треугольников с 3 на 36
// Создать вершинный буфер
vb = new VertexBuffer(typeof(CustomVertex.PositionColored),
36,
device,
Usage.Dynamic | Usage.WriteOnly,
CustomVertex.PositionColored.Format,
Pool.Default);
Листинг
12.4.
Изменить количество вершин в вершинном буфере
Мы моделируем объемную фигуру и нам не нужно делать видимой обратную сторону каждой плоской грани, как это было с треугольником, поэтому отключим эту возможность Direct3D.
-
Найдите
функцию SetupCamera() и закомментируйте
в ней следующий код
// Не скрывать обратную сторону плоской фигуры
// device.RenderState.CullMode = Cull.None;
Листинг
12.5.
Скрывать по умолчанию обратную сторону каждой грани куба
Изменим характер вращения куба, чтобы получить более эффективную картинку.
-
Найдите
в конце функции SetupCamera() секцию кода
преобразования координат объекта и замените его на следующую
// Преобразование пространства для произвольных поворотов
/*
device.Transform.World = Matrix.RotationAxis(
new Vector3(angle / ((float)Math.PI * 2.0F),
angle / ((float)Math.PI * 4.0F),
angle / ((float)Math.PI * 6.0F)),
angle / (float)Math.PI);
*/
device.Transform.World = Matrix.RotationYawPitchRoll(
angle / (float)Math.PI,
angle / (float)Math.PI * 2.0F,
angle / (float)Math.PI);
angle += 0.1F;
Листинг
12.6.
Изменяем характер вращения куба в функции SetupCamera()
Здесь мы применили для поворота куба статический метод RotationYawPitchRoll() структуры Microsoft.DirectX.Matrix
RotationYawPitchRoll(float yaw, float pitch, float roll)
где yaw -отклонение, pitch -шаг, roll -поворот.
Мы рисуем в данном приложении 12 примитивов-треугольников, поэтому нужно установить это количество в функции рисования DrawPrimitives() устройства.
-
Найдите
в методе OnPaint() секцию кода " Сформировать
сцену..." и установите в ней нужную размерность
примитивов рисования
// Сформировать сцену с учетом параметров
// "положение-нормаль-цвет"
device.BeginScene();
// Установить формат обработки вершин при отображении
device.VertexFormat = CustomVertex.PositionColored.Format;
// Нарисовать треугольник по данным из буфера
device.SetStreamSource(0, vb, 0);
device.DrawPrimitives(PrimitiveType.TriangleList, 0, 12);
device.EndScene();
Листинг
12.7.
Новое количество отображаемых треугольных примитивов в функции OnPaint()
-
Постройте
приложение и убедитесь, что рисуется вращающийся куб с
цветными гранями


