1 « » 6 « OpenGL» - МГТУ им. Н. Э. Баумана

advertisement
Модуль 1 «Основы компьютерной геометрии»
Лекция 6 «Геометрические примитивы OpenGL»
к.ф.-м.н., доц. каф. ФН-11, Захаров Андрей Алексеевич,
ауд.:930а(УЛК)
моб.: 8-910-461-70-04,
email: azaharov@bmstu.ru
МГТУ им. Н.Э. Баумана
12 декабря 2014 г.
Точки
Чтобы задать координаты единственной точки, используется следующая
функция OpenGL:
glVertex*();
Здесь звёздочка (*) означает, что для данной функции необходимы
индексные коды. Индексные коды обозначают размерность пространства,
тип числовых данных, которые используются в качестве значений
координат, и возможность представления координат в виде вектора.
Функция glVertex должна находиться в программе между функциями
glBegin и glEnd. Аргумент функции glBegin определяет тип
графического примитива, который следует изобразить, а функция glEnd
не требует аргументов. При выводе на экран точки аргументом функции
glBegin является символьная константа GL_POINTS. Т.о., положение точки
в OpenGL описывается так:
glBegin(GL_POINTS);
glVertex*();
glEnd();
Координаты точек в OpenGL могут задаваться в 2, 3 или 4-х измерениях.
Четырёхмерное описание указывает на представление с помощью
однородных координат, где однородный параметр h (четвертая
координата) — это масштабный коэффициент для значений декартовых
координат.
Точки
Далее нужно обозначить какой тип данных используется для описания
числовых значений координат. Это осуществляется с помощью второго
индексного кода функции glVertex. Типы числовых данных обозначаются
следующими индексами: i(int), s(short), f(float), d(double).
Наконец, значения координат glVertex могут перечисляться в явном виде,
или для них может использоваться массив. Если применяется описание
координат в виде массива, нам нужно прибавить третий индекс: v(vector).
Например:
glBegin(GL_POINTS);
glVertex2i(50,100);
glEnd();
Аналогичный результат можно получить при помощи задания координат
точки в виде массива:
int point1[] = {50,100};
glBegin(GL_POINTS);
glVertex2iv(point1);
glEnd();
Прямые линии (отрезки)
Каждый отрезок прямой определяется координатами двух его концов. В
пакете OpenGL координаты концов выбираются с помощью функции
glVertex, точно также как это делалось для координат точки, т.е. между
glBegin/glEnd. По умолчанию рисуются сплошные линии белого цвета.
Набор прямолинейных отрезков, соединяющих каждую последующую пару
точек-концов из перечня, задаётся с помощью константы примитива
линии — GL_LINES. В общем случае это даст набор несоединенных между
собой линий, если только некоторые значения констант не повторяются.
Если задать только одну точку, то ничего изображаться не будет, а если
число точек (концов отрезков) в списке будет нечётным, то последнее
значение отбрасывается.
glBegin(GL_LINES);
glVertex2iv(p1);
glVertex2iv(p2);
glVertex2iv(p3);
glVertex2iv(p4);
glVertex2iv(p5);
glEnd();
Прямые линии (отрезки)
С помощью константы OpenGL GL_LINE_STRIP можно построить
ломанную линию. В этом случае будет изображена последовательность
соединённых между собой отрезков, которая начинается в первой точке
перечня и заканчивается в последней.
Один из способов создания изображения простой кривой —
аппроксимировать её с помощью ломанной линии. Нужно всего лишь
задать набор точек, расположенных на этой кривой, а затем соединить эти
точки прямолинейными отрезками. Чем из большего числа отрезков будет
состоять ломанная линия, тем более гладкой будет выглядеть кривая.
Третий примитив прямой линии в OpenGL — это GL_LINE_LOOP, который
даёт замкнутую ломанную линию.
Примитивы символов
Графические изображения часто содержат текстовую информацию, как
подписи на графиках и таблицах, вывески на зданиях или надписи на
машинах, а также общая информация в приложениях, связанных с
моделированием и визуализацией.
Растровый символ GLUT можно получить с помощью функции
glutBitmapCharacter(font, character);
Здесь параметру font присваивается значение символьной константы
GLUT, которая указывает на определённый набор начертаний, а параметру
character присваивается значение символа, который мы хотим
изобразить, например ’A’. Возможны шрифты как с постоянной шириной
символов, так и с пропорциональными промежутками. Моноширинный
шрифт можно выбрать, присвоив параметру font значение
GLUT_BITMAP_8_BY_13 или GLUT_BITMAP_9_BY_15 (цифровые параметры
определяют расстояние и размер символов). А пропорциональный шрифт
размером 10pt можно выбрать с помощью команд
GLUT_BITMAP_TIMES_NEW_ROMAN_10 или GLUT_BITMAP_HELVETICA_10.
Возможен шрифт Times Roman размером 12pt, а также шрифты Helvetica
размером 12и 18pt.
Символы изображаются в том цвете, который был задан до выполнения
функции glutBitmapCharacter.
Примитивы символов
Каждый символ, созданный с помощью функции glutBitmapCharacter,
изображается так, что начало координат (нижний левый угол) битового
массива находится в текущем растровом положении. После того как
битовый массив символа загружается в буфер кадра, к координате x
текущего растрового поля добавляется смещение, равное ширине символа.
В качестве примера изобразим текстовую строку, состоящую из 36
растровых символов:
glRasterPos2i(x,y);
for (k=0; k<36; k++)
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, text[k]);
Чтобы задать координаты текущего растрового положения, применяется
следующая процедура:
glRasterPos* ( );
Параметры и индексы аналогичны тем, которые используются в функции
glVertex. Текущее растровое положение задаётся во внешних
координатах. По умолчанию значение текущего растрового положения
совпадает с началом отсчёта (0,0,0) внешней системы координат.
Примитивы символов
Векторный символ изображается путём вызова следующей функции:
glutStrokeCharacter(font, character);
Для этой функции параметру font можно присвоить значение
GLUT_STROKE_ROMAN, чтобы изобразить пропорциональный шрифт, или
GLUT_STROKE_MONO_ROMAN, чтобы представить моноширинный шрифт.
Текстовые строки, полученные с помощью векторных шрифтов, являются
частью геометрического описания двух- или трёхмерных сцен, поскольку
они состоят из геометрических линий. Ширина линии задаётся с помощью
функции glLineWidth, а тип линии — с помощью функции
glLineStipple. Т.е. их можно без каких-либо искажений сжимать,
растягивать или преобразовывать каким-то другим способом. Однако они
визуализируются медленнее, чем растровые шрифты.
Функции многоугольников в OpenGL
За одним исключением, все процедуры OpenGL описания
многоугольников похожи на функции описания точек или ломанной
линии. Функция glVertex используется для ввода координат одной
вершины многоугольника, а весь многоугольник описывается с помощью
списка вершин, расположенного между парой команд glBegin/glEnd.
По умолчанию внутренняя часть многоугольника изображается одним
цветом, который определяется по текущим установкам цвета.
В OpenGL заполненная область должна задаваться в виде выпуклого
простого многоугольника. Закрашенная область в виде одного
многоугольника может задаваться с помощью одного только списка
вершин, который должен содержать по меньшей мере три вершины. Конфигурации, содержащие отверстия во внутренней области многоугольника невозможно задать с помощью одного
примитива (такие конфигурации можно описать с помощью
двух наложенных друг на друга выпуклых многоугольников).
Каждый многоугольник имеет две стороны: переднюю и заднюю. В
OpenGL цвет заполнения и другие параметры можно задавать для каждой
стороны отдельно. Передняя сторона многоугольника определяется
вершинами, заданными в направлении против часовой стрелки.
Существует шесть различных символьных констант, которые используются
в качестве аргумента функции glBegin для описания многоугольников.
Функции многоугольников в OpenGL
С помощью константы OpenGL GL_POLYGON можно получить изображение
одного закрашенного многоугольника. Предположим, что задан массив
координат (x, y) шести точек: p1 , . . . p6 – вершин двухмерного
многоугольника, заданных в направлении против часовой стрелки. Тогда
код, формирующий данный многоугольник, имеет вид:
glBegin(GL_POLYGON);
glVertex2iv(p1);
glVertex2iv(p2);
glVertex2iv(p3);
glVertex2iv(p4);
glVertex2iv(p5);
glVertex2iv(p6);
glEnd();
В списке вершин многоугольника должно быть как минимум три вершины.
В противном случае ничего изображено не будет.
Функции многоугольников в OpenGL
Если поменять порядок точек в списке вершин из предыдущего кода и
воспользоваться другой константой примитива GL_TRIANGLES, то
получится два отдельных закрашенных треугольника.
glBegin(GL_TRIANGLES);
glVertex2iv(p1);
glVertex2iv(p2);
glVertex2iv(p6);
glVertex2iv(p3);
glVertex2iv(p4);
glVertex2iv(p5);
glEnd();
В этом случае первые три точки обозначают вершины одного
треугольника, следующие три точки задают следующий треугольник, и
т.д. Для каждого закрашенного треугольника вершины задаются в
направлении против часовой стрелки. Если количество заданных вершин
не будет кратно трем, то последние две или одна точка просто не будут
учитываться.
Функции многоугольников в OpenGL
Путём ещё одной перестановки вершин в списке и замены константы
примитива на GL_TRIANGLE_STRIP (полоса треугольников) можно
получить изображение соединённых треугольников.
glBegin(GL_TRIANGLE_STRIP);
glVertex2iv(p1);
glVertex2iv(p2);
glVertex2iv(p6);
glVertex2iv(p3);
glVertex2iv(p5);
glVertex2iv(p4);
glEnd();
У всех последовательных треугольников есть одна общая сторона с
предыдущим треугольником. Первые три вершины должны указываться в
направлении против часовой стрелки, если смотреть на переднюю
(внешнюю) поверхность треугольника. После этого каждый последующий
треугольник формируется в направлении против часовой стрелки.
Функции многоугольников в OpenGL
Ещё один способ построения набора соединённых треугольников —
воспользоваться методом «веера», где все треугольники имеют одну
общую вершину. Такое расположение треугольников можно получить с
помощью константы примитива GL_TRIANGLE_FAN и такого порядка шести
вершин:
glBegin(GL_TRIANGLE_FAN);
glVertex2iv(p1);
glVertex2iv(p2);
glVertex2iv(p3);
glVertex2iv(p4);
glVertex2iv(p5);
glVertex2iv(p6);
glEnd();
Вершины должны быть заданы в соответствующем порядке, чтобы можно
было правильно определить переднюю и заднюю стороны каждого
треугольника. Первое значение в списке (в данном случае, p1 ) — это
вершина всех треугольников веера.
Функции многоугольников в OpenGL
OpenGL также предлагает средства описания двух типов
четырёхугольников (многоугольников с четырьмя сторонами). С помощью
константы примитива GL_QUADS и следующего списка из восьми вершин
получится два отдельных закрашенных четырёхугольника:
glBegin(GL_QUADS);
glVertex2iv(p1);
glVertex2iv(p2);
glVertex2iv(p3);
glVertex2iv(p4);
glVertex2iv(p5);
glVertex2iv(p6);
glVertex2iv(p7);
glVertex2iv(p8);
glEnd();
Первые четыре точки определяют вершины одного четырёхугольника,
следующие четыре точки описывают следующий четырёхугольник и т.д.
Для каждого закрашенного четырёхугольника вершины задаются против
часовой стрелки. Если число заданных вершин не будет кратно четырём,
то лишние значения просто не будут приниматься во внимание.
Функции многоугольников в OpenGL
Переставив вершины в списке из предыдущего примера и заменив
константу примитива на GL_QUAD_STRIP (полоса четырёхугольников),
можно получить набор соединённых четырёхугольников:
glBegin(GL_QUAD_STRIP);
glVertex2iv(p1);
glVertex2iv(p2);
glVertex2iv(p4);
glVertex2iv(p3);
glVertex2iv(p5);
glVertex2iv(p6);
glVertex2iv(p8);
glVertex2iv(p7);
glEnd();
Вершины нужно перечислять таким образом, чтобы каждый
многоугольник имел правильный порядок вершин (против часовой
стрелки).
Функции многоугольников в OpenGL
Поскольку графические изображения очень часто содержат закрашенные
прямоугольные области, пакет OpenGL предлагает специальную функцию
изображения прямоугольника:
glRect* (x1, y1, x2, y2);
Один угол этого прямоугольника находится в точке с координатами
(x1 , y1 ), а противоположный угол прямоугольника — в точке с
координатами (x2 , y2 ). Суффиксы функции glRect обозначают тип
данных и то, выражаются ли координаты в виде элементов массива. Эти
индексы — i, s, f, d и v. Прямоугольник изображается таким образом. что
его стороны параллельны координатным осям плоскости xy. Например:
glRecti (50, 100, 200, 250);
//задание в виде массива данных
int vertex1 [] = {50, 100};
int vertex2 [] = {200, 250};
glRectiv (vertex1, vertex2);
250
200
150
100
50
50
100
150
200
В этом примере список вершин формируется по часовой стрелке. Во
многих двумерных приложениях различие между передней и задней
стороной многоугольника несущественно. Если требуется приписать
передним и задним сторонам различные свойства, то нужно изменить
порядок следования двух вершин.
Функции многоугольников в OpenGL
Во многих графических пакетах криволинейные поверхности
изображаются с помощью аппроксимирующих плоских граней. Это
объясняется тем, что уравнения плоскости линейны, а обработка
линейных уравнений выполняется намного быстрее, чем обработка
квадратных уравнений или уравнений других типов кривых. Поэтому
OpenGL и другие пакеты предлагают примитивы сеток многоугольников,
которыми можно аппроксимировать криволинейные поверхности. В пакете
OpenGL для этой цели можно использовать такие примитивы, как полоса
треугольников, веер треугольников или полоса четырёхугольников.
Высококачественные графические системы, способные изображать
миллион или больше закрашенных многоугольников (как правило,
треугольников) в секунду, включая приложения, связанные с наложением
текстур на поверхности и специальных эффектов освещения, имеют
встроенные аппаратные средства визуализации многоугольников.
Несмотря на то что корневая библиотека OpenGL принимает только
выпуклые многоугольники, библиотека OpenGL Utility (GLU) предлагает
функции, позволяющие работать с невыпуклыми многоугольниками.
Существует набор стандартных процедур библиотеки GLU для мозаичного
представления вогнутых многоугольников, которые позволяют
преобразовать такие фигуры в набор треугольников и треугольные сетки.
Затем их можно обрабатывать с помощью основных функций OpenGL.
Download