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 таким образом, чтобы она управлялась нажатием клавиши мыши - при нажатии левой клавиши- квадрат вращается, при нажатии правой клавиши- вращение прекращается.


 

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

14835. АЛАШ ФИЛОСОФИЯСЫ ӘЛЕМ ҚАЗАҚТАРЫ МӘДЕНИЕТІ КОНТЕКСІНДЕ 41.5 KB
  Тұрдығұл Шаңбай Алаштану ғылымизерттеу орталығының директоры Семей мемлекеттік педагогикалық институты Философия және саясаттану кафедрасының меңгерушісі АЛАШ ФИЛОСОФИЯСЫ ӘЛЕМ ҚАЗАҚТАРЫ МӘДЕНИЕТІ КОНТЕКСІНДЕ Құрметті қауым Қадірлі қонақтар ...
14836. Алтын жүлге 45 KB
  Алтын жүлге Халық мұрасының қайнар көзі көне заман әндері жөніндегі толғам Тарихымызды жазуда пәлен айтты түген айтты деп неше түрлі қазақ жерлерінде жолшыбай болғандардың айтқан жазғандарына сүйеніп жүреміз. Әрине оларды жоққа шығарудан аулақпыз. Ол да кер...
14837. АР ТҮЗЕЙТІН БІР ҒЫЛЫМ ТАБЫЛМАСА 39.5 KB
  АР ТҮЗЕЙТІН БІР ҒЫЛЫМ ТАБЫЛМАСА Шәкәрімнің танымдық әлеміне Абай мұрасы арқылы кіру ұтымды боларына айрықша ден қою керек өйткені бұл жол жантану ілімін танып білуде адастырмас темірқазығымыз. Екі ой алыбы өз туындыларында қазақтың қоғамдық ой санасындағы шеш...
14838. Тақырыбы: Аристотель 69.5 KB
  Тақырыбы: Аристотель Аристотель грекше: Ἀριστοτέλης Aristotélēs б.з.д. 384 б.з.д. 322 жылдар грек пәлсапашысы Платонның шәкірті Ұлы Александрдың ұстазы. Ол түрлітүрлі та
14839. Атлантида Ол қандай болған 52 KB
  Атлантида Ол қандай болған Сократ тыңда мені. Бұл таңғажайып ертегі емес түпкі жағында негіз бар әңгіме. Ол жөнінде жеті дананың данасы атанған Солон баян етіпті. Ол біздің арғы атамыз Дропидтің жақын туысы онымен аз уақыт болса да бірге болған достасқан адам. Ол до
14840. ДОМБЫРА ФИЛОСОФИЯСЫ 61 KB
  ДОМБЫРА ФИЛОСОФИЯСЫ Домбыра қазақтың жаны. Ол тар жол тайғақ кешу жолдарын бастан өткерген қазақ тарихын парақтауға негiз бола алады. Ұлтымыздың болмысына куә болған әдетғұрпы мен салтдәстүрлерiне жан бiтiрiп оның құнды қалпын сақтауға негiз болғанын көремiз. Бұл
14841. Көне түрік жазбаларындағы алғы философиялық ойлар 63 KB
  Көне түрік жазбаларындағы алғы философиялық ойлар Қазақтың ататегі болып табылатын сақтар ғұндар үйсіндердің түп төркіндеріндегі қарамақайшылықтарға қарамастан көшпенділк әмбебапшылығы басымдылыққа ие болды. Солай бола тұра жер өңдеушілерді
14842. ҚАЗАҚ БАТЫРЛАРЫНЫҢ НАНЫМ - СЕНІМДЕРІ МЕН МОРАЛЬДЫҚ ЭТИКАСЫ 50.5 KB
  ҚАЗАҚ БАТЫРЛАРЫНЫҢ НАНЫМ СЕНІМДЕРІ МЕН МОРАЛЬДЫҚ ЭТИКАСЫ С.Г.Есенов Ғылыми жетекшісі: т.ғ.к. Каримов М.К. Семей қаласы М.О.Әуезов атындағы Семей университеті. Қазақтың этноргафиялық суреттерінде кескінделген адам батыр бейнесі негізінен өте қарапайым түрде...
14843. ҚАЗАҚ ӘДЕБИЕТІНДЕГІ ДАНАЛЫҚ ҮРДІС 63.5 KB
  ҚАЗАҚ ӘДЕБИЕТІНДЕГІ ДАНАЛЫҚ ҮРДІС Г.Ә.Өтетілеуова Г.Ә.Мұраталиева Ыбырайым Сүлейменов атындағы № 37 қазақ орта мектебі Тараз қ. Даналық адамды басыбүтін және үнемі баурайтын соңғы лебіз соңғы дау. Даналық өне бойы өткенге көз тастап тарихқа үңілумен болады...