Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 891 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00
Тема: Программирование
Специальности: Программист, Архитектор программного обеспечения
Теги:
Самостоятельная работа 21:
Непрограммируемый конвейер в OpenGL
Упражнение 4. Построение модели атома в перспективнойпроекции (Atom Perspect)
Переделаем нашу модель атома, построенную в " Упражнении 1 ", с использованием перспективной проекции.
- Через панель Solution Explorer добавьте к проекту новый заголовочный файл с именем AtomPerspect.h
- Скопируйте в файл AtomPerspect.h содержимое файла Atom.h и откорректируйте его следующим образом
//********************************************************** // Прототипы void AtomPerspect(); void RenderSceneAtomPerspect(void); void ChangeSizeAtomPerspect(int, int); // При изменении размеров окна void ShowOrbitPerspect(GLfloat radius); //********************************************************** // Упражнение 4: "4) Модель атома в перспективе" void AtomPerspect() { // Угол поворота вокруг ядра static GLfloat fElect = 0.0f; GLfloat radius; // Сбрасываем буфер цвета и глубины glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Сбрасываем матрицу наблюдения модели в значение единичной матрицы glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Отодвигаем всю сцену назад по оси z // чтобы видеть ее glTranslatef(0.0f, 0.0f, -250.0f); // Управление видом glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); // Красное ядро прямо по центру линии наблюдения glColor3ub(255, 0, 0); glutSolidSphere(10.0f, 15, 15); // Задаем желтый цвет для всех электронов glColor3ub(255,255,0); // ПЕРВЫЙ ЭЛЕКТРОН radius = 90.0f; // Сохраняем исходное преобразование наблюдения в стеке матриц glPushMatrix(); ShowOrbit(radius); // Рисуем орбиту // Формируем точку центра первого электрона // поворотом на угол относительно оси 0y glRotatef(fElect, 0.0f, 1.0f, 0.0f); // Сдвинули точку по оси 0x на radius единиц glTranslatef(radius, 0.0f, 0.0f); // Рисуем электрон glutSolidSphere(6.0f, 15, 15); // Восстанавливаем исходную матрицу преобразования наблюдения glPopMatrix(); // ВТОРОЙ ЭЛЕКТРОН radius = 70.0f; glPushMatrix(); glRotatef(120.0f, 0.0f, 0.0f, 1.0f); ShowOrbit(radius); // Рисуем орбиту glRotatef(fElect + 90.0f, 0.0f, 1.0f, 0.0f); glTranslatef(-radius, 0.0f, 0.0f); glutSolidSphere(6.0f, 15, 15); glPopMatrix(); // ТРЕТИЙ ЭЛЕКТРОН radius = 60.0f; glPushMatrix(); glRotatef(-120.0f,0.0f, 0.0f, 1.0f); ShowOrbit(radius); // Рисуем орбиту glRotatef(fElect - 90.0f, 0.0f, 1.0f, 0.0f); glTranslatef(0.0f, 0.0f, radius); glutSolidSphere(6.0f, 15, 15); glPopMatrix(); // Увеличиваем угол поворота fElect += 10.0f; fElect = fElect > 360.0f ? 0.0f : fElect; // Переключаем буферы рисования glutSwapBuffers(); } //********************************************************** #define GL_PI 3.1415f #include <math.h> // Для тригонометрических функций void ShowOrbitPerspect(GLfloat radius) { // Переменные орбиты GLfloat x, y = 0.0f, z, angle; glBegin(GL_LINE_LOOP); for(angle = 0.0f; angle < 2.0f * GL_PI; angle += 0.1f) { x = radius * sin(angle); z = radius * cos(angle); glVertex3f(x, y, z); } glEnd(); } //********************************************************** // Функция обратного вызова для рисования сцены void RenderSceneAtomPerspect(void) { // Сбрасываем буфер цвета и буфер глубины glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Рисуем сцену AtomPerspect(); // Прокачка сообщений glFlush(); } //********************************************************** // Вызывается библиотекой GLUT при изменении размеров окна void ChangeSizeAtomPerspect(int width, int height) { // Предотвращаем деление на нуль if(height == 0) height = 1; // Устанавливаем поле просмотра с размерами окна glViewport(0, 0, width, height); // Устанавливает матрицу преобразования в режим проецирования glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Устанавливаем размеры перспективы (отсекающего объема) // (left, right, bottom, top, near, far) GLfloat aspectRatio = (GLfloat)width / (GLfloat)height;// Для коррекции gluPerspective(45.0, aspectRatio, 1.0, 500.0); // Восстановливает матрицу преобразования в исходный режим вида glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }Листинг 21.16. Файл AtomPerspect.h модели атома в перспективной проекции
- Скорректируйте файл ProjectionMatrix.cpp для четвертого упражнения
//********************************************************** // Подключение стандартного файла с библиотекой 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) Брусок в перспективной проекции" #include "AtomPerspect.h" // Упражнение 4: "4) Модель атома в перспективе" //********************************************************** // Функция обратного вызова обработки выбора пользователя 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; case 4: ChangeSizeAtomPerspect(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; case 4: SetupLight(false); RenderSceneAtomPerspect(); 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; case 4: ChangeSizeAtomPerspect(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); glutAddMenuEntry("4) Модель атома в перспективе", 4); glutAttachMenu(GLUT_RIGHT_BUTTON);// Присоединяем // Конец создания меню glutMainLoop(); // Цикл сообщений графического окна }Листинг 21.17. Код файла ProjectionMatrix.cpp после добавления четвертого упражнения
- Разберитесь с кодом, запустите упражнение, поуправляйте изображением с помощью клавиш-стрелок.
На динамической модели атома в перспективной проекции мгновенные снимки экрана могут быть такими