Главная страница
Навигация по странице:

  • NormalPointer

  • Списки изображений

  • GL_COMPILE

  • Преобразования координат и проекции

  • Видовое преобразование

  • Область вывода

  • Введение в OpenGL - royallib.ru. Учебное пособиеСодержание Введение


    Скачать 101.72 Kb.
    НазваниеУчебное пособиеСодержание Введение
    АнкорOpengl
    Дата02.10.2019
    Размер101.72 Kb.
    Формат файлаdoc
    Имя файлаВведение в OpenGL - royallib.ru.doc
    ТипУчебное пособие
    #88338
    страница2 из 4
    1   2   3   4

    Массивы вершин
    Если вершин много, то чтобы не вызывать для каждой команду glVertex…(), удобно объединять вершины в массивы, используя команду

    void glVertexPointer (GLint size, GLenum type, GLsizei stride, void *ptr)

    которая определяет способ хранения и координаты вершин. При этом size определяет число координат вершины (может быть равен 2, 3, 4), type определяет тип данных (может быть равен GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE). Иногда удобно хранить в одном массиве другие атрибуты вершины, и тогда параметр stride задает смещение от координат одной вершины до координат следующей; если stride равен нулю, это значит, что координаты расположены последовательно. В параметре ptr указывается адрес, где находятся данные.

    Аналогично можно определить массив нормалей, цветов и некоторых других атрибутов вершины, используя команды

    void NormalPointer (GLenum type, GLsizei stride, void*pointer)

    void ColorPointer (GLintsize, GLenum type, GLsizei stride, void *pointer)

    Для того, чтобы эти массивы можно было использовать в дальнейшем, надо вызвать команду

    void glEnableClientState (GLenum array)

    с параметрами GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, GL_COLOR_ARRAY соответственно. После окончания работы с массивом желательно вызвать команду

    void glDisableClientState (GLenum array)

    с соответствующим значением параметра array.

    Для отображения содержимого массивов используется команда

    void glArrayElement (GLint index)

    которая передает OpenGL атрибуты вершины, используя элементы массива с номером index. Это аналогично последовательному применению команд вида glColor…(…), glNormal…(…), glVertex…(…) c соответствующими параметрами. Однако вместо нее обычно вызывается команда

    void glDrawArrays (GLenum mode, GLint first, GLsizei count)

    рисующая count примитивов, определяемых параметром mode, используя элементы из массивов с индексами от first до first+count-1. Это эквивалентно вызову команды glArrayElement() с соответствующими индексами.

    В случае если одна вершина входит в несколько примитивов, то вместо дублирования ее координат в массиве удобно использовать ее индекс.

    Для этого надо вызвать команду

    void glDrawArrays (GLenum mode, GLsizei count, GLenum type, void *indices)

    где indices - это массив номеров вершин, которые надо использовать для построения примитивов, type определяет тип элементов этого массива: GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, а count задает их количество.
    Списки изображений
    Если нужно несколько раз обращаться к одной и той же группе команд,эти команды можно объединить в так называемый список изображений (display list) и вызывать его при необходимости. Для того, чтобы создать новый список изображений надо поместить все команды, которые должны в него войти между командными скобками:

    void glNewList (GLuint list, GLenum mode)

    void glEndList ()

    Для различения списков используются целые положительные числа, задаваемые при создании списка значением параметра list, а параметр mode определяет режим обработки команд, входящих в список:

    GL_COMPILE команды записываются в список без выполнения

    GL_COMPILE_AND_EXECUTE команды сначала выполняются, а затем записываются в список

    После того, как список создан, его можно вызвать командой

    void glCallList (GLuint list)

    указав в параметре list идентификатор нужного списка. Чтобы вызвать сразу несколько списков, можно воспользоваться командой

    void glCallLists (GLsizei n, GLenum type, const GLvoid *lists)

    вызывающей n списков с идентификаторами из массива lists, тип элементов которого указывается в параметре type. Это могут быть типы GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_INT, GL_UNSIGNED_INT ›и некоторые другие. Для удаления списков используется команда

    void glDeleteLists (GLint list, GLsizei range)

    которая удаляет списки с идентификаторами ID из диапазона list ‹= ID ‹= list+range-1.

    Преобразования координат и проекции
    В OpenGL используются как основные три системы координат: левосторонняя, правосторонняя и оконная. Первые две системы являются трехмерными и отличаются друг от друга направлением оси z: в правосторонней она направлена на наблюдателя, а в левосторонней - в глубь экрана. Расположение осей x и y аналогично описанному выше. Левосторонняя система используется для задания значений параметрам команды gluPerspective(), glOrtho(), которые будут рассмотрены ниже, а правосторонняя или мировая система координат во всех остальных случаях. Отображение трехмерной информации происходит в двумерную оконную систему координат.

    Для задания различных преобразований объектов сцены в OpenGL используются операции над матрицами, при этом различают три типа матриц: видовая, проекций и текстуры. Все они имеют размер 4×4. Видовая матрица определяет преобразования объекта в мировых координатах, такие как параллельный перенос, изменение масштаба и поворот. Матрица проекций задает как будут проецироваться трехмерные объекты на плоскость экрана (в оконные координаты), а матрица текстуры определяет наложение текстуры на объект.

    Для того, чтобы выбрать, какую матрицу надо изменить, используется команда

    void glMatrixMode (GLenum mode)

    вызов которой со значением параметра mode равным GL_MODELVIEW, GL_PROJECTION, GL_TEXTURE включает режим работы с видовой, проекций и матрицей текстуры соответственно. Для вызова команд, задающих матрицы того или иного типа необходимо сначала установить соответствующий режим.

    Для определения элементов матрицы текущего типа вызывается команда

    void glLoadMatrix[f d] (GLtype *m)

    где m указывает на массив из 16 элементов типа float или double в соответствии с названием команды, при этом сначала в нем должен быть записан первый столбец матрицы, затем второй, третий и четвертый.

    Команда

    void glLoadIdentity (void)

    заменяет текущую матрицу на единичную. Часто нужно сохранить содержимое текущей матрицы для дальнейшего использования, для чего используют команды

    void glPushMatrix (void)

    void glPopMatrix (void)

    Они записывают и восстанавливают текущую матрицу из стека, причем для каждого типа матриц стек свой. Для видовых матриц его глубина равна как минимум 32, а для двух оставшихся типов как минимум 2.

    Для умножения текущей матрицы слева на другую матрицу используется команда

    void glMultMatrix[f d] (GLtype *m)

    где m должен задавать матрицу размером 4x4 в виде массива с описанным расположением данных. Однако обычно для изменения матрицы того или иного типа удобно использовать специальные команды, которые по значениям своих параметров создают нужную матрицу и перемножают ее с текущей. Чтобы сделать текущей созданную матрицу, надо перед вызовом этой команды вызвать glLoadIdentity().

    В целом, для отображения трехмерных объектов сцены в окно приложения используется следующая последовательность действий:

    Координаты объекта → Видовые координаты → Усеченные координаты → Нормализованные координаты → Оконные координаты

    Рассмотрим каждое из этих преобразований отдельно.
    Видовое преобразование
    К видовым преобразованиям будем относить перенос, поворот и изменение масштаба вдоль координатных осей. Для проведения этих операций достаточно умножить на соответствующую матрицу каждую вершину объекта и получить измененные координаты этой вершины:

    (x’, y’, z’, 1)T = M * (x, y, z, 1)T

    где M матрица видового преобразования. Перспективное преобразование и проектирование производится аналогично. Сама матрица может быть создана с помощью следующих команд:

    void glTranslate[f d] (GLtype x, GLtype y, GLtype z)

    void glRotate[f d] (GLtype angle, GLtype x, GLtype y, GLtype z)

    void glScale[f d] (GLtype x, GLtype y, GLtype z)

    glTranlsate…() производит перенос объекта, прибавляя к координатам его вершин значения своих параметров.

    glRotate…() производит поворот объекта против часовой стрелки на угол angle (измеряется в градусах) вокруг вектора (x,y,z).

    glScale…() производит масштабирование объекта (сжатие или растяжение), домножая соответствующие координаты его вершин на значения своих параметров.

    Все эти преобразования будут применяться к примитивам, описания которых будут находиться ниже в программе. В случае если надо, например, повернуть один объект сцены, а другой оставить неподвижным, удобно сначала сохранить текущую видовую матрицу в стеке командой glPushMatrix(), затем вызвать glRotate…() с нужными параметрами, описать примитивы, из которых состоит этот объект, а затем восстановить текущую матрицу командой glPopMatrix().

    Кроме изменения положения самого объекта иногда бывает нужно изменить положение точки наблюдения, что однако также приводит к изменению видовой матрицы. Это можно сделать с помощью команды

    void gluLookAt (GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz)

    где точка (eyex,eyey,eyez) определяет точку наблюдения, (centerx, centery, centerz)задает центр сцены, который будет проектироваться в центр области вывода, а вектор (upx,upy,upz) задает положительное направление оси у, определяя поворот камеры. Если, например, камеру не надо поворачивать, то задается значение (0,1,0), а со значением (0,-1,0) сцена будет перевернута.

    Фактически, эта команда совершает перенос и поворот объектов сцены, но в таком виде задавать параметры бывает удобнее.
    Проекции
    В OpenGL существуют ортографическая (параллельная) и перспективная проекция. Первый тип проекции может быть задан командами

    void glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)

    void gluOrtho2D (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)

    Первая команда создает матрицу проекции в усеченный объем видимости (параллелограмм видимости) в левосторонней системе координат. Параметры команды задают точки (left, bottom, -near) и (right, top, -near), которые отвечают левому нижнему и правому верхнему углам окна вывода. Параметры near и far задают расстояние до ближней и дальней плоскостей отсечения по дальности от точки (0,0,0) и могут быть отрицательными.

    Во второй команде, в отличие от первой, значения near и far устанавливаются равными -1 и 1 соответственно.

    Перспективная проекция определяется командой

    void gluPerspective (GLdouble angley, GLdouble aspect, GLdouble znear, GLdouble zfar)

    которая задает усеченный конус видимости в левосторонней системе координат. Параметр angley определяет угол видимости в градусах по оси у и должен находиться в диапазоне от 0 до 180. Угол видимости вдоль оси x задается параметром aspect, который обычно задается как отношение сторон области вывода. Параметры zfar и znear задают расстояние от наблюдателя до плоскостей отсечения по глубине и должны быть положительными. Чем больше отношение zfar/znear, тем хуже в буфере глубины будут различаться расположенные рядом поверхности, так как по умолчанию в него будет записываться ‘сжатая’ глубина в диапазоне от 0 до 1 (см. следующий пункт).
    Область вывода
    После применения матрицы проекций на вход следующего преобразования подаются так называемые усеченные (clip) координаты, для которых значения всех компонент (xc, yc, zc, wc)T находятся в отрезке [-1,1]. После этого находятся нормализованные координаты вершин по формуле:

    (xn, yn, zn)T=(xc/wc, yc/wc, zc/wc)T

    Область вывода представляет из себя прямоугольник в оконной системе координат, размеры которого задаются командой:

    void glViewPort (GLint x, GLint y, GLint width, GLint height)

    Значения всех параметров задаются в пикселах и определяют ширину и высоту области вывода с координатами левого нижнего угла (x,y) в оконной системе координат. Размеры оконной системы координат определяются текущими размерами окна приложения, точка (0,0)находится в левом нижнем углу окна.

    Используя параметры команды glViewPort(), вычисляются оконные координаты центра области вывода (ox, oy) по формулам ox=x+width/2, oy=y+height/2.

    Пусть px=width, py=height, тогда можно найти оконные координаты каждой вершины:

    (xw, yw, zw)T = ((px/2) xn+ ox , (py/2) yn+ oy, [(f-n)/2] zn+(n+f)/2)T

    При этом целые положительные величины n и f задают минимальную и максимальную глубину точки в окне и по умолчанию равны 0 и 1 соответственно. Глубина каждой точки записывается в специальный буфер глубины (z-буфер), который используется для удаления невидимых линий и поверхностей. Установить значения n и f можно вызовом функции

    void glDepthRange (GLclampd n, GLclampd f)

    Команда glViewPort() обычно используется в функции, зарегистрированной с помощью команды glutReshapeFunc(), которая вызывается, если пользователь изменяет размеры окна приложения, изменяя соответсвующим образом область вывода.
    1   2   3   4


    написать администратору сайта