Китай |
Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 21:
Непрограммируемый конвейер в OpenGL
Упражнение 3. Модель полого бруска в перспективной проекции (Perspect)
Перейдем к перспективной проекции отсекающего объема.
- Через панель Solution Explorer добавьте к проекту новый заголовочный файл с именем Perspect.h
- Наполните этот файл следующим кодом, который будет определять перспективный отсекающий объем видимости
//********************************************************** // Прототипы void ChangeSizePerspect(int, int); // При изменении размеров окна void Perspect(); void RenderScenePerspect(void); //********************************************************** // Упражнение 3: "3) Брусок в перспективной проекции" void Perspect() { float fZ,bZ; fZ = 100.0f; bZ = -100.0f; // Сбрасываем матрицу преобразования модели в значение единичной матрицы glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Отодвигаем всю сцену назад по оси z // чтобы видеть ее glTranslatef(0.0f, 0.0f, -300.0f); // Поворачиваем сцену на угол, определяемый клавишами-стрелками glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); // Устанавливаем цвет рисования красный glColor3f(1.0f, 0.0f, 0.0f); glBegin(GL_QUADS); // Рисуем наружнюю сторону // Нормаль по оси Z glNormal3f(0.0f, 0.0f, 1.0f); // Левая грань glVertex3f(-50.0f, 50.0f, fZ); glVertex3f(-50.0f, -50.0f, fZ); glVertex3f(-35.0f, -50.0f, fZ); glVertex3f(-35.0f,50.0f,fZ); // Правая грань glVertex3f(50.0f, 50.0f, fZ); glVertex3f(35.0f, 50.0f, fZ); glVertex3f(35.0f, -50.0f, fZ); glVertex3f(50.0f,-50.0f,fZ); // Верхняя грань glVertex3f(-35.0f, 50.0f, fZ); glVertex3f(-35.0f, 35.0f, fZ); glVertex3f(35.0f, 35.0f, fZ); glVertex3f(35.0f, 50.0f,fZ); // Нижняя грань glVertex3f(-35.0f, -35.0f, fZ); glVertex3f(-35.0f, -50.0f, fZ); glVertex3f(35.0f, -50.0f, fZ); glVertex3f(35.0f, -35.0f,fZ); // Левая верхняя секция // Нормаль по оси Y glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-50.0f, 50.0f, fZ); glVertex3f(50.0f, 50.0f, fZ); glVertex3f(50.0f, 50.0f, bZ); glVertex3f(-50.0f,50.0f,bZ); // Верхняя секция glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(-50.0f, -50.0f, fZ); glVertex3f(-50.0f, -50.0f, bZ); glVertex3f(50.0f, -50.0f, bZ); glVertex3f(50.0f, -50.0f, fZ); // Левая секция glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f(50.0f, 50.0f, fZ); glVertex3f(50.0f, -50.0f, fZ); glVertex3f(50.0f, -50.0f, bZ); glVertex3f(50.0f, 50.0f, bZ); // Правая секция glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-50.0f, 50.0f, fZ); glVertex3f(-50.0f, 50.0f, bZ); glVertex3f(-50.0f, -50.0f, bZ); glVertex3f(-50.0f, -50.0f, fZ); glEnd(); glFrontFace(GL_CW); // Лицевыми будем считать те грани, вершины // которых обходятся по часовой стрелки // для рисования задней стенки glBegin(GL_QUADS); // Рисуем внутреннюю сторону // Нормаль по оси Z glNormal3f(0.0f, 0.0f, -1.0f); // Левая грань glVertex3f(-50.0f, 50.0f, bZ); glVertex3f(-50.0f, -50.0f, bZ); glVertex3f(-35.0f, -50.0f, bZ); glVertex3f(-35.0f,50.0f,bZ); // Правая грань glVertex3f(50.0f, 50.0f, bZ); glVertex3f(35.0f, 50.0f, bZ); glVertex3f(35.0f, -50.0f, bZ); glVertex3f(50.0f,-50.0f,bZ); // Верхняя грань glVertex3f(-35.0f, 50.0f, bZ); glVertex3f(-35.0f, 35.0f, bZ); glVertex3f(35.0f, 35.0f, bZ); glVertex3f(35.0f, 50.0f,bZ); // Нижняя грань glVertex3f(-35.0f, -35.0f, bZ); glVertex3f(-35.0f, -50.0f, bZ); glVertex3f(35.0f, -50.0f, bZ); glVertex3f(35.0f, -35.0f,bZ); // Внутренняя часть glColor3f(0.75f, 0.75f, 0.75f); // Серый // Нормаль по оси Y glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-35.0f, 35.0f, fZ); glVertex3f(35.0f, 35.0f, fZ); glVertex3f(35.0f, 35.0f, bZ); glVertex3f(-35.0f,35.0f,bZ); // Нижняя секция glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-35.0f, -35.0f, fZ); glVertex3f(-35.0f, -35.0f, bZ); glVertex3f(35.0f, -35.0f, bZ); glVertex3f(35.0f, -35.0f, fZ); // Левая секция glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f(-35.0f, 35.0f, fZ); glVertex3f(-35.0f, 35.0f, bZ); glVertex3f(-35.0f, -35.0f, bZ); glVertex3f(-35.0f, -35.0f, fZ); // Правая секция glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(35.0f, 35.0f, fZ); glVertex3f(35.0f, -35.0f, fZ); glVertex3f(35.0f, -35.0f, bZ); glVertex3f(35.0f, 35.0f, bZ); glEnd(); // Возвращаем обход сторон к значению по умолчанию glFrontFace(GL_CCW); // Переключаем буфер кадра glutSwapBuffers(); } //********************************************************** void ChangeSizePerspect(int width, int height) { // Предотвращаем деление на нуль if(height == 0) height = 1; // Устанавливаем поле просмотра с размерами окна glViewport(0, 0, width, height); // Устанавливаем размеры перспективы (отсекающего объема) // (left, right, bottom, top, near, far) GLfloat aspectRatio = (GLfloat)width / (GLfloat)height;// Для коррекции // Устанавливает матрицу преобразования в режим проецирования glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Устанавливаем перспективную проекцию gluPerspective(60.0f, aspectRatio, 0.5, 400.0); // Восстановливает матрицу преобразования в исходный режим вида glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } //********************************************************** // Функция обратного вызова для рисования сцены void RenderScenePerspect(void) { // Сбрасываем буферы цвета и глубины glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Рисуем сцену Perspect(); // Прокачка сообщений glFlush(); }Листинг 21.14. Код файла Perspect.h реализации модели полого бруска в перспективной проекции
//********************************************************** // Подключение стандартного файла с библиотекой OpenGL #include "stdafx.h" //********************************************************** // Прототипы функций void ExecuteMenu(int); // Контекстное меню первого уровня void TimerFunc(int); // Обработчик события таймера void SetupRC(void); // Начальные настройки OpenGL void SpecialKeys(int, int, int); // Обработка нажатия клавиш void RenderScene(void); void ChangeSize(int, int); // Глобальная переменная выбранного варианта основного меню int choice = 1; // Глобальные переменные для создания вращения // в градусах GLfloat xRot = 0.0f; GLfloat yRot = 0.0f; GLint w, h; // Ширина и высота экрана //********************************************************** // Подключение файлов с упражнениями #include "Atom.h" // Упражнение: "1) Простая модель атома" #include "Ortho.h" // Упражнение 2: "2) Брусок в ортогональной проекции" #include "Perspect.h" // Упражнение 3: "3) Брусок в перспективной проекции" //********************************************************** // Функция обратного вызова обработки выбора пользователя void ExecuteMenu(int choice) { // Сбрасываем углы вращения прежнего варианта xRot = yRot = 0; // Запоминаем выбор в глобальную переменную ::choice = choice; switch(::choice) { case 1: ChangeSizeAtom(w, h); break; case 2: ChangeSizeOrtho(w, h); break; case 3: ChangeSizePerspect(w, h); break; } // Вызвать принудительно визуализацию glutPostRedisplay(); } //********************************************************** // Функция обратного вызова для рисования сцены void RenderScene(void) { switch(::choice) { case 1: SetupLight(false); RenderSceneAtom(); break; case 2: SetupLight(true); RenderSceneOrtho(); break; case 3: SetupLight(true); RenderScenePerspect(); break; } } //********************************************************** // Вызывается библиотекой GLUT при изменении размеров окна void ChangeSize(int width, int height) { w = width; h = height; switch(::choice) { case 1: ChangeSizeAtom(width, height); break; case 2: ChangeSizeOrtho(width, height); break; case 3: ChangeSizePerspect(width, height); break; } } //********************************************************** // Обработчик события таймера void TimerFunc(int value) { glutPostRedisplay(); // Перерисовка сцены glutTimerFunc(100, TimerFunc, 1); // Заряжаем новый таймер } //********************************************************** // Устанавливается состояние инициализации void SetupRC(void) { glClearColor(0.0F, 0.0F, 0.0F, 1.0F);// Фон черный непрозрачный glEnable(GL_DEPTH_TEST); // Включили проверку глубины glFrontFace(GL_CCW); // Лицевыми будем считать те грани, вершины // которых обходятся против часовой стрелки glEnable(GL_CULL_FACE); // Включили режим отсечения сторон } //********************************************************** // Управление с клавиатуры стрелками // для задания новых значений матрицы поворота void SpecialKeys(int key, int x, int y) { if(key == GLUT_KEY_UP) // Стрелка вверх xRot -= 5.0f; if(key == GLUT_KEY_DOWN)// Стрелка вниз xRot += 5.0f; if(key == GLUT_KEY_LEFT)// Стрелка влево yRot -= 5.0f; if(key == GLUT_KEY_RIGHT)// Стрелка вправо yRot += 5.0f; xRot = (GLfloat)((const int)xRot % 360); yRot = (GLfloat)((const int)yRot % 360); // Вызвать принудительно визуализацию с помощью RenderScene() glutPostRedisplay(); } //********************************************************** void main(int argc, char* argv[]) { glutInit(&argc, argv); // Двойная буферизация, цветовая модель RGB, буфер глубины glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(300, 300); // Начальные размеры окна glutCreateWindow("Матричные преобразования"); // Заголовок окна glutDisplayFunc(RenderScene); // Обновление сцены при разрушении окна glutReshapeFunc(ChangeSize); // При изменении размера окна glutTimerFunc(100, TimerFunc, 1); // Создали таймер SetupRC(); glutSpecialFunc(SpecialKeys); // Для управления с клавиатуры // Создание меню и добавление опций выбора glutCreateMenu(ExecuteMenu); glutAddMenuEntry("1) Простая модель атома", 1); glutAddMenuEntry("2) Брусок в ортогональной проекции", 2); glutAddMenuEntry("3) Брусок в перспективной проекции", 3); glutAttachMenu(GLUT_RIGHT_BUTTON);// Присоединяем // Конец создания меню glutMainLoop(); // Цикл сообщений графического окна }Листинг 21.15. Код файла ProjectionMatrix.cpp после добавления третьего упражнения
- Запустите приложение, повращайте брусок и отметьте, что при перспективной проекции изделие кажется более реалистичным
- Попытайтесь разобраться с кодом!!!