Глава 14. Пространственные геометрические преобразования в OpenGL

Вершины объектов, а также матрицы преобразований в OpenGL используют однородные координаты. То есть вершины объектов являются 4-х компонентными векторами, а матрицы преобразований имеют размер 4х4.

Рис. 277. Проволочная сфера, цилиндр внутри нее и источник света.

На рис.47 показаны три объекта в пространстве: проволочная сфера, полый цилиндр внутри нее и источник света. Пусть нам требуется поворачивать эти объекты относительно центра сферы. Поворот будем осуществлять с помощью мыши, нажатием и перемещением указателя в нужном направлении.

 

Для перемещений в пространстве используется текущая матрица в режиме GL_MODELVIEW. Эту матрицу можно сформировать непосредственно, но можно воспользоваться функциями, задающими преобразования привычным для нас способом. Одного и того же эффекта можно добиться перемещением объектов относительно наблюдателя, а также перемещением наблюдателя относительно объектов в пространстве. Поэтому важно правильно понимать действие функций преобразования, которые включают в себя функции переноса, поворота и масштабирования.

Рассмотрим процедуру построения объектов DrawScene, изображенных на рис. 47.

 

procedure TfrmGL.DrawScene;

begin

glMatrixMode(GL_MODELVIEW);

glLoadIdentity;

glTranslatef(0,0,-260);//задаем матрицу переноса

glRotatef(AngleX, 0.0, 1.0, 0.0); // поворот вокруг оси Y

glRotatef(AngleY, 1.0, 0.0, 0.0); // поворот вокруг оси X

DrawLight;

DrawCylinder;

DrawSphere;

end;

 

После установления текущей единичной матрицывидового преобразования GL_MODELVIEW следуют три функции, которые задают расположение и текущий угол поворота сферы, цилиндра и источника света относительно центра сферы. Последующие команды DrawLight,DrawCylinder и DrawSphere создают источник света, цилиндр и сферу, к которым автоматически применяется матрица видового преобразования.

Как было замечено выше, последовательность функций преобразования координат можно рассматривать применительно как к вершинам трехмерных объектов, так и к системе координат наблюдателя. Это может привести к некоторой путанице. К сожалению, в литературе и документации по OpenGL объяснение действия функций преобразования координат явно недостаточное, так что изучающие вынуждены приходить к пониманию с помощью многочисленных проб и экспериментов. Попытаемся составить понятную картину происходящего. Для этого не будем углубляться в какие-либо математические выкладки на языке матриц и векторов. Укажем лишь фактический алгоритм, которым руководствуется система OpenGL.

Во-первых, необходимо указать на то, что после установления режима GL_MODELVIEW мы будем иметь дело не с одной только матрицей видового преобразования. В реальности мы всегда имеем взаимодействие двух систем координат. Одна из них – мировая система координат – описывает расположение всех объектов в пространстве, в том числе и точку расположения, и ориентацию системы координат наблюдателя. Вторая из них – система координат наблюдателя или видовая система координат. По умолчанию начала этих систем координат совпадают. Совпадают также их оси x и y. Однако оси z этих систем координат не совпадают по направлению.

Мировая система координат традиционно является правосторонней, а видовая система координат левосторонней. Такое расположение осей систем координат связано с интуитивным и привычным представлением об их расположении. Например, начало видовой системы координат расположено в центре экрана монитора, ось x направлена слева направо, ось y снизу вверх, а ось z – перпендикулярно экрану в направлении от пользователя к монитору. Это дает левостороннюю систему. Однако при изображении объектов в трехмерном пространстве удобнее рисовать и представлять систему координат как правостороннюю. Как раз то же самое, что и в мировой системе координат.

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

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

Во втором случае, мы считаем, что действие функций геометрических преобразований относится к видовой системе координат, то есть к осям системы координат наблюдателя относительно начального положения видовой же системы координат. В этом случае мировая система координат остается неподвижной вместе с объектами, который в ней описаны. Задавая координаты объектов, мы каждый раз переносим наблюдателя и располагаем оси его системы координат в соответствии с текущей матрицей преобразования, которая была задана с помощью функций glTranslate, glRotate и glScale. Действие функций геометрических преобразований при этом следует учитывать в том порядке, в котором они записаны в тексте программы.

Для проверки правильности этих двух правил применим их на примере функции DrawScene, приведенной выше. Итак, матрица геометрических преобразований составлена всего из трех действий:

glTranslatef(0,0,-260);//задаем матрицу переноса

glRotatef(AngleX, 0.0, 1.0, 0.0); // поворот вокруг оси Y

glRotatef(AngleY, 1.0, 0.0, 0.0); // поворот вокруг оси X

 

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

 

glRotatef(AngleY, 1.0, 0.0, 0.0); // поворот вокруг оси X

glRotatef(AngleX, 0.0, 1.0, 0.0); // поворот вокруг оси Y

glTranslatef(0,0,-260);//задаем матрицу переноса

 

Функции поворота задают вращение объектов относительно начала координат мировой системы. Оси систем обеих систем координат при этом остаются на своих местах. Первая команда поворота вращает объекты вокруг оси вращения образованной вектором (1,0,0), то есть вокруг оси OX мировой системы координат. Положительное вращение, т.е. поворот на положительный угол, происходит при повороте против часовой стрелки, если смотреть из положительной полуоси образованной вектором вращения (в данном случае из положительной полуоси OX) в направлении начала координат. Поскольку центры сферы и других объектов совпадают с началом координат, то объекты пока остаются на своих местах. Третья функция glTranslatef(0,0,-260) переносит объекты на (–260) единиц по оси Z в мировой системе координат. Все объекты удаляются от начала координат мировой системы, а значит и от начала координат видовой системы координат на 260 единиц. Вспомним, что отрицательное направление оси Z мировой системы координат соответствует положительному направлению видовой системы координат. Поэтому на экране мы видим, что объекты перенесены на (+260) единиц вперед.

Рассмотрим второй вариант, когда преобразуется система координат наблюдателя относительно мировой системы, а объекты остаются неподвижными. В этом случае последовательность команд остается той же что и в тексте программы. Первым действием выполняется перенос начала координат наблюдателя на (-260) единиц по оси Z системы координат наблюдателя. Это дает эффект как если бы мы отодвинулись от монитора назад. Затем производится поворот вокруг оси Y первоначального положения видовой системы координат, а после этого и вокруг оси X тоже первоначального положения видовой системы координат. Поскольку ось Z видовой системы координат всегда остается направленной на начало координат первоначальной видовой системы и на начало координат мировой системы, то получается эффект как будто мы облетаем начало мировой системы координат, глядя на него. Но это неотличимо от того, как если бы объекты вращались перед нами, оставаясь все время на одном месте!

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

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

Рассмотрим далее описания некоторых других функций, которые участвуют в процессе формирования матрицы видового преобразования в OpenGL.

Для операции масштабирования объектов относительно начала координат применяется функция glScale, которая существует в двух версиях: glScaled и glScalef. В качестве параметров они принимают значения масштабных коэффициентов по трем координатным осям. Напомним, что значение масштабного коэффициента равное единице не изменяет размеров объекта вдоль данной оси.

Описание функции glScalef:

void glScalef(

GLfloat x,

GLfloat y,

GLfloat z

);

 

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