| Матричные преобразования в OpenGL. |
| Написал gdever | ||||||||
| 15.11.2011 | ||||||||
|
До сих пор для осуществления преобразований мы пользовались либо только достаточно простыми механизмами (сдвиг вектора), либо механизмами, которые нельзя применять повсеместно (кватернионы). Конечно у нас есть достаточно навороченный класс cVector, с помощью которого можно сдвигать и вращать вершины. Однако все эти преобразования будут выполняться на CPU и, следовательно, существенно тормозить нашу игру. У кватернионов те же недостатки. Поэтому сейчас настало время рассмотреть способ, с помощью которого можно осуществлять все преобразования практически даром!
Речь пойдет о матричных преобразованиях, которые предоставляет нам в наше распоряжение OpenGL. В этой графической библиотеке реализовано три типа матриц: матрица проецирования, матрица вида, текстурная матрица. Сегодня речь пойдет только о матрице вида. Все эти три матрицы можно свободно изменять. Для начала нужно сообщить системе с каком матрицей мы будем работать. Сделать это можно вызвав функцию glMatrixMode:
glMatrixMode( mode );
// где mode это одно из следующих значений
// GL_MODELVIEW – матрица вида
// GL_PROJECTION – матрица проецирования
// GL_TEXTURE – текстурная матрица
С матрицей проецирования и текстурной матрицей все более менее понятно – они отвечают за проецирование (ортогональное, перспективное etc.) и модификацию текстурных координат. А вот матрица вида требует отдельного, более подробного объяснения. Дело в том что при рендеринге все вершины попадают на конвейер рендеринга в так называемом camera space'e. Это такое пространство, в котором ось OZ направлена в сторону противоположной направлению взгляда (ну и с помощью нормали вида достраиваются оси OX и OY), с началом координат в точке визирования (там где расположена камера). Поэтому если перед рендерингом поставить матрицу вида следующим образом:
glMatrixMode( GL_MODELVIEW );
// загрузка единичной матрицы
glLoadIdentity();
то вся выводимая геометрия будет выводиться непосредственно перед экраном а не там где ей положено быть. Для перевода координат геометрии из camera space'а в глобальные координаты, как раз и применяется матрица вида. После этого можно выбранную матрицу домножать справа на матрицы поворота, смещения или переноса:
// поворот на угол angle (задается в градусах)
// вокруг вектора ( vx , vy , vz )
glRotatef( angle , vx , vy , vz );
// перенос на вектор ( tx , ty , tz )
glTranslatef( tx , ty , tz );
// масштабирование по осям x, y, z
// sx, sy, sz – масштабирующие коэффициенты
// по соответствующим осям
glScalef( sx , sy , sz );
К сожалению эти функции изменяют выбранную матрицу. Поэтому после окончания преобразований нужно возвращать измененную матрицу в исходное состояние. Можно было бы конечно высчитывать обратные матрицы, для выполнения обратных преобразований, но OpenGL предлагает другой, более простой и элегантный способ – стек матриц. Работа с ним осуществляется следующим образом – перед началом преобразований сохраняем матрицу в стеке, которую планируем изменять. Изменяем матрицу согласно нашим замыслам. Выполняем преобразование. Выталкиваем исходную матрицу из стека. Все просто! Работа со стеком осуществляется с помощью следующих функций:
// помещение матрицы в стэк
glPushMatrix();
// выталкивание матрицы из стека
glPopMatrix();
При использовании преобразований следует помнить следующее правило: вектор домножается на матрицу справа, т.е. при перемножении справа стоит вектор, а слева – матрица. Таким образом, если у нас есть последовательность преобразований, то последовательность функций должна быть противоположной. Для большей ясности рассмотрим один пример: пускай у нас есть квадрат, центр которого расположен в начале координат. Нам надо этот квадрат поворачивать вокруг собственного центра, а затем, отодвинув его от начала координат на 3 единицы, повернуть его вокруг начала координат, ну и для большего интереса будем масштабировать этот квадрат. В качестве решения задачи имеем следующую последовательность преобразований:
Теперь распишем вызовы соответствующих функций:
glMatrixMode( GL_MODELVIEW );
// вращение вокруг начала координат
glRotatef( Angle , 0 , 0 , 1 );
//сдвиг на 3 единицы
glTranslatef( 3 , 0 , 0 );
//вращение вокруг центра квадрата
glRotatef( Angle++ , 0 , 0 , 1 );
//масштабирование
glScalef( Scale , Scale , 0 );
Как видите, все согласно правилу. Вот пожалуй и все на сегодня, вроде все просто, однако если возникнут вопросы – пишите сами знаете куда )). ЗЫ исходные коды к данной статье прилагаются.
Только зарегистрированные пользователи могут оставлять коментарии. |
||||||||
| Последнее обновление ( 15.11.2011 ) | ||||||||
| < Пред. | След. > |
|---|


