тел вращения и функционально заданных поверхностей

advertisement
Лабораторная работа №3
Визуализация трехмерных объектов в OpenGL. Построение тел вращения с
использованием OpenGL. Построение функционально заданных
поверхностей с помощью библиотеки GLUT.
Оглавление
1. Методы формирования моделей объемных объектов в виде тел
вращения. ...........................................................................................................1
2. Визуализация функционально заданных поверхностей в OpenGL .......11
1. Методы формирования моделей объемных объектов в виде тел
вращения.
Одним из способов формирования сложных объемных изображений на
экране является применение скелетных тел вращения. При этом выбирается
ось вращения и в одной плоскости с ней формируется кривая,
аппроксимируемая обычно последовательностью отрезков прямых линий. В
результате вращения кривой вокруг выбранной оси и фиксации положения
этой кривой через определенные отсчеты угла вращения создается скелетное
тело вращения.
Имея некоторую геометрию кривой, заданную рядом точек, мы можем
построить объект, основываясь на повороте геометрии данной кривой. Разбив
объект на N кривых и соединив их вершины, образовывая полигоны между
кривыми, мы получаем оболочку тела вращения.
Количество отрезков исходной кривой и количество разбиений
определяют гладкость объекта. Соответственно большое количество полигонов
– увеличивают нагрузку на графический адаптер.
Для построения трехмерного объекта с оболочкой необходимо рассчитать
нормали для определения полигонов.
Реализация алгоритма построения тел вращения с визуализацией на OpenGl
Создайте
окно
программы
и
разместите
на
ней
элемент
openglsimplecontrol, после чего установите его размеры 500х500.
Переименуйте данный объект, дав ему имя AnT.
Справа от данного элемента поместите элемент comboBox, после чего в
его
свойствах
установите
значение
параметра
DropDownStyle
=
DropDownList. После этого выпадающие элементы перестанут быть
доступными для редактирования. После этого измените элементы Items как
показано на рисунке.
Помимо этого установите элемент trackBar в окно формы. Перейдя к его
свойствам установите Orientation равным Vertical. Максимальный диапазон
установите равным ста.
Так же не забудьте установить ссылки на используемые библиотеки Tao.
Для реализации визуализации будет использоваться таймер – после
инициализации окна он будет генерировать событие, называемое тиком
таймера, раз в 30 миллисекунд – добавьте элемент таймер, переименуйте
экземпляр в RenderTimer и установите время тика 30 миллисекунд, а так же
добавьте ему событие для обработки тика.
Инициализация окна и OpenGl происходит, так же как и в предыдущей
работе.
Необходимо также объявить ряд переменных, для дальнейшей работы
программы:
Как и раньше, функция Form1_Load отвечает за инициализацию
OpenGL. Но теперь, помимо этого здесь происходит построение массива
геометрии тела, построенного вращением на основе заданного заранее массива
GeometricArray.
Итак, геометрия объекта построена, далее необходимо обработать
сообщение таймера для вызова функции отрисовки, а так же реализовать
непосредственно функцию Draw.
В функции Draw мы рассмотрим 3 вида визуализации, которые будут
использованы в зависимости от установленного режима в элементе comboBox.
Визуализация с помощью точек – самая простая.
Визуализация с помощью линий или полигонов – уже сложнее.
Постарайтесь максимально разобрать алгоритм, чтобы понять суть его работы.
На рисунках представлены результаты работы программы: вращающееся
тело с различными режимами отрисовки геометрии.
2. Визуализация функционально заданных поверхностей в OpenGL
Создайте
окно
программы
и
разместите
на
ней
элемент
openglsimplecontrol, после чего установите его размеры 500х500.
Переименуйте данный объект, дав ему имя AnT.
Справа от данного элемента поместите элемент comboBox, после чего в
его
свойствах
установите
значение
параметра
DropDownStyle
=
DropDownList. После этого выпадающие элементы перестанут быть
доступными для редактирования. После этого, измените элементы Items как
показано на рисунке.
Так же не забудьте установить ссылки на используемые библиотеки Tao.
Для реализации визуализации будет использоваться таймер – после
инициализации окна он будет генерировать событие, называемое тиком
таймера, раз в 30 миллисекунд – добавьте элемент таймер, переименуйте
экземпляр в RenderTimer и установите время тика 30 миллисекунд, а так же
добавьте ему событие для обработки тика.
Инициализация окна и OpenGl происходит, так же как и в предыдущей
работе в функции Form1_Load.
public Form1()
{
InitializeComponent();
AnT.InitializeContexts();
}
private void Form1_Load(object sender, EventArgs e)
{
// инициализация Glut
Glut.glutInit();
Glut.glutInitDisplayMode(Glut.GLUT_RGB | Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH);
// настройка параметров OpenGL для визуализации
Gl.glEnable(Gl.GL_CULL_FACE);
Gl.glCullFace(Gl.GL_BACK);
Gl.glFrontFace(Gl.GL_CCW);
// Запуск таймера
RenderTimer.Start();
}
private void RenderTimer_Tick(object sender, EventArgs e)
{
DrawSurface();
AnT.Invalidate();
}
В OpenGL отсутствуют средства визуализации кривых линий и
поверхностей, поэтому нам придется аппроксимировать их с помощью отрезков
прямых линий и треугольников.
Для начала, равномерно разобьем отображаемую область функции на
область N*M ячеек и вычислим значение функции в узлах сетки и используем
ее в качестве координаты z.
Далее соединим данные вершины при помощи лент из треугольников
(GL_TRIANGLE_STRIP):
В качестве альтернативы можно было бы соединить вершины в виде
набора вееров из треугольников (GL_TRIANGLE_FAN), но это потребовало бы
большего количества групп примитивов.
Для сокращения количества групп примитивов, можно «сшивать»
соседние ленты треугольников, добавляя пару дополнительных вершин в конце
каждой ленты для образования пары вырожденных треугольных граней для
смены направления обхода рядов ленты:
Такой прием позволит нарисовать всю сетку с помощью одной ленты из
треугольников, что положительно скажется на эффективности ее обработки
OpenGL.
Каждая вершина сетки будет характеризоваться координатами
нормалью. Для хранения данных параметров создадим структуру Vertex:
и
Теперь создадим класс CSincSurface, который будет визуализировать
трехмерный вариант функции sinc:
где
√
Методы Sinc и F в более подробном описании не нуждаются. А вот про
метод CalculateVertex стоит рассказать поподробнее.
Сначала мы вычисляем координату z по формуле из задания. На этом
можно было бы остановиться, но нам необходимо вычислить вектор нормали к
поверхности в точке (x, y, z). Для поверхностей, заданных в виде направление
вектора нормали будет совпадать с вектором антиградиента данной функции в
точке (x, y, z).
Вектор антиградиента – вектор, обратный вектору частных производных
функции F.
Вычислить вектор частных производных можно было бы аналитически,
выполнив дифференцирование функции F по dx, dy и dz, однако вычисления
получились бы достаточно громоздкими. В нашем случае нас устроит
приблизительное (хотя и достаточно близкое) вычисление производной по ее
определению:
«Производная равна отношению приращения функции к приращению
аргумента, при приращении аргумента стремящемуся к нулю». В нашем случае
«стремящееся к нулю» число можно представить как просто «достаточно
маленькое число», например, 10-6. Здесь нам пригодятся числа с плавающей
запятой двойной точности.
Метод
рисования
полигональной
сетки,
аппроксимирующей
функционально заданную поверхность, воплощает ранее описанный подход к
ее построению с помощью лент из треугольников. Для повышения
быстродействия, все же, воспользуемся дисплейными списками OpenGL для
записи и последующего воспроизведения команд рисования поверхности.
Для управления свойствами материала используем функцию SetupMaterial()
Для управления источниками света используем функцию SetupLight()
Для анимации в виде вращения поверхности используем функцию
SetupCamera()
Далее соберем элементы программы в функцию рисования поверхности.
Собрав все воедино,
трехмерной
поверхности
представлениями.
мы
с
получим анимированную визуализацию
возможностью
переключения
между
Download