OpenGL в Delphi

       

Поворот


Для поворота используется команда glRotatef с четырьмя аргументами: угол поворота, в градусах, и вектор поворота, три вещественных числа.
Для двумерных построений наиболее нагляден поворот по оси Z, чем я и пользуюсь в приводимых примерах.
В предыдущем примере перед командными скобками вставьте строку:

glRotatef (5, 0. 0, 0. 0, 1. 0);

и создайте обработчик события Keypress с единственной командой Refresh. Теперь при нажатии любой клавиши окно перерисовывается, при этом каждый раз фигура поворачивается на пять градусов по оси Z (проект из подкаталога Ex52).
Здесь надо обратить внимание на две вещи: на то, что при положительном значении компоненты вектора поворот осуществляется против часовой стрелки и то, что важно не само значение компоненты, а ее знак и равенство/неравенство ее нулю.
Хотя мы пока ограничиваемся плоскостными построениями, поворот по любой из осей сказывается на воспроизводимой картинке. Проверьте: при повороте по осям X и Y мы получаем правильную картинку в проекции с учетом поворота по осям.
Поворот часто используется при построениях, поэтому важно разобраться в нем досконально. Точно так же, как было с масштабом, поворот действует на все последующие команды воспроизведения, так что при необходимости текущее состояние восстанавливается обратным поворотом.
Например, если надо нарисовать повернутый на 45 градусов квадрат, т e. ромб, то код должен выглядеть так (готовый проект можете взять в подкаталоге Ex53):

glRotatef (45, 0. 0, 0. 0, 1. 0);
glBegin (GL_POLYGON);
glVertex2f (-0. 6, -0. 1);
glVertex2f (-0. 6, 0. 4);
glVertex2f (-0. 1, 0. 4);
glVertex2f (-0. 1, -0. 1);
glEnd; glRotatef (-45, 0. 0, 0. 0, 1. 0);

Этот пример очень занимателен и вот почему. Удалим восстановление угла поворота и запустим приложение. Увидим не ромб, а квадрат. При внимательном рассмотрении обнаружим, что квадрат был повернут дважды Произошло это потому, что сразу после появления окна на экране (функция API showWindow) происходит его перерисовка (функция API updateWindow). Если вы были внимательны, то могли заметить, что такой же эффект наблюдался и в предыдущем примере.
При выполнении операции поворота можно спросить: поворачивается изображение или точка зрения? Мы будем для ясности считать, что поворачивается именно изображение. Следующий пример пояснит это.

Замечание
Точный ответ такой все объекты в OpenGL рисуются в точке отсчета системы координат, а команда glRotate осуществляет поворот системы координат.

Нарисуем две фигуры: квадрат и ромб, причем ромб получим путем поворота квадрата. Текст программы будет такой (проект из подкаталога Ex54):

glRotatef (45, 0. 0, 0. 0, 1. 0);
glBegin (GL_POLYGON);
glVertex2f (-0. 6, -0. 1);
glVertex2f (-0. 6, 0. 4);
glVertex2f (-0. 1, 0. 4);
glVertex2f (-0. 1, -0. 1);
glEnd;
glRotatef (-45, 0. 0, 0. 0, 1. 0);
glBegin (GL_POLYGON);
glVertex2f (0. 1, -0. 1);
glVertex2f (0. 1, 0. 4);
glVertex2f (0. 6, 0. 4);
glVertex2f (0. 6, -0. 1);
glEnd;

Точно так же нам придется поступать всегда, когда на экране присутствует несколько объектов, повернутых относительно друг друга: перед рисованием очередного объекта осуществлять поворот, а после рисования - возвращать точку зрения или осуществлять следующий поворот с учетом текущего положения точки зрения.
Пожалуйста, будьте внимательны! Начинающие пользователи OpenGL пoстоянно задают вопрос, как повернуть примитив, не поворачивая остальные примитивы. Еще один раз перечитайте предыдущий абзац В заключение разговора о повороте рассмотрите проект (подкаталог Ex55) основанный на примере с диском. При нажатой кнопке или движении кур, сора происходит перерисовка окна и поворот диска на 60 градусов.
Чтобы вы могли оценить преимущества использования "низкоуровневых" приемов, окно перерисовывается в этих случаях по-разному:

procedure TfrmGL. FormKeyPress(Sender: TObject; var Key: Char);
begin
Refresh
end;
procedure TfrmGL. FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
InvalidateRect(Handle, nil, False);
end;

При нажатии кнопки хорошо видно мерцание на поверхности окна, которого не появляется при движении указателя мыши по его поверхности.



Содержание раздела