В этом большом разделе вы познакомитесь со всеми примитивами библиотеки OpenGL, их атрибутами и многими командами, управляющими выводом примитивов на экран.
Модуль 0. Точки
Точка является простейшим примитивом OpenGL. Она обладает рядом атрибутов. Это размер, сглаживаемость, цвет, положение.
Комплексной целью модуля является изучение следующих элементов OpenGL
-
Атрибуты точки
-
Цвет, маска цвета
-
Альфа-тестирование
-
Системы координат в OpenGL
-
Тест глубины
-
Дисплейные списки
-
Вывод символов
Методы Begin, End. Вершины. Примитив POINTS
Построение примитива в OpenGL требует выполнения ряда обязательных команд. К ним относятся
-
"Команды-скобки" Begin и End, внутри которых примитив строится путем перечисления его вершин. Команда Begin имеет параметр, определяющий тип примитива.
-
Команды Vertex, определяющие расположения вершин строящегося примитива.
На форме f3D создайте главное меню. Для этого
-
Откройте окно дизайна f3D
-
Войдите в окно ToolBox.
-
Найдите раздел Menus & Toolbars
-
Найдите в нем класс MenuStrip
-
Перенесите объект этого класса на верхнюю панель TopToolStripPanel объекта toolStripContainer1.
-
Дайте ему имя (свойство Name в окне Properties) menuStrip
В появившемся окошке названия меню наберите текст Primitives. В окошке ниже наберите Points. Это будет первая команда меню Primitives. В появившемся окошке подменю, справа от Points наберите текст "One point". Это будет первая команда меню "Points".
Дальнейшее изложение будет предполагать использование "театральной" терминологии. Каждое меню ( в данном случае это меню с текстом "Primitives") будет соответствовать действию спектакля (action), команда меню (в данном случае "Points") – акту данного действия спектакля (act), и, наконец, команда подменю (в данном случае "One point") будет обозначать сцену спектакля (scene) в данном акте и данном действии. При выборе каждой команды подменю приложение воспроизводит сцену, инициализируя свойства (атрибуты) тех объектов, которые в ней участвуют.
На этом этапе в коде формы f3D проведите следующую редакцию
#region Методы инициализации
void InitSceneAttributes()
{
#region Init Common Controls&Fields
stLabel.Text = string.Empty;
#endregion
}
#endregion
-
В раздел "Рабочие поля и свойства" введите описание
///
/// Хранит текст выбранной команды подменю (имя сцены)
///
string SceneName;
///
/// Устанавливает и возвращает текущий индекс подменю (номер сцены)
///
public static int SceneNmb
{
private set;
get;
}
///
/// Хранит текст выбранной команды меню (имя акта)
///
string ActName;
///
/// Устанавливает и возвращает текущий индекс команды меню (номер акта)
///
public static int ActNmb
{
private set;
get;
}
///
/// Хранит текст текущего раздела главного меню (имя действия)
///
string ActionName;
///
/// Устанавливает и возвращает текущий индекс главного меню (номер действия)
///
public static int ActionNmb
{
private set;
get;
}
-
В раздел "Методы воспроизведения" добавьте новый метод RenderScene, который устанавливает в заголовок формы имена и номера действия, акта и сцены, вызывает инициализатор сцены InitSceneAttributes и, наконец, вызывает отображение начального фрейма сцены на экране RenderFrame
void RenderScene()
{
Text = ActionName + " (" + ActionNmb.ToString() + "): " +
ActName + " (" + ActNmb.ToString() + "): " + SceneName + " (" + SceneNmb.ToString() + ")";
InitSceneAttributes();
RenderFrame();
}
-
Добавьте раздел "Главное меню" и в нем опишите метод, который будет использоваться как обработчик события вызова команд подменю. Операторы обработчика определяют имена и номера действия, акта и сцены и вызывают метод RenderScene
#region Главное меню
private void subMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
SceneName = e.ClickedItem.Text;
SceneNmb = (sender as ToolStripMenuItem).DropDownItems.IndexOf(e.ClickedItem);
ActName = (sender as ToolStripMenuItem).Text;
ActNmb = (sender as ToolStripMenuItem).Owner.Items.IndexOf(sender as ToolStripMenuItem);
ActionName = (sender as ToolStripMenuItem).OwnerItem.Text;
ActionNmb = menuStrip.Items.IndexOf((sender as ToolStripMenuItem).OwnerItem);
RenderScene();
}
#endregion
-
Присоедините метод subMenuItem_DropDownItemClicked к событию DropDownItemClicked команды "Points" (именно "Points", а не "One point"!!). Для этого
-
в окне Properties найдите объект pointsToolStripMenuItem
-
в этом же окне перейдите на страницу событий (значок молнии) и найдите событие DropDownItemClicked
-
добавьте из выпадающего списка обработчик subMenuItem_DropDownItemClicked.
-
Добавьте в раздел "Методы воспроизведения" описание нового, пока пустого метода с именем SetCurPointsActAttr:
void SetCurPointsActAttr()
{
}
-
Добавьте в конец тела метода BuildFrame формы f3D оператор
// Построение изображения
switch (ActName)
{
case "Points":
#region Points
SetCurPointsActAttr();
#region Puppets
switch (SceneName)
{
case "One point": //0
break;
}
#endregion
#endregion
break;
}
В разделе (#region) "Points" будут находиться операторы, строящие изображения сцен из акта "Points". В метод SetCurPointsActAttr (пока пустой) будут помещаться операторы, устанавливающие текущие параметры участников акта "Points" в зависимости от сцены. Будем считать спектакль кукольным и назовем участников спектакля куклами, или марионетками (puppets). В раздел "Puppets" в зависимости от сцены будут помещаться операторы, строящие изображение куклы – геометрического объекта, воспроизводимого на экране.
Основой построения примитивов в OpenGL является так называемая вершина (vertex). Под вершинами понимаются именно вершины простых геометрических фигур – треугольника, четырехугольника, многоугольника. У отрезка прямой – две вершины, у точки – одна. Вызывать методы Vertex можно только между двумя последовательными вызовами методов Begin и End. При этом аргумент метода Begin определяет, к какому типу примитивов вызываемая вершина относится. Внимательно ознакомьтесь с комментариями в описании этих методов.
Перейдите к файлу библиотеки GL.cs и в класс gl добавьте описание примитивов и методов, с помощью которых они изображаются
#region Постоянные примитивов
///
/// Рассматривает каждую вершину, как отдельную точку
///
public const int POINTS = 0x0000;
///
/// Рассматривает каждую пару вершин как независимый отрезок прямой.
/// Вершины 2n - 1 и 2n определяют прямую n.
/// Изображается N/2 прямых, где N - полное число вершин.
///
public const int LINES = 0x0001;
///
/// Изображает связанную группу отрезков прямых от первой до последней вершины,
/// затем назад - к первой вершине.
/// Вершины n и n+1 определяют прямую n. Последняя прямая определяется вершинами N и 1.
/// Изображается N прямых, где N - полное число вершин.
///
public const int LINE_LOOP = 0x0002;
///
/// Изображает связанную группу отрезков прямых от первой до последней вершины.
/// Вершины n и n+1 определяют прямую n.
/// Изображается N - 1 прямая, где N - полное число вершин.
///
public const int LINE_STRIP = 0x0003;
///
/// Рассматривает каждый триплет вершин, как независимый треугольник.
/// Вершины 3n - 2, 3n-1 и 3n определяют треугольник n.
/// Изображается N/3 треугольников, где N - полное число вершин.
///
public const int TRIANGLES = 0x0004;
///
/// Изображает связанную группу треугольников.
/// Один треугольник определен для каждой вершины после первых двух вершин.
/// Для нечетных n, вершины n, n+1 и n+2 определяют треугольник n.
/// Для четных n, вершины n+1, n и n+2 определяют треугольник n.
/// Изображается N - 2 треугольника, где N - полное число вершин.
///
public const int TRIANGLE_STRIP = 0x0005;
///
/// Изображает связанную группу треугольников.
/// Один треугольник определен для каждой вершины после первых двух вершин.
/// Вершины 1, n+1 и n+2 определяют треугольник n.
/// Изображается N - 2 треугольника, где N - полное число вершин.
///
public const int TRIANGLE_FAN = 0x0006;
///
/// Рассматривает каждую группу из четырех вершин, как независимый четырехугольник.
/// Вершины 4n - 3, 4n - 2, 4n - 1 и 4n определяют четырехугольник n.
/// Изображается N/4 четырехугольника, где N - полное число вершин.
///
public const int QUADS = 0x0007;
///
/// Изображает связанную группу четырехугольников.
/// Один четырехугольник определен для каждой пары вершин после первой пары.
/// Вершины 2n - 1, 2n, 2n+2 и 2n+1 определяют четырехугольник n.
/// Изображается N четырехугольника, где N - полное число вершин.
/// Заметьте, что порядок используемых вершин
/// для построения четырехугольника в данном примитиве
/// отличается от того, что используется при построении независимых четырехугольников.
///
public const int QUAD_STRIP = 0x0008;
///
/// Изображает один выпуклый многоугольник.
/// Вершины от 1 до N определяют этот многоугольник.
///
public const int POLYGON = 0x0009;
#endregion
#region Методы Begin, End, Vertex
///
/// Begin и End ограничивают вершины примитива или группы примитивов одного типа
///
///
/// Определяет примитив или примитивы, которые будут созданы из вершин, представленных
/// между вызовом Begin и последующим вызовом End.
/// В качестве значений доступны десять символических постоянных:
/// POINTS, LINES, LINE_STRIP, LINE_LOOP, TRIANGLES,
/// TRIANGLE_STRIP, TRIANGLE_FAN, QUADS, QUAD_STRIP и POLYGON.
///
[DllImport("OPENGL32.DLL", EntryPoint = "glBegin")]
public static extern void Begin(int mode);
///
/// Begin и End ограничивают вершины примитива или группы примитивов одного типа.
///
[DllImport("OPENGL32.DLL", EntryPoint = "glEnd")]
public static extern void End();
///
/// Методы Vertex используются внутри пары Begin/End
/// для определения положения вершин точки, линии и многоугольника.
/// Текущий цвет, направление нормали и координаты текстуры ассоциируются с вершиной,
/// когда вызывается Vertex.
/// Если заданы только две координаты, то это x и y, при этом z по умолчанию равна 0.0
/// и четвертая координата (масштаб) w по умолчанию равна 1.0.
///
[DllImport("OPENGL32.DLL", EntryPoint = "glVertex2f")]
public static extern void Vertex(float x, float y);
///
/// Методы Vertex используются внутри пары Begin/End
/// для определения положения вершин точки, линии и многоугольника.
/// Текущий цвет, направление нормали и координаты текстуры ассоциируются с вершиной,
/// когда вызывается Vertex.
/// Если заданы три координаты x, y и z, то координата w по умолчанию равна 1.0.
///
[DllImport("OPENGL32.DLL", EntryPoint = "glVertex3f")]
public static extern void Vertex(float x, float y, float z);
///
/// Методы Vertex используются внутри пары Begin/End
/// для определения положения вершин точки, линии и многоугольника.
/// Текущий цвет, направление нормали и координаты текстуры ассоциируются с вершиной,
/// когда вызывается Vertex.
///
[DllImport("OPENGL32.DLL", EntryPoint = "glVertex4f")]
public static extern void Vertex(float x, float y, float z, float w);
#endregion
Вернувшись к методу BuildFrame формы f3D, вставьте в раздел "Points" операторы, позволяющие изобразить одну точку. Так, что весь метод BuildeFrame примет вид
void BuildFrame()
{
// Очистка буфера цвета
gl.Clear(gl.COLOR_BUFFER_BIT);
// Построение изображения
switch (ActName)
{
case "Points":
#region Points
SetCurPointsActAttr();
#region Puppets
switch (SceneName)
{
case "One point": //0
gl.Begin(gl.POINTS);
gl.Vertex(0, 0);
gl.End();
break;
}
#endregion
#endregion
break;
}
}
Активируйте проект и убедитесь, что в центре панели появилась белая точка. Результат должен быть такой же, как здесь.
Тест рубежного контроля
-
Что такое примитив в терминологии OpenGL?
-
Для чего служат методы Begin, End?
-
Какой аргумент должен принимать метод Begin для изображения точек?
-
Что делает метод Vertex?
-
Какие версии метода Vertex описаны в этом разделе?
Что дальше.
Точка может иметь размеры, цвет, изображаться в форме квадрата или круга. Как регулировать эти атрибуты?
Достарыңызбен бөлісу: |