
Лабораторные работа 5.ppt
- Количество слайдов: 105
Лабораторная работа 5 «Вычислители и NURBS »
Теоретические основы
На самом низком уровне графическая аппаратура рисует только точки, сегменты линий и полигоны, которые обычно являются треугольниками или четырехугольниками.
Плавные кривые и поверхности рисуются с помощью аппроксимаций большим числом маленьких сегментов линий или полигонов.
Множество полезных кривых и поверхностей могут быть математически описаны небольшим числом параметров, например, несколькими контрольными точками.
Сохранение 16 контрольных точек для поверхности требует значительно меньше места в памяти, чем сохранение 1000 треугольников вместе с вектором нормали для каждой вершины.
Кроме того, 1000 треугольников всего лишь аппроксимирует поверхность, а контрольные точки определяют ее истинную форму.
Вычислители (evaluators) предоставляют возможность задать точки кривой или поверхности (или их частей) используя только контрольные точки. Затем кривая или поверхность может быть визуализирована с любой точностью.
Вектора нормалей для поверхностей могут быть вычислены автоматически. Точки, сгенерированные вычислителем можно использовать по-разному – чтобы нарисовать часть точек поверхности, чтобы нарисовать ее каркасный вариант или чтобы отобразить полностью освещенную, закрашенную и даже текстурированную поверхность.
Задание нормалей вершин для объекта с плоскими гранями
Задание нормалей вершин примитивов, аппроксимирующих криволинейную поверхность
Пример 5. 1 Одномерные вычислители. Вывод изображения кубической кривой Безье с использование четырёх контрольных точек.
Кривая Безье – это векторная функция одной переменно. Й. где u изменяется в некотором диапазоне (например [0, 1]).
GL_SHADE_MODEL Режим закраски
Кубическая кривая Безье описывается 4 точками, которые фигурируют в примере в виде массива ctrlpoints[][]. Этот массив является одним из аргументов для команды gl. Map 1 f(). Полный список аргументов для этой команды следующий:
Второй и третий аргументы команды управляют параметризацией кривой – в то время как uзменяется от 0. 0 до 1. 0, кривая проходит от своего начала до своего конца. Вызов команды gl. Enable() активизирует одномерный вычислитель для трехмерных вершин.
Команда gl. Map 1() определяет одномерный вычислитель, использующий данные уравнения.
Аргумент target определяет, что именно задается контрольными точками (смотрите таблицу 1) и, как следствие, сколько величин должно быть задано в аргументе points.
Таблица 1. Типы контрольных точек для gl. Map 1*()
Например, если задать для target значение GL_MAP 1_COLOR_4, вычислитель генерирует цветовые данные в четырехмерном RGBA пространстве вдоль кривой.
Величины параметров, перечисленные в таблице 1, также используются для активизации конкретного вычислителя до его вызова. Чтобы активизировать или деактивировать нужный вычислитель, необходимо передать соответствующий аргумент командам gl. Enable() или gl. Disable() соответственно.
Два параметра gl. Map 1*() – u 1 и u 2 задают диапазон изменения переменной u. Аргумент stride– это количество величин с плавающей точкой одинарной или двойной точности в каждом блоке хранилища, то есть это величина смещения между началом предыдущей контрольной точки и началом следующей.
Аргумент order – это степень кривой плюс 1, и это число должно согласовываться с количеством поставляемых контрольных точек. Аргумент points должен указывать на первую координату первой контрольной точки.
Одновременно может быть включено более одного вычислителя. Если у вас определены, например, два вычислителя GL_MAP 1_VERTEX_3 и GL_MAP 1_COLOR_4, то вызов команды gl. Eval. Coord 1() сгенерирует и позицию и цвет.
Для вычисления заданной и активизированной одномерной таблицы используйте команду gl. Eval. Coord 1*().
Вызывает к исполнению процесс вычисления одномерных таблиц. Аргумент u задает одномерную координату на кривой. Обращения к gl. Eval. Coord*() не используют текущие величины цвета, цветового индекса, вектора нормали и координат текстуры. gl. Eval. Coord*() оставляет эти величины неизмененными.
ЗАДАНИЯ
Пример 5. 2 Двумерные вычислители. Вывод изображения поверхности Безье.
Двумерный случай практически идентичен одномерному за тем исключением, что все команды должны принимать в расчет 2 параметра u и v.
Точки, цвета, нормали и координаты текстуры должны поставляться по поверхности, а не по кривой. Математически описание поверхности Безье задается в виде
где величины представляют собой набор из m*n контрольных точек, а функции B это те же многочлены Бернштейна, что и в одномерном случае.
Как и раньше величины могут являться вершинами, нормалями, цветами или координатами текстуры.
Процедура использования двумерного вычислителя: 1. Определите вычислитель (или вычислители) с помощью gl. Map 2*(). 2. Активизируйте их, передав нужную величину (или величины) команде gl. Enable().
3. Вызовите их к исполнению либо с помощью команд gl. Eval. Coord 2() между gl. Begin() и gl. End(), либо определив и применив сетку величин с помощью команд gl. Map. Grid 2() и gl. Eval. Mesh 2().
Определение и вычисление двумерного вычислителя Используйте gl. Map 2*() и gl. Eval. Coord 2*() для определения и выполнения двумерного вычислителя.
Параметр target может принимать любые значения из таблицы 1, но в данном случае MAP 1 нужно изменить на MAP 2 в именах всех параметров.
Как и раньше, эти же значения используются в командах gl. Enable() и gl. Disable() для активизации или деактивации нужных вычислителей. Минимальное и максимальное значения аргументов u и v, задаются в виде аргументов u 1, u 2, v 1 и v 2, соответственно.
Аргументы ustride и vstride задают количество чисел однократной или двойной точности между независимыми установками величин u и v, позволяя пользователю выбирать подрегион контрольных точек из намного большего по размеру массива.
Например, если данные заданы в форме и вы хотите использовать только подмножество точек размером 4 x 4, начинающееся с точки ctrlpoints[20][30], установите ustrideв 100*3, а vstride в 3. Аргумент points в этом случае должен быть задан как &ctrlpoints[20][30][0].
Аргументы, определяющие порядок – uorder и vorder, могут иметь разные значения, позволяя создавать, например, поверхности квадратные в одном направлении и кубические в другом.
Вызывает к исполнению заданные и активизированные двумерные вычислители. Аргументы u и v являются величинами (или указателями на величины в случае векторной версии команды) доменных координат (координат на поверхности или кривой).
Если активизирован один из вершинных вычислителей (GL_MAP 2_VERTEX_3 или GL_MAP 2_VERTEX_4), то координаты нормалей к поверхности вычисляются автоматически.
Если активизирован режим автоматической генерации нормалей (с помощью аргумента GL_AUTO_NORMAL в команде gl. Enable()), эта нормаль ассоциируется с вычисленной вершиной.
Если этот режим выключен, для вычисления нормали используется текущий активизированный вычислитель. Если же таковой отсутствует, используется текущий вектор нормали.
Пример 5. 2
Реализовать программный код для отрисовки каркасной поверхности Безье в виде 9 изогнутых линий в каждом направлении. Каждая линия состоит из 30 сегментов. Для получения цельной программы, добавьте функции reshape() и main() из примера 5. 1.
GLfloat ctrlpoints[4][4][3]={ {{-1. 5, 4. 0}, {-0. 5, 1. 5, 2. 0}, {0. 5, -1. 0}, {1. 5, 2. 0}}, {{-1. 5, -0. 5, 1. 0}, {-0. 5, 3. 0}, {0. 5, -0. 5, 0. 0}, {1. 5, -0. 5, 1. 0}}, {{-1. 5, 0. 5, 4. 0}, {0. 5, 0. 0}, {0. 5, 3. 0}, {1. 5, 0. 5, 4. 0}}, {{-1. 5, -2. 0}, {-0. 5, 1. 5, 2. 0}, {0. 5, 1. 5, 0. 0}, {1. 5, -1. 0}} };
Пример 5. 3 Определение двумерных доменных координат на поверхности с равными промежутками. Освещенная и закрашенная поверхность Безье, нарисованная по сетке доменных координат.
В двух измерениях команды gl. Map. Grid 2*() и gl. Eval. Mesh 2() используются так же как их одномерные версии, за тем исключением, что должна быть задана информация и о u, и о v.
Определяют двумерную сетку величин, проходящих от u 1 до u 2 за nu шагов с равными промежутками и от v 1 до v 2 за nv с равными промежутками (gl. Map. Grid 2*()) и затем применяют эту сетку ко всем активизированным вычислителям (gl. Eval. Mesh 2()).
Существенное отличие от одномерного случая заключается в том, что аргумент mode команды gl. Eval. Mesh 2() помимо GL_POINT и GL_LINE может принимать и значение GL_FILL генерирует закрашенные полигоны с помощью четырехугольников.
Отличия, которые нужно внести в программный код примера 5. 2, чтобы нарисовать ту же поверхность, но с применением gl. Map. Grid 2() и gl. Eval. Mesh 2() для разделения квадрата доменных координат на сетку величин размерностью 8 x 8. Пример 5. 3 также добавляет освещение и закраску.
Пример 5. 4 Интерфейс GLU NURBS. Вывод изображения NURBS – поверхности.
Библиотека утилит GLU предоставляет интерфейс NURBS, построенный поверх команд Open. GL для работы с вычислителями.
Для того, чтобы нарисовать кривую или поверхность NURBS необходимо реализовать следующие шаги:
1. Если вы намереваетесь использовать освещение на поверхности NURBS, вызовите gl. Enable() с аргументом GL_AUTO_NORMAL для активизации режима автоматического вычисления нормалей.
2. Используйте функцию glu. New. Nurbs. Renderer() для создания нового объекта NURBS и получения указателя на него. На этот объект вы будете ссылаться при построении кривой или поверхности NURBS.
3. Можно вызвать glu. Nurbs. Property() для установки значений различных свойств, например, максимального размера линий или полигонов, используемых для визуализации кривой или поверхности. glu. Nurbs. Property() также позволяет активизировать режим, в котором тесселированные геометрические данные могут быть получены через интерфейс возвратно – вызываемых функций.
4. Если вы хотите принимать уведомления об ошибках, вызовите glu. Nurbs. Callback(). (Проверка ошибок может снизить быстродействие программы, но, тем не менее, ее наличие настойчиво рекомендуется. ) glu. Nurbs. Callback() также позволяет задать возвратные функции, которые будут вызываться для извлечения тесселированных геометрических данных.
5. Начните описание вашей кривой или поверхности, вызвав glu. Begin. Curve() или glu. Begin. Surface().
6. Сгенерируйте и визуализируйте вашу кривую или поверхность. Вы должны хотя бы один раз вызвать функцию glu. Nurbs. Curve() или glu. Nurbs. Surface(), передавая им контрольные точки (рациональные или нерациональные), узловые последовательности и порядок полиномиальной базисной функции для вашего объекта NURBS.
Для указания нормалей и/или координат текстуры вам могут понадобиться дополнительные вызовы этих функций.
7. Вызовите glu. End. Curve() или glu. End. Surface(), завершая описание кривой или поверхности
Пример 5. 4 визуализирует поверхность NURBS в форме симметричного холма с контрольными точками, изменяющимися от -3. 0 до 3. 0. Базисная функция представляет собой кубический B – сплайн, но узловая последовательность является неравномерной, заставляя функцию вести себя в каждом направлении как кривая Безье.
Поверхность освещена, имеет темно-серое диффузное отражение и белый зеркальный блик.
void display() { GLfloat knots[8]={0. 0, 1. 0}; int i, j; gl. Clear(GL_COLOR_BUFFER_BIT|GL_DEP TH_BUFFER_BIT); gl. Push. Matrix(); gl. Rotatef(330. 0, 1. 0, 0. 0); gl. Scalef(0. 5, 0. 5);
glu. Begin. Surface(the. Nurb); glu. Nurbs. Surface(the. Nurb, 8, knots, 4*3, 3, &ctrlpoints[0][0][0], 4, 4, GL_MAP 2 _VERTEX_3); glu. End. Surface(the. Nurb); if(show. Points) { gl. Point. Size(5. 0); gl. Disable(GL_LIGHTING); gl. Color 3 f(1. 0, 0. 0);
gl. Begin(GL_POINTS); for(i=0; i<4; i++) for(j=0; j<4; j++) gl. Vertex 3 fv(&ctrlpoints[i][j][0] ); gl. End(); gl. Enable(GL_LIGHTING); } gl. Pop. Matrix(); gl. Flush(); }
void init() { GLfloat mat_diffuse[]={0. 7, 1. 0}; GLfloat mat_specular[]={1. 0, 1. 0}; GLfloat mat_shininess[]={100. 0}; gl. Clear. Color(0. 0, 0. 0); gl. Materialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); gl. Materialfv(GL_FRONT, GL_SPECULAR, mat_specular);
gl. Materialfv(GL_FRONT, GL_SHININ ESS, mat_shininess); gl. Enable(GL_LIGHTING); gl. Enable(GL_LIGHT 0); gl. Enable(GL_DEPTH_TEST); gl. Enable(GL_AUTO_NORMAL); gl. Enable(GL_NORMALIZE);
init_surface(); the. Nurb=glu. New. Nurbs. Renderer(); glu. Nurbs. Property(the. Nurb, GLU_SAMPLIN G_TOLERANCE, 2. 0); glu. Nurbs. Property(the. Nurb, GLU_DISPLAY _MODE, GLU_FILL); }
void keyboard(unsigned char key, int x, int y) { switch(key) { case 'c': case 'C': show. Points=!show. Points; glut. Post. Redisplay(); break; } }
Пример 5. 5 Вывод изображения декорированной NURBS – поверхности.
Чтобы создать декорированную поверхность NURBS с помощью Open. GL, начните так же как и при создании обычной поверхности. После вызовов glu. Begin. Surface() и glu. Nurbs. Surface(), но до вызова glu. End. Surface() начните декорирование с вызова glu. Begin. Trim()
void glu. Begin. Trim (GLUnurbs. Obj* nobj); void glu. End. Trim (GLUnurbs. Obj* nobj); Маркируют начало и конец определения декорирующих кривых и поверхностей.
Декорирующий круг – это набор ориентированных декорирующих сегментов кривой (формирующих замкнутую кривую), определяющих границы поверхности NURBS.
Можно создавать два вида декорирующих кривых: кусочную линейную кривую с помощью glu. Pwl. Curve() или кривую NURBS с помощью glu. Nurbs. Curve().
Кусочная линейная кривая не выглядит как то, что обычно называют кривой, поскольку состоит она из прямых линий.
Кривая NURBS для декорирования должна лежать в единичном параметрическом пространстве (u, v). Типом для декорирующей кривой NURBS обычно является GLU_MAP 1_TRIM_2. Реже, типом является GLU_MAP 1_TRIM_3, где кривая описывается в двумерном однородном пространстве (u’, v’, w’) как (u, v)=(u’/w’, v’/w’).
void glu. Pwl. Curve (GLUnurbs. Obj* nobj, GLint count, GLfloat* array, GLint stride, GLenum type); Описывает кусочную линейную декорирующую кривую для NURBS Объекта nobj. На кривой count точек, задаваемых в массиве array.
Аргумент type может принимать значения GLU_MAP 1_TRIM_2 (более часто) или GLU_MAP 1_TRIM_3 (однородное параметрическое пространство (u, v, w)).
Значение type определяет значение stride, которое может быть равно 2 или 3. stride должен быть равен количеству величин между соседними вершинами в array.
Параметрические декорирующие кривые
Модифицируйте программный код 5. 4 , заменив соответствующий фрагмент на приведённый ниже.
Вызовы glu. Begin. Trim() и glu. End. Trim() обрамляют каждую декорирующую кривую. Первая из них с вершинами, определенными в массиве edge. Pt[ ][ ], проходит против часовой стрелки вокруг всего единичного квадрата параметрического пространства.
Это позволяет быть уверенным в том, что будет нарисовано все (если, конечно, часть поверхности не будет удалена внутренней кривой с ориентацией по часовой стрелке).
Вторая кривая – это комбинация кривой NURBS и кусочной линейной кривой. Кривая NURBS заканчивается в точках (0. 9, 0. 5) и (0. 1, 0. 5), где она соединяется с линейной кривой, формируя замкнутую кривую.
Лабораторные работа 5.ppt