Помощь в написании студенческих работ
Антистрессовый сервис

Работа с матрицами

РефератПомощь в написанииУзнать стоимостьмоей работы

OpenGL поддерживает преобразование координат с помощью матриц 4×4. Координаты всех входных вершин приводятся к однородным и умножаются сначала на модельно-видовую матрицу (GL_MODELVIEW), а потом — на матрицу проектирования (GL_ PROJECTION). Тем самым OpenGL объединяет модельную матрицу и видовую матрицу в одну общую модельно-видовую матрицу. Кроме того, OpenGL также поддерживает преобразование… Читать ещё >

Работа с матрицами (реферат, курсовая, диплом, контрольная)

В ходе рендеринга передаваемые координаты примитивов подвергаются преобразованиям и многократно переводятся из одной системы координат в другую. Традиционно считается, что изначально объекты заданы в так называемых координатах объекта (object space). Иными словами, когда мы вызываем функцию glutSolidTeapot, она выводит изображение чайника, расположенного в начале координат и ориентированного стандартным образом.

С помощью умножения на модельную матрицу координаты переводятся в мировую систему координат (world space), т. е. если у нас есть несколько объектов, то обычно каждый из них задан в своей собственной системе координат (координаты объекта), а потом они переводятся в общую мировую систему координат.

Далее с камерой (наблюдателем) связана своя система координат — система координат наблюдателя (eye space). Для перевода координат из мировой системы координат в систему координат наблюдателя они умножаются на видовую матрицу.

Заключительный шаг: умножение па матрицу проектирования переводит координаты в систему координат отсечения (clip space).

OpenGL поддерживает преобразование координат с помощью матриц 4×4. Координаты всех входных вершин приводятся к однородным и умножаются сначала на модельно-видовую матрицу (GL_MODELVIEW), а потом — на матрицу проектирования (GL_ PROJECTION). Тем самым OpenGL объединяет модельную матрицу и видовую матрицу в одну общую модельно-видовую матрицу. Кроме того, OpenGL также поддерживает преобразование текстурных координат посредством матрицы преобразования текстурных координат (GL_TEXTURE). Нормали, заданные в вершинах, автоматически преобразуются в соответствии с преобразованием вершин.

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

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

Для задания текущей матрицы в OpenGL используется команда glMatrixMode, единственным аргументом которой является одна из следующих констант: GL_MODELVIEW, GL_PROJECTION и GLJEXTURE:

void glMatrixMode (GLenum matrix).

Простейшей командой для явного задания матрицы служит glLoadldentity, которая заменяет текущую матрицу на единичную. Кроме того, есть команда gl Load Matrix, явно задающая матрицу, на которую нужно заменить текущую. Обратите внимание, что эта матрица задается как массив из 16 чисел: сначала идет первый столбец, потом второй, третий и четвертый:

void glLoadldenity;

void glLoadMatrixff d} (ptr);

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

void gIMultMatrix {f d} (ptr);

Существуют также команды, умножающие текущую матрицу на матрицу одного из базовых преобразований — переноса (gITranslate), масштабирования/отражения (gIScale) и поворота (gIRotate):

void glTranslate{f d} (x, у, z);

void gIScaleff d} (sx, sy, sz);

void glRotate{f d} (angle, x, y, z);

Обратите внимание, что в команде gIScale аргументы могут иметь любой знак. Таким образом, эта команда может использоваться как для задания преобразования масштабирования, так и для задания преобразования отражения относительно координатных плоскостей.

Команда gIRotate домножает текущую матрицу на матрицу поворота, задаваемого с помощью угла (в градусах) angle и вектора (х, у, z), определяющего направление, вокруг которого будет осуществляться поворот.

Часто возникает необходимость явно задать положение и ориентацию камеры/наблюдателя в пространстве. Фактически это просто переход к новой системе координат (рис. 10.5), и в библиотеке GLU для этого есть специальная команда:

void gluLookAt (GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ,.

GLdouble toX, GLdouble toY, GIDouble toZ,.

GLdouble upX, GLdouble upY, GLdouble upZ);

Puc. 10.5. Параметры новой системы координат Здесь первые три параметра определяют точку в пространстве, где находится начало системы координат (камера). Следующие три параметра задают точку, на которую направлен взгляд, последние три параметра определяют направление вверх. Обратите внимание, что первые шесть параметров задают точки в пространстве, а последние три — направление в пространстве.

Puc. 10.5. Параметры новой системы координат Здесь первые три параметра определяют точку в пространстве, где находится начало системы координат (камера). Следующие три параметра задают точку, на которую направлен взгляд, последние три параметра определяют направление вверх. Обратите внимание, что первые шесть параметров задают точки в пространстве, а последние три — направление в пространстве.

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

Также в OpenGL и GLU есть функции для задания матриц параллельного и перспективного проектирования. Для задания параллельного проектирования служит следующая команда OpenGL:

void glOrtho (GLdouble left, GLdouble right,.

GLdouble bottom, GLdouble up,.

GLdouble near, GLdouble far);

Данная команда умножает текущую матрицу на матрицу следующего вида:

где.

Видимая область для параллельного проектирования.

Рис. 10.6. Видимая область для параллельного проектирования.

Данная команда фактически задает параллельное проектирование вдоль оси Oz, при котором область, изображенная на рис. 10.6, становится областью видимости (все, что вне этой области, будет автоматически отсечено).

Для задания перспективного проектирования служит команда gluPerspective: void gluPerspective (GLdouble fovY, GLdouble aspect, GLdouble near, GLdouble far);

На рис. 10.7 изображена область видимости, соответствующая данной команде. С помощью этой команды текущая матрица умножается на следующую матрицу проектирования:

Работа с матрицами.

где через / обозначена следующая величина:

Работа с матрицами.

Здесь параметр fovY определяет угол видимости по вертикали (в градусах) и должен меняться от 0 до 180°. Для определения угла видимости по горизонтали используется параметр aspect, являющийся отношением ширины окна в пикселах к его высоте. Параметры near и far, как и ранее, определяют плоскости, перпендикулярные оси Ог, такие, что все, что лежит не между ними, будет автоматически отсечено.

Видимая область для перспективного проектирования.

Рис. 10.7. Видимая область для перспективного проектирования.

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

void glViewport (GLint х, GLint у, GLint width, GLint height);

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

void gIPushMatrix ();

void gIPopMatrix ();

Первая из этих команд (gIPushMatrix) создает копию матрицы на вершине стека и помещает ее на стек. Вторая команда выбрасывает матрицу с вершины стека, делая текущей следующую матрицу стека.

Наличие стеков матриц облегчает рендеринг иерархических данных. Например, если у нас есть объект А (положение и ориентация которого заданы посредством матрицы), к которому прикреплены объекты В и С (положение и ориентация каждого из которых заданы с помощью своей матрицы), и к объекту В прикреплен еще объект D, также обладающий своей матрицей (рис. 10.8), матрица, задающая положение и ориентацию объекта В, будет являться произведением соответствующих матриц для объектов А и В. Матрица для объекта D будет равна произведению матриц объектов А, В и D.

Составной объект.

Рис. 10.8. Составной объект.

Тогда процедура рендеринга этого составного объекта может быть выражена с помощью следующего фрагмента кода:

Работа с матрицами.

Рассмотрим теперь, как можно вывести изображение чайника, который можно вращать с помощью мыши, и как правильно настроить проектирование. Начнем с настройки проектирования: проще всего это сделать в функции-обработчике, которая вызывается при изменении размеров окна. Для удобства будем хранить положение наблюдателя (камеры) в отдельной переменной eye и используем эту переменную в вызове gluLookAt: Работа с матрицами.

Для задания ориентации объекта также заведем отдельную переменную, в которой будем хранить трехмерный вектор. Отдельные компоненты этого вектора будут задавать повороты относительно осей координат. Тогда функция для рендеринга объекта будет выглядеть, как показано ниже, при этом мы используем функцию glutSolidTeapot из библиотеки GLUT для вывода трехмерной модели чайника:

Работа с матрицами.

Обратите внимание, что приведенная функция восстанавливает за собой значение модельно-видовой матрицы (матрицу проектирования она не изменяет вообще).

Следующим шагом будет обработка перемещений мыши. В библиотеке GLUT разделяют перемещения мыши на два типа: активное (когда при перемещении одна из кнопок мыши нажата) и пассивное (когда ни одна из кнопок мыши не нажата). Нам нужно обрабатывать только активные перемещения мыши.

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

Работа с матрицами.

Поскольку мы используем координаты курсора мыши с прошлого раза, то должны запомнить их в момент нажатия кнопки мыши. Для этого также нужно установить обработчик событий, который получит на вход значение, определяющее, какая именно кнопка мыши была нажата (button), что именно произошло с этой кнопкой (она была нажата или она была отпущена, state) и координаты курсора мыши в пикселах:

Работа с матрицами.

Заключительной частью кода будет инициализация и установка обработчиков событий. Функция glutMouseFunc устанавливает обработчик нажатия и отпускания клавиш мыши, а функция glutMotionFunc — обработчик активного перемещения мыши (для задания обработчика пассивного перемещения мыши служит функция glutPassiveMotionFunc):

Работа с матрицами.
Показать весь текст
Заполнить форму текущей работой