Украина, Киев |
Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 21:
Непрограммируемый конвейер в OpenGL
Упражнение 1. Построение модели атома в ортогональной проекции (Atom)
Используем рассмотренные преобразования для решения простейшей задачи - формирования модели атома. Разместим в файле ProjectionMatrix.cpp общую часть программы, а код каждого упражнения будем размещать в отдельном файле.
-
Заполните файл 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) Простая модель атома" //********************************************************** // Функция обратного вызова обработки выбора пользователя void ExecuteMenu(int choice) { // Сбрасываем углы вращения прежнего варианта xRot = yRot = 0; // Запоминаем выбор в глобальную переменную ::choice = choice; switch(::choice) { case 1: ChangeSizeAtom(w, h); break; } // Вызвать принудительно визуализацию glutPostRedisplay(); } //********************************************************** // Функция обратного вызова для рисования сцены // для первого упражнения Atom void RenderScene(void) { switch(::choice) { case 1: RenderSceneAtom(); break; } } //********************************************************** // Вызывается библиотекой GLUT при изменении размеров окна // для первого упражнения Atom void ChangeSize(int width, int height) { w = width; h = height; switch(::choice) { case 1: ChangeSizeAtom(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); glutAttachMenu(GLUT_RIGHT_BUTTON);// Присоединяем // Конец создания меню glutMainLoop(); // Цикл сообщений графического окна }Листинг 21.10. Код файла ProjectionMatrix.cpp для первого упражнения
-
Добавьте к проекту новый заголовочный файл (Header File) с именем Atom.h и заполните его следующим кодом
//********************************************************** // Прототипы void Atom(); void RenderSceneAtom(void); void ChangeSizeAtom(int, int); // При изменении размеров окна void ShowOrbit(GLfloat radius); //********************************************************** // Упражнение 1: "1) Простая модель атома" void Atom() { // Угол поворота вокруг ядра 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, -100.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 ShowOrbit(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(); } //********************************************************** // Функция обратного вызова для рисования сцены // для первого упражнения Atom void RenderSceneAtom(void) { // Сбрасываем буфер цвета и буфер глубины glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Рисуем сцену Atom(); // Прокачка сообщений glFlush(); } //********************************************************** // Вызывается библиотекой GLUT при изменении размеров окна // для первого упражнения Atom void ChangeSizeAtom(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;// Для коррекции const GLfloat nRange = 100; // Размеры отсекающих плоскостей // Первоначально задали куб, теперь его корректируем // в зависимости от искажения графического окна if (width <= height) glOrtho (-nRange, nRange, nRange / aspectRatio, -nRange / aspectRatio, -nRange * 2.0f, nRange * 2.0f); else glOrtho (-nRange * aspectRatio, nRange * aspectRatio, nRange, -nRange, -nRange * 2.0f, nRange * 2.0f); // Восстановливает матрицу преобразования в исходный режим вида glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }Листинг 21.11. Код файла Atom.h реализации модели атома
-
Разберитесь с кодом, запустите упражнение, поуправляйте изображением с помощью клавиш-стрелок
На динамической модели атома снимки экрана могут быть такими