Функции, устанавливающие отображаемый объем и положение наблюдателя в 3D
В OpenGL существуют стандартные функции для задания ортографической (параллельной) и перспективной проекций. Первый тип проекции может быть задан функцией
void glOrtho (GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f) Эта функция задает отображаемый объем как параллелепипед в системе координат наблюдателя СКe (xeyeze). Геометрический смысл параметров ясен из рис. 1. Параметры n и f задают расстояние до ближней и дальней плоскостей отсечения по удалению от точки (0, 0, 0) в отрицательном направлении. Параметры l, r, b, t, задают координаты левой, правой, нижней и верхней плоскостей отсечения. По умолчанию система координат наблюдателя совпадает с МСК (CKw). Функция создает матрицу Fep преобразования координат из СКe в систему координат канонического отображаемого объема (CKp). Канонический отображаемый объем – куб размерами 2´2´2 ед. CKp – левосторонняя система координат, помещенная в центре канонического отображаемого объема. Рис.1 поясняет сказанное.
Эта функция задает отображаемый объем как усеченную пирамиду в системе координат наблюдателя СКe (xeyeze). Геометрический смысл параметров ясен из рис. 2. Функция создает матрицу перспективного преобразования координат из СКe в СК1, при котором усеченная пирамида отображается как параллелепипед, а затем матрицу преобразования из СК1 в СКp. Т.о. результирующая матрица преобразования координат, создаваемая функцией, это матрица преобразования координат из СКe в CKp. Далее текущая матрица перемножается на созданную функцией и результат замещает текущую.
Существует более удобная модификация описанной выше функции. Это функция
void gluPerspective (GLdouble angle, GLdouble aspect, GLdouble n, GLdouble f).
В этой функции параметр angle – угол охвата (обзора), параметр aspect = w/h, параметры n и f ближняя и дальняя плоскости отсечения. Функция создает ту же матрицу Fep, что и функция glFrustum( ) и аналогично выполняется. При этом предварительно вычисляются
t = n*tg(p/180*angle/2);
b = -t; r = t*aspect; l = -r.
По умолчанию система координат наблюдателя СКe (xeyeze) совпадает с мировой системой координат СКw (МСК ). Возможно установить наблюдателя в любую позицию в МСК вызвав функцию
C(centerx, centery, centerz) – точка в CKw в которую направлен взгляд наблюдателя;
UP(upx, upy, upz) – вектор, задающий плоскость zeye и направление оси ze.
Система координат наблюдателя устанавливается таким образом:
N = E - C – вектор, задает направление оси ze;
U = UP ´ N - вектор, задает направление оси xe, векторное произведение;
V = N ´ U - вектор, задает направление оси ye.
Функция создает матрицу преобразования координат из CKw в CKe, перемножает текущую матрицу на созданную и текущую замещает результатом перемножения. На рис.4 показано как при этом размещается отображаемый объем в МСК при ортографическом проецировании, а на рис.5 – при перспективном проецировании.
Обработка событий
Функции библиотеки GLUT реализуют так называемый событийно-управляемый механизм. Это означает, что есть некоторый внутренний цикл, который запускается после соответствующей инициализации и обрабатывает одно за другим все события, объявленные во время инициализации. К событиям относятся: щелчок мыши, закрытие окна, изменение свойств окна, передвижение курсора, нажатие клавиши, и "пустое" (idle) событие, когда ничего не происходит. Для проведения периодической проверки совершения того или иного события надо зарегистрировать функцию, которая будет его обрабатывать. Для этого используются функции вида:
void glutDisplayFunc(void (*func) (void)) – регистрируется функция перерисовки экранного окна когда оно первоначально открывается, когда оно всплыло и его содержимое может быть повреждено, когда явно вызвана функция glutPostRedisplay( ).Для явного указания, что окно надо обновить, иногда удобно использовать функцию
void glutPostRedisplay(void).
void glutReshapeFunc (void (*func) (int width, int height)) – регистрируется функция, которая должна вызываться всякий раз, когда пользователем изменены размеры экранного окна. Функция func(width, height ) получает от ОС новые значения ширины и высоты экранного окна. Как правило func(width, height ) содержит вызов glViewport( ) с тем, чтобы порт просмотра уместить в новых размерах экранного окна и при этом по возможности сохранить пропорции рисуемого объекта.
void glutKeyboardFunc (void(*func)(unsigned int key, int x, int y)) - регистрируется функция, которая должна вызываться всякий раз, когда нажата клавиша, генерирующая символ ASCCI. Параметры key, x, y функция func() получает от ОС. Значения их следующие:key – значение ASCCI нажатой клавиши;x, y – координаты положения курсора «мыши» в момент, когда нажата клавиша.void glutMouseFunc (void (*func) (int button, int state, int x, int y)) – зарегистрированная функция вызывается при «мышиных» событиях. Значения параметров она получает от ОС. Эти параметры следующие:button – принимает значения GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON;state - принимает значения GLUT_UP (нажатие), GLUT_DOWN (отпускание);x, y – координаты курсора «мыши» в pix, x – число pix от левого края окна, y – число pix вниз от верха окна!
void glutIdleFunc(void (*func) (void)) - задает функцию, которая будет вызываться каждый раз, когда нет событий от пользователя.
void glutMotionFunc(void (*func)(int x, int y)) - регистрируется функция, которая должна вызываться, когда курсор «мыши» перемещается при одновременно нажатой одной или нескольких кнопках «мыши». Параметры x, y указывают местоположение курсора.
void glutPassiveMotionFunc(void (*func)(int x, int y)) - регистрируется функция, которая должна вызываться, когда курсор «мыши» перемещается и не нажато ни одной кнопки мыши. Параметры x, y указывают местоположение курсора.