Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
4. Преобразование координат.doc
Скачиваний:
9
Добавлен:
09.11.2019
Размер:
706.05 Кб
Скачать

4.7.2. Функции OpenGl для работы со стеком

Прежде чем разобрать несколько примеров, использующих понятие ЛСК полезно ознакомиться с функциями OpenGL для работы со стеком матриц.

В OpenGL стеков несколько. Текущий из них всегда только один, он устанавливается вместе с установкой текущей матрицы. Например, функция glMatrixMode(GL_MODELVIEW) установит текущей матрицу VM и одновременно в качестве текущего будет установлен стек матрицы VM, глубина такого стека – 32. При вызове функции установки режима с параметром GL_PROJECTION текущим будет установлен стек матрицы проецирования. Глубина такого стека – 2.

Функция, прототип которой void glPushMatrix(void), проталкивает текущую матрицу в стек матриц. При этом текущая матрица остается в вершине стека. (Текущая матрица всегда в вершине стека.) При вталкивании она копируется на уровень ниже. Верхняя сохраняется.

Функция, прототип которой void glPopMatrix(void), выталкивает данные из текущего стека матриц, замещая текущую матрицу на ту, что находится под ней.

Примечание. Если функция glPushMatrix() не используется, то считается, что в вершине стека находится текущая матрица. В этом случае ошибкой будет ее выталкивать.

4.7.3. Примеры программ с использованием понятия «локальная система координат»

В листинге 4.1 приводится текст программы, решающий следующую задачу. Точка вращается вокруг произвольной точки (ax, ay) в МСК. Вращающаяся точка задается своим положением (a1x, a1y) относительно центра вращения.

В программе создается функция myFig1(), где точка (a1x, a1y) считается заданной в ЛСК и вращается вокруг начала координат ЛСК.

Функция myDisplay() помещает ЛСК в положение (ax, ay) МСК и затем вызывает функцию myFig1(). При этом осуществляется преобразование координат вращающейся в ЛСК точки в систему координат МСК.

Листинг 4.1. Точка вращается вокруг произвольной точки.

#include <stdio.h>

#include <windows.h>

#include <math.h>

#include <GL/glut.h>

float R=640.0/480; //Устанавливается форматное соотношение

float w=640; //Ширина порта просмотра

float df=2; //Приращение угла поворота

float ax=25, ay=25; //Центр вращения в МСК

float alx=100, aly=0; //Начальное положение вращающейся точки в ЛСК

int k=0;

float h, l, r, b, t, f=0;

//Эта функция сохраняет форматное соотношение порта просмотра при

//событиях изменения размеров экранного окна

void myReshape(int W, int H)

{

if (R>W/H) glViewport(0,0,W,W/R);

else glViewport(0,0,H*R,H);

}

void myInit(void) //Функция инициализации

{

h=w/R; l=-w/2; r=w/2; b=-h/2; t=h/2;

glClearColor(1.0, 0.7, 0.7, 0.0);

glPointSize(6.0);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(l, r, b, t);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

//Координатные оси в МСК

void myFig0(void)

{

glBegin(GL_LINES);

glVertex2f(0, b);

glVertex2f(0, t);

glVertex2f(l, 0);

glVertex2f(r, 0);

glEnd();

}

//Вращающаяся точка и ее вектор в ЛСК

void myFig1(void)

{ glRotated(f, 0, 0, 1);

glBegin(GL_POINTS);

glVertex2f(0, 0); //Центр вращения в ЛСК

glVertex2f(alx, aly); //Положение вращающейся точки в ЛСК

glEnd();

//Вектор, соединяющий вращающуюся точку с началом ЛСК

glBegin(GL_LINES);

glVertex2f(0.0, 0.0);

glVertex2f(alx, aly);

glEnd();

f+=df;

if (abs(f)>=360) f=0;

}

void myDisplay(void)

{

glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.0f, 0.0f, 1.0f);

myFig0(); // VM = 1, рисуются координатные оси МСК

glPushMatrix(); // VM = 1, сохраняется в стеке

glTranslated(ax, ay, 0); // VM = T, привязка ЛСК к МСК

glColor3f(1.0, 0.0, 0.0);

myFig1();

glPopMatrix(); // Восстанавливается VM = 1

glutSwapBuffers(); // Переключение буферов

Sleep(5);

}

void main(int argc, char **argv)

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

glutInitWindowSize(640, 480);

glutInitWindowPosition(20, 20);

glutCreateWindow(“Myprog”);

glutReshapeFunc(myReshape);

glutDisplayFunc(myDisplay);

glutIdleFunc(myDisplay);

myInit();

glutMainLoop();

}

В листинге 4.2 приводится текст программы, решающий следующую задачу. В функции myFig1() рисуется стрелка в ЛСК (рис. 4.18).

В функции myDisplay() устанавливается ЛСК поочередно в несколько положений, как на рис. 4.19 и каждый раз вызывается функция myFig1().

В результате фигура «стрелка» разместится на сцене как на рис. 4.19. При этом фигура «стрелка» создается в ЛСК только один раз, а ее положение и ориентация на сцене определяется привязкой ЛСК к МСК.

Листинг 4.2. Пример размещения объектов на сцене с использованием понятия «локальная система координат»

#include <stdio.h>

#include <windows.h>

#include <math.h>

#include <GL/glut.h>

float R=640.0/480; //Устанавливается форматное соотношение

float w=640; //Ширина порта просмотра

float h, l, r, b, t, f=0;

//Эта функция сохраняет форматное соотношение порта просмотра при

//событиях изменения размеров экранного окна

void myReshape(int W, int H)

{

if (R>W/H) glViewport(0,0,W,W/R);

else glViewport(0,0,H*R,H);

}

void myInit(void) // Функция инициализации

{

h=w/R; l=-w/2; r=w/2; b=-h/2; t=h/2;

glClearColor(1.0, 0.7, 0.7, 0.0);

glPointSize(6.0);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(l, r, b, t);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

//Координатные оси в МСК

void myFig0(void)

{

glBegin(GL_LINES);

glVertex2f(0, b);

glVertex2f(0, t);

glVertex2f(l, 0);

glVertex2f(r, 0);

glEnd();

}

void myFig1(void)

{

glBegin(GL_LINE_STRIP); // Рисуется стрелка в ЛСК

glVertex2f(0, 0);

glVertex2f(10.0, 0.0);

glVertex2f(5, 5);

glVertex2f(5, -5);

glVertex2f(10.0, 0.0);

glEnd();

}

void myDisplay(void)

{

glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.0f, 0.0f, 1.0f);

myFig0(); // VM = 1, рисуются координатные оси МСК

glPushMatrix(); // VM = 1, сохраняется в стеке

glTranslatef(25, 25, 0);

glRotatef(45, 0, 0, 1); // VM = TR, привязка ЛСК к МСК

myFig1(); // Рисуется fig1

glPopMatrix(); // Восстанавливается VM = 1

glPushMatrix(); // VM = 1, сохраняется в стеке

glTranslatef(-25, 25, 0);

glRotatef(135, 0, 0, 1); // VM = TR, привязка ЛСК к МСК

myFig1(); // Рисуется fig1

glPopMatrix(); // Восстанавливается VM = 1

glPushMatrix(); // VM = 1, сохраняется в стеке

glTranslated(-25, -25, 0);

glRotatef(225, 0, 0, 1); // VM = TR, привязка ЛСК к МСК

myFig1(); // Рисуется fig1

glPopMatrix(); // Восстанавливается VM = 1

glPushMatrix(); // VM = 1, сохраняется в стеке

glTranslated(25, -25, 0);

glRotatef(315, 0, 0, 1); // VM = TR, привязка ЛСК к МСК

myFig1(); // Рисуется fig1

glPopMatrix(); // Восстанавливается VM = 1

glFlush();

}

void main(int argc, char **argv)

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

glutInitWindowSize(640, 480);

glutInitWindowPosition(20, 20);

glutCreateWindow(“Myprog”);

glutReshapeFunc(myReshape);

glutDisplayFunc(myDisplay);

myInit();

glutMainLoop();

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]