Модель манипулятора робота
Манипулятор робота на экране изображается в виде нескольких каркасных параллелепипедов (по одному для каждого сегмента манипулятора – "плечо", "локоть", "кисть", "пальцы"). Предполагается, что в местах соединения сегментов расположены шарниры и сегменты могут вращаться вокруг них. На рис. 2.2 и рис. 2.3 показаны манипуляторы с разным количеством сегментов.
Перед рисованием каждого сегмента надо выполнить модельное преобразование, обеспечивающее корректную ориентацию сегмента. При рисовании параллелепипеда его центр располагается в начале модельной системы координат, поэтому предварительно надо сместить модельную систему координат на половину длины сегмента. Если этого не сделать, то сегмент будет вращаться вокруг своего центра, а не вокруг шарнира. После вызова glTranslated(), который задает положение шарнира, надо вызвать glRotated() для поворота сегмента. После этого надо выполнить перенос в обратном направлении для правильного позиционирования центра сегмента. В целом, для рисования одного сегмента надо вызвать следующие функции:
glTranslatef(-1.0, 0.0, 0.0); glRotatef((float)shoulder_angle, 0.0, 0.0, 1.0); glTranslatef(1.0, 0.0, 0.0); auxWireBox(2.0, 0.4, 1.0);
Для рисования второго сегмента надо переместить модельную систему координат в позицию второго шарнира. Т.к. координатная система уже была повернута, то ось X направлена в направлении первого сегмента. Следовательно, для переноса модельной системы координат в точку второго шарнира надо произвести перенос вдоль оси X. После этого можно нарисовать второй сегмент (функциями, аналогичными использованным для рисования первого сегмента):
glTranslatef(1.0, 0.0, 0.0); glRotatef((float)elbow_angle, 0.0, 0.0, 1.0); glTranslatef(1.0, 0.0, 0.0); auxWireBox(2.0, 0.4, 1.0);
Описанную процедуру можно продолжать повторять, чтобы нарисовать все сегменты манипулятора (плечо, локоть, кисть, пальцы). Рисование двух сегментов манипулятора с двумя степенями свободы показано в программе 2.3. Поворот сегментов осуществляется с помощью клавиш курсора.
#include <windows.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glaux.h>
void CALLBACK resize(int width, int height); void CALLBACK display(); void CALLBACK elbowAdd(); void CALLBACK elbowSubtract(); void CALLBACK shoulderSubtract(); void CALLBACK shoulderAdd();
// Текущие углы поворота плеча и локтя int shoulder = 0, elbow = 0;
void main() { // Создание экранного окна auxInitDisplayMode(AUX_RGBA | AUX_DEPTH | AUX_DOUBLE); auxInitPosition(50, 10, 400, 400); auxInitWindow("Лекция 2, Программа 2.3");
// Включение ряда параметров OpenGL glEnable(GL_ALPHA_TEST); glEnable(GL_DEPTH_TEST); glEnable(GL_COLOR_MATERIAL); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LIGHTING);
// Включение максимального рассеянного освещения float ambient[4] = { 1.0, 1.0, 1.0, 1 }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
// Регистрация обработчиков событий auxReshapeFunc(resize); auxKeyFunc(AUX_LEFT, shoulderSubtract); auxKeyFunc(AUX_RIGHT, shoulderAdd); auxKeyFunc(AUX_UP, elbowAdd); auxKeyFunc(AUX_DOWN, elbowSubtract);
// Вход в главный цикл GLAUX auxMainLoop(display); }
void CALLBACK resize(int width, int height) { glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (float)width/(float)height, 1.0, 20.0);
gluLookAt(0,0,10, 0,0,0, 0,1,0);
glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }
void CALLBACK display() { // Очистка буфера кадра glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glPushMatrix(); glTranslatef(-1.0, 0.0, 0.0); glRotatef((float)shoulder, 0.0, 0.0, 1.0); glTranslatef(1.0, 0.0, 0.0); auxWireBox(2.0, 0.4, 1.0); // плечо
glTranslatef(1.0, 0.0, 0.0); glRotatef((float)elbow, 0.0, 0.0, 1.0); glTranslatef(1.0, 0.0, 0.0); auxWireBox(2.0, 0.4, 1.0); // локоть glPopMatrix();
// Копирование содержимого буфера кадра на экран glFlush(); auxSwapBuffers(); }
void CALLBACK elbowAdd() { elbow = (elbow + 5) % 360; }
void CALLBACK elbowSubtract()
{ elbow = (elbow - 5) % 360; }
void CALLBACK shoulderAdd() { shoulder = (shoulder + 5) % 360; }
void CALLBACK shoulderSubtract() { shoulder = (shoulder - 5) % 360; } Программа 2.3. Модель манипулятора робота.
Сводка результатов Для создания плавной анимации применяется метод "двойная буферизация". При этом используются два буфера кадра: один показывается на экране, а в другом, невидимом, выполняется рисование следующего кадра. В макете консольной программы, написанной с помощью библиотеки GLAUX, используются функции обратной связи. Чаще всего это функция отображения сцены, фоновая функция и функция реакции на изменение размеров окна. Кроме того, можно определить функции-обработчики событий от клавиатуры и мыши. При создании анимации с несколькими движущимися объектами важно правильно построить композицию преобразований модельной системы координат. В лекции приведены два примера подобных моделей.
Упражнения Упражнение 1 Внесите в программу 2.1 изменения, описанные в п.2.1, чтобы по нажатию левой кнопки мыши менялся цвет вращающегося чайника. Упражнение 2 В программу из упр.1 добавьте обработчик нажатия правой кнопки мыши для включения/выключения вращения. Сделайте обработчики для клавиш курсора "стрелка вверх" и "стрелка вниз" (коды клавиш AUX_LEFT и AUX_UP), чтобы увеличивать и уменьшать скорость вращения. С помощью обработчика клавиши "пробел" (код AUX_SPACE) обеспечьте циклическое переключение осей вращения между тремя координатными осями. Подсказка: можно завести глобальную переменную-флаг, обозначающую, включено вращение или нет. Переключение флага следует выполнять в обработчике события. В зависимости от состояния флага в функции фоновой обработки должно или не должно выполняться увеличение угла поворота. Аналогичные приемы используйте при написании обработчиков остальных событий. Упражнение 3 В программу 2.2 добавьте отображение спутника планеты и наклоните ось вращения планеты под углом 45 градусов к плоскости ее орбиты. Упражнение 4 Сделайте вариант программы 2.2 с 4-мя планетами и 3-мя спутниками. Для сохранения/восстановления позиции и ориентации координатных систем пользуйтесь функциями glPushMatrix() и glPopMatrix(). Чтобы нарисовать несколько спутников у одной планеты, сохраняйте параметры координатной системы перед рисованием каждого спутника и восстанавливайте их после рисования спутника. Чтобы разобраться с положением координатных осей, можете применить функцию рисования осей из 4-го упражнения к 1-й лекции.
Упражнение 5 Измените программу 2.3 так, чтобы она рисовала манипулятор из 10-ти сегментами (рис. 2.3). Для поворота всех сегментов применяйте две клавиши курсора "стрелка вверх/вниз". Текущий сегмент (который будет поворачиваться этими клавишами) должен быть выделен цветом. Переключение текущего сегмента должно производиться циклически по нажатию пробела. Подсказка: для сохранения и восстановления позиции и ориентации координатной системы, связанной с кистью манипулятора, применяйте функции glPushMatrix() и glPopMatrix(). При рисовании пальцев перед позиционированием каждого пальца сохраняйте текущую видовую матрицу, а после рисования – восстанавливайте ее.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|