14572

Ввод и взаимодействие с пользователем и анимация Взаимодействие с пользователем в OpenGL

Лабораторная работа

Информатика, кибернетика и программирование

Лабораторная работа №3 Ввод и взаимодействие с пользователем и анимация Взаимодействие с пользователем в OpenGL Функции библиотеки GLUT реализуют так называемый событийноуправляемый механизм. Это означает что есть некоторый внутренний цикл который запускается

Русский

2013-06-08

50.5 KB

15 чел.

Лабораторная работа №3

Ввод и взаимодействие с пользователем и анимация

Взаимодействие с пользователем в OpenGL

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

void glutDisplayFunc (void (*func) (void))

void glutReshapeFunc (void (*func) (int width, int height))

void glutMouseFunc (void (*func) (int button, int state, int x, int y))

void glutIdleFunc (void (*func) (void))

void glutKeyboardFunc(void (*func)(unsigned int key, int x, int y)

void glutMotionFunc(void (*func)(int x, int y));

void glutKeyboardFunc(void (*func)(unsigned int key, int x, int y);

 Определяет функцию (func), которая вызывается, когда нажата клавиша на клавиатуре. Возвращаемые параметры:

 key - сгенерированный клавиатурой ASCII код;

x,y – лоординаты положения мыши в координатах отображаемого окна, в момент, когда была нажата кнопка на клавиатуре.

void glutMouseFunc(void (*func)(int button, int state, int x, int y));

Определяет функцию, func, которая вызывается, когда кнопка мыши нажата или отпущена. Возвращаемый функцией параметр button может принимать значения GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, или GLUT_RIGHT_BUTTON. Значение параметра  state есть GLUT_UP или GLUT_DOWN в зависимости от того была ли кнопка мыши нажата или отпущена,  x and y параметры указывают на координаты в текущем окне, где находилась мышь в момент нажатия или отпускания кнопки.

void glutMotionFunc(void (*func)(int x, int y));

Определяет функцию, func, которая вызывается, когда указатель мыши перемещается в пределах окна принажатой одной или более кнопки, x and y параметры указывают на координаты в текущем окне, где находилась мышь в момент  начала события

void glutPostRedisplay(void);

Отмечает текущее окно как требующее перерисовки. На следующем шаге работы программы будет вызвана функция, зарегистрированная в gflutDisplayFunc()

void glutIdleFunc (void (*func) (void))

glutIdleFunc() задает функцию, которая будет вызываться каждый раз, когда нет событий от пользователя.

Видовое преобразование

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

(x-, y-, z-, 1)T =M * (x, y, z, 1)T

где M матрица видового преобразования. Перспективное преобразование и проектирование производится аналогично. Сама матрица может быть создана с помощью следующих команд:

void glTranslate[f d](GLtype x, GLtype y, GLtype z)

void glRotate[f d](GLtype angle, GLtype x, GLtype y, GLtype z)

void glScale[f d](GLtype x, GLtype y, GLtype z)

glTranlsate..() производит перенос объекта, прибавляя к координатам его вершин значения своих параметров.

glRotate..() производит поворот объекта против часовой стрелки на угол angle (измеряется в градусах) вокруг вектора ( x,y,z ).

glScale..() производит масштабирование объекта (сжатие или растяжение), домножая соответствующие координаты его вершин на значения своих параметров.

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

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

void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz)

где точка ( eyex,eyey,eyez ) определяет точку наблюдения, ( centerx, centery, centerz )задает центр сцены, который будет проектироваться в центр области вывода, а вектор ( upx,upy,upz ) задает положительное направление оси у, определяя поворот камеры. Если, например, камеру не надо поворачивать, то задается значение (0,1,0), а со значением (0,-1,0) сцена будет перевернута.

Фактически, эта команда совершает перенос и поворот объектов сцены, но в таком виде задавать параметры бывает удобнее.

Анимация

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

Эту проблему можно решить с использованием двойной буферизации- стандартной технологии организации компьютерной анимации. В этом случае в нашем распоряжении имеется два буфера кадра, которые принято называть рабочим и фоновым. Рабочий буфер- это тот, из которого выполняется регенерация изображения на экране, а в фоновом буфере изображение формируется программой. По командам из прикладной программы можно переключать функции буферов: сделать рабочим тот, который ранее был фоновым, а фоновым- тот, который ранее был рабочим. Механизм двойной буферизации устанавливается в процессе инициализации аргументом функции glutInitDisplayMode(). Вместо константы GLUT_SINGLE нужно задать константу GLUT_DOUBLE. Переключение буферов выполняется функцией glutSwapBuffers(). Все операторы формирования изображения включатся в функцию display(), но при использовании этой двойной буферизации в этой функции сначала нужно очистить рабочий буфер, вызвав команду glClear(), а последним оператором вызвать функцию переключения буферов glutSwapBuffers().

Структура приложения, использующего анимацию, будет следующей:

#include <GL/glut.h>
void MyIdle(void){
//--Код, который меняет переменные, определяющие следующий кадр--//
....
};
void
display(void){
//--Код OpenGL, который отображает кадр --//
....
//-- После рисования переставляем буфера --//
glutSwapBuffers();
};
void main(int argcp, char **argv){
//-- Инициализация GLUT --//
glutInit(&argcp, argv);
glutInitWindowSize(640, 480);
glutInitWindowPosition(0, 0);
//--Открытие окна--//
glutCreateWindow("My OpenGL Application");
//-- Выбор режима:Двойной буфер и RGBA цвета --//
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
//-- Регистрация вызываемых функций --//
glutDisplayFunc(
display);
glutIdleFunc(MyIdle);
//-- Запуск механизма обработки событий --//
glutMainLoop();

}

Программа рисования вращающегося квадрата

#include <GL/glut.h>

#include <stdlib.h>

static GLfloat spin = 0.0;

void spinDisplay(void)

{

   spin = spin + 2.0;

  if (spin > 360.0)

     spin = spin - 360.0;

  glutPostRedisplay();

}

void display(void)

{

  glClear(GL_COLOR_BUFFER_BIT);

  glPushMatrix();

  glRotatef(spin, 0.0, 0.0, 1.0);

  glColor3f(1.0, 1.0, 1.0);

  glBegin(GL_POLYGON);

glVertex2f(-25.0,-25.0);

glVertex2f(25.0,-25.0);

glVertex2f(25.0,25.0);

glVertex2f(-25.0,25.0);

glEnd( );

  glPopMatrix();

  glutSwapBuffers();

}

void init(void)

{

  glClearColor (0.0, 0.0, 0.0, 0.0);

  glShadeModel (GL_FLAT);

}

void reshape(int w, int h)

{

  glViewport (0, 0, (GLsizei) w, (GLsizei) h);

  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();

  glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);

  glMatrixMode(GL_MODELVIEW);

  glLoadIdentity();

}

int main(int argc, char** argv)

{

  glutInit(&argc, argv);

  glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);

  glutInitWindowSize (250, 250);

  glutInitWindowPosition (100, 100);

  glutCreateWindow (argv[0]);

  init ();

  glutDisplayFunc(display);

  glutReshapeFunc(reshape);

  glutIdleFunc(spinDisplay);

  glutMainLoop();

  return 0;   /* ANSI C requires main to return int. */

}

Порядок выполнения лабораторной работы

  1.  Ввести и отладить программу рисования вращающегося квадрата.
  2.  Изменить программу п.1 таким образом, чтобы она управлялась нажатием клавиш на клавиатуре- при нажатии клавиши “x”, квадрат вращается, при нажатии клавиши “X”- вращение прекращается, при нажатии клавиши “Esc”- программа завершает своя работу.
  3.  Изменить программу п.1 таким образом, чтобы она управлялась нажатием клавиши мыши - при нажатии левой клавиши- квадрат вращается, при нажатии правой клавиши- вращение прекращается.


 

А также другие работы, которые могут Вас заинтересовать

8637. Западная философия 19 века (философия жизни, экзистенциализм, позитивизм, психоанализ) 174.5 KB
  Западная философия 19 века (философия жизни, экзистенциализм, позитивизм, психоанализ) Вопросы: 1. Сформулируйте основной тезис экзистенциализма. Какие виды экзистенциализма следует различать? 2. Раскройте содержание основных принципов экзисте...
8638. Философия античности. Диалектика мифа. Квантовая теория и истоки учения об атоме и другие 305.5 KB
  Философия античности. Лосев А.Ф.Диалектика мифа. Гейзенберг. В.Квантовая теория и истоки учения об атоме. Платон: Природа души и ее свойства. Мир идеей и его познание. Теоретическое знание и философское познание. Философия как стремление...
8639. Философия Ренессанса. Гайденко П.П. Культура эпохи Возрождения. И другие 214.5 KB
  Философия Ренессанса. Гайденко П.П. Культура эпохи Возрождения. Джованни Пико делла Мирандола. Речь о достоинстве человека. Никколо Макиавелли. Государь. Лосев А.Ф. Бытовые типы Возрождения. Оборотная сторона титанизма. Гайденко П.П. Культура ...
8640. Немецкая классическая философия. Теория познания. Нравственная философия 263.5 KB
  Немецкая классическая философия. И. Кант: Теория познания. Нравственная философия. Г.В.Ф. Гегель: Наука логики. О природе диалектического. Всемирная история. В конце XVIII – XIX вв. в Германии наступил расцвет философии, который можно сравнит...
8641. Философия Нового времени и Просвещения. Экспериментальный метод научного познания 158 KB
  Философия Нового времени и Просвещения. Черникова И.В. Механизм – образ природы Нового времени. Рене Декарт: Научное познание: методология рационализма. Интеллектуальная интуиция. Френсис Бэкон: Цель научного познания. Экспериментальный метод н...
8642. Философия Средневековья. Августин Аврелий и Фома Аквинский 225 KB
  Философия Средневековья. Августин Аврелий и Фома Аквинский: О философии. Поиск Бога и доказательство Его бытия. Теодицея: причины возникновения зла в мире. Теория познания: вера и разум. Августин Аврелий. Время и вечность. Библия. Первая книга ...
8643. Определение философии. Речь Гегеля. Энциклопедия философских наук 181 KB
  Определение философии. Гегель Г.В.Ф. Речь Гегеля. Энциклопедия философских наук. Соловьев Вл. Исторические дела философии. Хайдеггер М. Основные понятия метафизики. Мамардашвили М.К. Философия - это сознание вслух. Г.В.Ф. Гегель (1770 - 18...
8644. Античная греческая философия 92.5 KB
  Античная греческая философия. ПЛАН 1. Становление античной философии. Философия досократиков (Милетская школа, Пифагор, Гераклит, Элейская школа, Демокрит). Философия классической эпохи (Софисты, Сократ, Платон, Аристотель). Фи...
8645. Основные направления современной западной философии 104 KB
  Основные направления современной западнойфилософии. План 1. Философия позитивизма: этапы развития 2. Прагматизм 3. Герменевтика 4.Сциентизм и антисциентизм 5.Философия жизни 6.Психоанализ и неофрейдизм 7. Экзистенциализм Позитивизм (от л...