Сделай Сам Свою Работу на 5

GLUT_BITMAP_9_BY_15, GLUT_BITMAP_8_BY_13, GLUT_BITMAP_TIMES_ROMAN_10, GLUT_BITMAP_TIMES_ROMAN_24, GLUT_BITMAP_HELVETICA_10, GLUT_BITMAP_HELVETICA_12, GLUT_BITMAP_HELVETICA_18





Кафедра математики

 

Компьютерная Графика

Отчёт по лабораторной работе №3

Основы создания графических приложений в системе Windows

OpenGL 2Dс использованиемGLUT

 

Выполнил: студент 2 курса группы ПМИ-34,

Ибрагимов Ринат Радикович

Проверил: старший преподаватель кафедры ВВТиС,

Мухтаров Айрат Радикович

 

 

г. Уфа, УГАТУ, Апрель 25, 2012


Задание

Создать приложение, в окне которого средствами OpenGl, с помощью графических примитивов, рисуется график функции
y = sin(3x)+cos(2x + π/12).

Приложение должно корректно работать при различных размерах окна и поддерживать масштабирование. К штрихам на осях координат должны быть подписи.

 

Теоретическая часть

OpenGL (Open Graphics Library — открытая графическая библиотека, графическое API) — спецификация, определяющая независимый от языка программирования платформонезависимый программный интерфейс для написания приложений, использующих двумерную и трёхмерную компьютерную графику.

Включает более 250 функций для рисования сложных трёхмерных сцен из простых примитивов. Используется при создании компьютерных игр, САПР, виртуальной реальности, визуализации в научных исследованиях. На платформе Windows конкурирует с Direct3D.



На базовом уровне, OpenGL — это просто спецификация, то есть документ, описывающий набор функций и их точное поведение. Производители оборудования на основе этой спецификации создают реализации — библиотеки функций, соответствующих набору функций спецификации. Реализация использует возможности оборудования там, где это возможно. Если аппаратура не позволяет реализовать какую-либо возможность, она должна быть эмулирована программно. Производители должны пройти специфические тесты (conformance tests — тесты на соответствие) прежде чем реализация будет классифицирована как OpenGL реализация. Таким образом, разработчикам программного обеспечения достаточно научиться использовать функции, описанные в спецификации, оставив эффективную реализацию последних разработчикам аппаратного обеспечения.

Эффективные реализации OpenGL существуют для Windows, Unix-платформ, PlayStation 3 и Mac OS. Эти реализации обычно предоставляются изготовителями видеоадаптеров и активно используют возможности последних. Существуют также чисто программные реализации спецификации OpenGL, одной из которых является библиотека Mesa. Из лицензионных соображений Mesa является «неофициальной» реализацией OpenGL, хотя полностью с ней совместима на уровне кода.



Спецификация OpenGL пересматривается Консорциумом ARB (Architecture Review Board), который был сформирован в 1992 году. Консорциум состоит из компаний, заинтересованных в создании широко распространённого и доступного API. Согласно официальному сайту OpenGL, членами ARB с решающим голосом на ноябрь 2004 года являются производители профессиональных графических аппаратных средств SGI, 3Dlabs, Matrox и Evans & Sutherland (военные приложения), производители потребительских графических аппаратных средств ATI и NVIDIA, производитель процессоров Intel, и изготовители компьютеров и компьютерного оборудования IBM, Apple, Dell, Hewlett-Packard и Sun Microsystems, а также один из лидеров компьютерной игровой индустрии id Software. Microsoft, один из основоположников Консорциума, покинула его в марте 2003 года. Помимо постоянных членов, каждый год приглашается большое количество других компаний, становящихся частью OpenGL ARB в течение одного года. Такое большое число компаний, вовлеченных в разнообразный круг интересов, позволило OpenGL стать прикладным интерфейсом широкого назначения с большим количеством возможностей.

OpenGL ориентируется на следующие две задачи:

1. Скрыть сложности адаптации различных 3D-ускорителей, предоставляя разработчику единый API.

2. Скрыть различия в возможностях аппаратных платформ, требуя реализации недостающей функциональности с помощью программной эмуляции.



Основным принципом работы OpenGL является получение наборов векторных графических примитивов в виде точек, линий и многоугольников с последующей математической обработкой полученных данных и построением растровой картинки на экране и/или в памяти. Векторные трансформации и растеризация выполняются графическим конвейером (graphics pipeline), который по сути представляет собой дискретный автомат. Абсолютное большинство команд OpenGL попадают в одну из двух групп: либо они добавляют графические примитивы на вход в конвейер, либо конфигурируют конвейер на различное исполнение трансформаций.

OpenGL является низкоуровневым процедурным API, что вынуждает программиста диктовать точную последовательность шагов, чтобы построить результирующую растровую графику (императивный подход). Это является основным отличием от дескрипторных подходов, когда вся сцена передается в виде структуры данных (чаще всего дерева), которое обрабатывается и строится на экране.

Существует ряд библиотек, созданных поверх или в дополнение к OpenGL. Например, библиотека GLU, являющаяся практически стандартным дополнением OpenGL и всегда её сопровождающая, построена поверх последней, то есть использует её функции для реализации своих возможностей. Другие библиотеки, как, например, GLUT и SDL, созданы для реализации возможностей, недоступных в OpenGL. К таким возможностям относятся создание интерфейса пользователя (окна, кнопки, меню и др.), настройка контекста рисования (область рисования, использующаяся OpenGL), обработка сообщений от устройств ввода/вывода (клавиатура, мышь и др.), а также работа с файлами. Обычно, каждый оконный менеджер имеет собственную библиотеку-расширение для реализации вышеописанных возможностей, например, WGL в Windows или GLX в X Window System, однако библиотеки GLUT и SDL являются кросс-платформенными, что облегчает перенос написанных приложений на другие платформы.

GLUT

OpenGL Utility Toolkit (GLUT) — библиотека утилит для приложений под OpenGL, которая в основном отвечает за системный уровень операций ввода-вывода при работе с операционной системой. Из функций можно привести следующие: создание окна, управление окном, мониторинг за вводом с клавиатуры и событий мыши. Она также включает функции для рисования ряда геометрических примитивов: куб, сфера, чайник. GLUT даже включает возможность создания несложных всплывающих меню.

GLUT был создан Марком Килгардом (Mark Kilgard), во время его работы в Silicon Graphics Inc.

Использование библиотеки GLUT преследует две цели. Во-первых, это создание кроссплатформенного кода. Во-вторых, GLUT позволяет облегчить изучение OpenGL. Чтобы начать программировать под OpenGL, используя GLUT, требуется всего страница кода. Написание аналогичных вещей на API требует несколько страниц, написанных со знанием API управления окнами операционной системы.

Все функции GLUT начинаются с префикса glut (например, glutPostRedisplay() отмечает текущее окно, как требующее перерисовки).

Выполнение работы

Исходный код полученного приложения, компилируемый в системе Windows с помощью средств Microsoft Visual Studio, Dev-Cpp, системе Linux при помощи GCC G++ или Mac OS при помощи GCC G++ или xCode прилагается к отчёту (3.cpp).

Для корректной работы программы требуется наличие установленной в систему библиотеки GLUT.

 

Здесь же приведу инструкцию по установке и настройке библиотеки GLUT для Windows и среды Microsoft Visual Studio 2010 и разбор исходного кода.

Для установки библиотеки GLUT в систему Windows достаточно просто положить её файлы в директории, в которыx Windows хранит библиотеки и использует для их подключения при компиляции или запуске программ. От себя рекомендую среду разработки перед этим закрыть.

Так, файл glut.h должен попасть в эту директорию C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\GL
glut32.lib -> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib
glut32.dll
-> C:\Windows\System32

После этих действий заново откройте среду разработки и пересоберите ваши проекты с использованием glut, если они были. Всё. Установка и настройка glut в систему завершена.

 

Первое что мы должны сделать – это кроссплатформенно подключить glut (По правилам хорошего тона, если можем, то пишем кроссплатформенное приложение).

Большую часть других библиотек при этом лучше подключить ДО glut.

#include <stdio.h>

#include <stdlib.h>

#define _USE_MATH_DEFINES

#include <math.h>

#if defined(linux) || defined(_WIN32)

#include <GL/glut.h> /*Для Linux и Windows*/

#if defined(_WIN32)

#include <windows.h>

#endif

#else

#include <GLUT/GLUT.h> /*Для Mac OS*/

#endif

 

Определим константу для нажатия кнопки Esc. При её нажатии будем завершать приложение.

И ещё несколько переменных.

 

#define KEY_ESCAPE 27

 

bool fullscreen = true;

int Width, Height, Top = 50, Left = 162,

oWidth = 700, oHeight = 500,

zoom = 30, left = 0, direct = 1,old = 0;

char buf[19];

 

Эти константы отвечают за размеры и положение окна в неполноэкранном режиме, так же за уровень масштабирования графика, и некоторые настройки направления перемотки.

Строка buf нам потребуется для конвертирования чисел в строки.

 

Следующая функция отвечает за вывод текста на экран. К сожалению, она поддерживает всего 7 встроенных шрифтов, но для нашего дела хватит.

 

void glutPrint(float x, float y, LPVOID font, char* text){

if(!text || !strlen(text)) return;

bool blending = false;

if(glIsEnabled(GL_BLEND)) blending = true;

glEnable(GL_BLEND);

glRasterPos2f(x,y);

while(*text){

glutBitmapCharacter(font, *text);

text++;

}

if(!blending) glDisable(GL_BLEND);

}

 

А вот список этих шрифтов, на всякий случай:

GLUT_BITMAP_9_BY_15, GLUT_BITMAP_8_BY_13, GLUT_BITMAP_TIMES_ROMAN_10, GLUT_BITMAP_TIMES_ROMAN_24, GLUT_BITMAP_HELVETICA_10, GLUT_BITMAP_HELVETICA_12, GLUT_BITMAP_HELVETICA_18

 

Эта функция работает при выходе из полноэкранного режима.

 

void window(){

glutReshapeWindow(oWidth, oHeight);

glutPositionWindow(Left,Top);

}

 

Теперь надо написать функцию-обработчик изменений размеров окна.
Зададим область вывода изображения размером со все окно при помощи команды glViewport(х, у, ширина, высота). Затем загрузим матрицу проекции glMatrixMode(GL_PROJECTION), заменим ее единичной glLoadIdentity() и установим ортогональную проекцию. И наконец, загрузим модельно-видовую матрицу glMatrixMode(GL_MODELVIEW) и заменим ее единичной.

 

void reshape(int w, int h){

Width = w; Height = h;

glViewport(0, 0, w, h);

 

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0, w, 0, h);

 

glMatrixMode(GL_MODELVIEW);

}

 

Функция, срабатывающая, когда необходимо обновить содержимое окна. По сути – онПеинт.

 

void display(){

int i;

glClear(GL_COLOR_BUFFER_BIT);

 

Начали с очистки экрана. В библиотеке доступны следующие флаги очистки буферов.

GL_COLOR_BUFFER_BIT — для очистки буфера цвета

GL_DEPTH_BUFFER_BIT — для очистки буфера глубины

GL_ACCUM_BUFFER_BIT — для очистки буфера накопления

GL_STENCIL_BUFFER_BIT — для очистки трафаретного буфера

Для установки нескольких этих флагов следует воспользоваться операцией логического побитового сложения.

 

 

Теперь нарисуем оси координат.

 

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

glBegin(GL_LINES);

glVertex2i(0,Height/2);

glVertex2i(Width,Height/2);

glVertex2i(Width/2+left,0);

glVertex2i(Width/2+left,Height);

 

glVertex2i(Width-5,Height/2-5);

glVertex2i(Width,Height/2);

glVertex2i(Width-5,Height/2+5);

glVertex2i(Width,Height/2);

 

glVertex2i(Width/2+left-5,Height-5);

glVertex2i(Width/2+left,Height);

glVertex2i(Width/2+left+5,Height-5);

glVertex2i(Width/2+left,Height);

 

glEnd();

 

Сменим цвет и нарисуем штрихи на осях

 

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

glBegin(GL_LINES); //штрихи на осях

int k = zoom/50, j;

for(i = Width/2+left; i <= Width; i += zoom){

glVertex2i(i, Height/2-3);

glVertex2i(i, Height/2+3);

for(j=1;j<=k;++j){

glVertex2i(i-zoom*j/(k+1), Height/2-1);

glVertex2i(i-zoom*j/(k+1), Height/2+1);

}

}

for(i = Width/2+left; i >= 0; i -= zoom){

glVertex2i(i, Height/2-3);

glVertex2i(i, Height/2+3);

for(j=1;j<=k;++j){

glVertex2i(i+zoom*j/(k+1), Height/2-1);

glVertex2i(i+zoom*j/(k+1), Height/2+1);

}

}

for(i = 0;i<Height/2;i+=zoom){

glVertex2i(Width/2+left-2,Height/2+i);

glVertex2i(Width/2+left+2,Height/2+i);

 

glVertex2i(Width/2+left-2,Height/2-i);

glVertex2i(Width/2+left+2,Height/2-i);

}

glEnd();

 

Вся соль в том, что при большом масштабе между текущими штрихами на оси ординат будут добавляться ещё.

 

Теперь напишем текст (Подписи к штрихам)

 

int label = 0;

for(i = Width/2+left; i <= Width; i += zoom){

itoa(label,buf,10);

glutPrint(i-5,Height/2-15, GLUT_BITMAP_HELVETICA_12, buf);

++label;

}

label = 0;

for(i = Width/2+left; i >= 0; i -= zoom){

itoa(label,buf,10);

glutPrint(i-5,Height/2-15, GLUT_BITMAP_HELVETICA_12, buf);

--label;

}

for(label = 1;label < Height/2; ++label){

itoa(label,buf,10);

glutPrint(Width/2+left+5,Height/2+label*zoom-5, GLUT_BITMAP_HELVETICA_12, buf);

itoa(-label,buf,10);

glutPrint(Width/2+left+5,Height/2-label*zoom-5, GLUT_BITMAP_HELVETICA_12, buf);

}

 

И, наконец, перейдём к рисованию графика функции

 

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

glBegin(GL_LINE_STRIP);

for(i=-Width/2-left;i<=Width/2-left;++i){

glVertex2i(i+left+Width/2, zoom*(sin(3*((double)i/zoom)) + cos(2*((double)i/zoom) + M_PI/12)) + Height/2);

}

glEnd();

 

glutSwapBuffers();

}

 

Последней строкой функция обменивает содержимое экрана с содержимым буфера, в котором мы и рисовали.

 

 

Функция, отслеживающая нажатия клавиш, не возвращающих последовательность символов.

 

void bind(int key, int x, int y){

if(key == GLUT_KEY_LEFT){

left += 15*(old == 1 ? direct+2 : old == 0 ? direct = 2 : direct = 1);

old = 1;

}

if(key == GLUT_KEY_RIGHT){

left -= 15*(old == -1 ? direct+2 : old == 0 ? direct = 2 : direct = 1);

old = -1;

}

if(key == GLUT_KEY_UP){

zoom += 2;

old = 0;

}

if(key == GLUT_KEY_DOWN && zoom > 4){

zoom -= 2;

old = 0;

}

if(key == GLUT_KEY_F11){ (fullscreen = !fullscreen) ? glutFullScreen() : window(); return; }

display();

}

 

По нажатию клавиш со стрелками вправо или влево мы двигаем график в соответствующую сторону, а стрелками вверх и вниз управляем масштабом изображения.

 

 

Функция, отслеживающая нажатия остальных клавиш

 

void keys(unsigned char key, int x, int y){

if(key == KEY_ESCAPE) exit(0);

}

 

Тело приложения. Первое, что мы сделаем, это спрячем консоль в операционной системе Windows.

 

int main (int argc, char * argv[]){

#if defined(_WIN32)

FreeConsole();

#endif

 

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);

glutCreateWindow("Простейшая анимация 3");

 

glutReshapeFunc(reshape);

glutKeyboardFunc(keys);

glutSpecialFunc(bind);

glutDisplayFunc(display);

 

glutFullScreen();

glutMainLoop();

return 0;

}

 

Затем инициализируем GLUT с параметрами нашего приложения, создаём окно и включаем обработку наших функций.

 

Флаги параметров приложения могут быть комбинацией этих констант с помощью побитового ИЛИ:

Константа Значение
GLUT_RGB Для отображения графической информации используются 3 компоненты цвета RGB.
GLUT_RGBA То же что и RGB, но используется также 4 компонента ALPHA (прозрачность).
GLUT_INDEX Цвет задается не с помощью RGB компонентов, а с помощью палитры. Используется для старых дисплеев, где количество цветов например 256.
GLUT_SINGLE Вывод в окно осуществляется с использованием 1 буфера. Обычно используется для статического вывода информации.
GLUT_DOUBLE Вывод в окно осуществляется с использованием 2 буферов. Применяется для анимации, чтобы исключить эффект мерцания.
GLUT_ACCUM Использовать также буфер накопления (Accumulation Buffer). Этот буфер применяется для создания специальных эффектов, например отражения и тени.
GLUT_ALPHA Использовать буфер ALPHA. Этот буфер, как уже говорилось используется для задания 4-го компонента цвета - ALPHA. Обычно применяется для таких эффектов как прозрачность объектов и антиалиасинг.
GLUT_DEPTH Создать буфер глубины. Этот буфер используется для отсечения невидимых линий в 3D пространстве при выводе на плоский экран монитора.
GLUT_STENCIL Буфер трафарета используется для таких эффектов как вырезание части фигуры, делая этот кусок прозрачным. Например, наложив прямоугольный трафарет на стену дома, вы получите окно, через которое можно увидеть что находится внутри дома.
GLUT_STEREO Этот флаг используется для создания стереоизображений. Используется редко, так как для просмотра такого изображения нужна специальная аппаратура.

 

 

Далее, необходимо установить обработку различных действий нашими функциями. GLUT реализует событийно-управляемый механизм. Т.е. есть главный цикл, который запускается после инициализации, и в нем уже обрабатываются все объявленные события. Например нажатие клавиши на клавиатуре или движение курсора мыши и т.д. Зарегистрировать функции-обработчики событий можно при помощи следующих команд:

 

void glutDisplayFunc (void(*func) (void)) — задает функцию рисования изображения

void glutReshapeFunc (void(*func) (intwidth,intheight)) — задает функцию обработки изменения размеров окна

void glutVisibilityFunc (void(*func)(intstate)) — задает функцию обработки изменения состояния видимости окна

void glutKeyboardFunc (void(*func)(unsigned charkey,intx,inty)) — задает функцию обработки нажатия клавиш клавиатуры (только тех, что генерируют ascii-символы)

void glutSpecialFunc (void(*func)(intkey,intx,inty)) — задает функцию обработки нажатия клавиш клавиатуры (тех, что не генерируют ascii-символы)

void glutIdleFunc (void(*func) (void)) — задает функцию, вызываемую при отсутствии других событий

void glutMouseFunc (void(*func) (intbutton,intstate,intx,inty)) — задает функцию, обрабатывающую команды мыши

void glutMotionFunc (void(*func)(intx,inty)) — задает функцию, обрабатывающую движение курсора мыши, когда зажата какая-либо кнопка мыши

void glutPassiveMotionFunc (void(*func)(intx,inty)) — задает функцию, обрабатывающую движение курсора мыши, когда не зажато ни одной кнопки мыши

void glutEntryFunc (void(*func)(intstate)) — задает функцию, обрабатывающую движение курсора за пределы окна и его возвращение

void glutTimerFunc (unsigned intmsecs,void(*func)(intvalue),value) — задает функцию, вызываемую по таймеру

 

После этих действий разворачиваем окно на весь экран и запускаем главный цикл приложения.


Скриншот

 








Не нашли, что искали? Воспользуйтесь поиском по сайту:



©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.