Знакомимся с OpenGL. Значения параметров функции glPolygonMode

ВВЕДЕНИЕ

OpenGL является одним из самых популярных прикладных программных интерфейсов (API - Application Programming Interface) для разработки приложений в области двумерной и трехмерной графики.

Стандарт OpenGL (Open Graphics Library - открытая графическая библиотека) был разработан и утвержден в 1992 году ведущими фирмами в области разработки программного обеспечения как эффективный аппаратно-независимый интерфейс, пригодный для реализации на различных платформах. Основой стандарта стала библиотека IRIS GL, разработанная фирмой Silicon Graphics Inc.

Библиотека насчитывает около 120 различных команд, которые программист использует для задания объектов и операций, необходимых для написания интерактивных графических приложений.

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

Характерными особенностями OpenGL, которые обеспечили распространение и развитие этого графического стандарта, являются:

Стабильность. Дополнения и изменения в стандарте реализуются таким образом, чтобы сохранить совместимость с разработанным ранее программным обеспечением.

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

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

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

ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ БИБЛИОТЕКИ OPENGL

Назначение и возможности библиотеки OpenGL

Для упрощения разработки программ на языке Си++ существует большое количество готовых библиотек с реализацией алгоритмов для конкретных предметных областей, от численных расчетов до распознавания речи. Библиотека OpenGL является одним из самых популярных программных интерфейсов (API) для работы с трехмерной графикой. Стандарт OpenGL был утвержден в 1992 г. ведущими фирмами в области разработки программного обеспечения. Его основой стала библиотека IRIS GL, разработанная фирмой Silicon Graphics на базе концепции графической машины Стэнфордского университета (1982 г.).

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

С точки зрения программиста, OpenGL - это программный интерфейс для графических устройств (например, графических ускорителей). Он включает в себя около 150 различных функций, с помощью которых программист может задавать свойства различных трехмерных и двумерных объектов и выполнять их визуализацию (рендеринг). Т.е. в программе надо задать местоположение объектов в трехмерном пространстве, определить другие параметры (поворот, растяжение), задать свойства объектов (цвет, текстура, материал и т.д.), положение наблюдателя, а затем библиотека OpenGL выполнит генерацию двумерной проекции этой трехмерной сцены.

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

Основные возможности OpenGL, предоставляемые программисту, можно разделить на несколько групп:

1. Геометрические и растровые примитивы. На основе этих примитивов строятся все остальные объекты. Геометрические примитивы - это точки, отрезки и многоугольники. Растровыми примитивами являются битовые массивы и изображения.

2. Сплайны. Сплайны применяются для построения гладких кривых по опорным точкам.

3. Видовые и модельные преобразования. Эти преобразования позволяют задавать пространственное расположение объектов, изменять форму объектов и задавать положение камеры, для которой OpenGL строит результирующее проекционное изображение.

4. Работа с цветом. Для операций с цветом в OpenGL есть режим RGBA (красный - зелёный - синий - прозрачность) и индексный режим (цвет задается порядковым номером в палитре).

5. Удаление невидимых линий и поверхностей.

6. Двойная буферизация. В OpenGL доступна и одинарная, и двойная буферизация. Двойная буферизация применяется для устранения мерцания при мультипликации. При этом изображение каждого кадра сначала рисуется в невидимом буфере, а на экран кадр копируется только после того, как полностью нарисован.

7. Наложение текстуры. Текстуры упрощают создание реалистичных сцен. Если на объект, например, сферу, наложить текстуру (некоторое изображение), то объект будет выглядеть иначе (например, сфера будет выглядеть как разноцветный мячик).

8. Сглаживание. Автоматическое сглаживание компенсирует ступенчатость, свойственную растровым дисплеям. При сглаживании отрезков OpenGL изменяет интенсивность и цвет пикселей так, что эти отрезки отображаются на экране без зигзагов".

9. Освещение. Указание расположения, интенсивности и цвета источников света.

10. Специальные эффекты. Например, туман, дым, прозрачность объектов. Эти средства позволяют сделать сцены более реалистичными.

Хотя библиотека OpenGL предоставляет практически все возможности для моделирования и воспроизведения трёхмерных сцен, некоторые графические функции непосредственно в OpenGL недоступны. Например, чтобы задать положение и направление камеры для наблюдения сцены придется рассчитывать проекционную матрицу, что сопряжено с достаточно громоздкими вычислениями. Поэтому для OpenGL существуют так называемые вспомогательные библиотеки.

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

Еще две известные библиотеки - GLUT (для Unix) и GLAUX (для MS Windows). В них реализованы не только дополнительные функции OpenGL (для построения некоторых сложных фигур вроде конуса и тетраэдра), но также есть функции для работы с окнами, клавиатурой и мышью в консольных приложениях. Чтобы работать с OpenGL в конкретной операционной системе (например, Windows или Unix), надо провести некоторую предварительную настройку, которая зависит от операционной системы. GLUT и GLAUX позволяют буквально несколькими командами определить окно, в котором будет работать OpenGL, задать функции для обработки команд от клавиатуры или мыши.

Возможности OpenGL описаны через функции его библиотеки. Все функции можно разделить на пять категорий.

Функции описания примитивов определяют объекты нижнего уровня иерархии (примитивы), которые способна отображать графическая подсистема. В OpenGL в качестве примитивов выступают точки, линии, многоугольники и т.д.

Функции описания источников света служат для описания положения и параметров источников света, расположенных в трехмерной сцене.

Функции задания атрибутов. С помощью задания атрибутов программист определяет, как будут выглядеть на экране отображаемые объекты. Другими словами, если с помощью примитивов определяется, что появится на экране, то атрибуты определяют способ вывода на экран. В качестве атрибутов OpenGL позволяет задавать цвет, характеристики материала, текстуры, параметры освещения.

Функции визуализации позволяет задать положение наблюдателя в виртуальном пространстве, параметры объектива камеры. Зная эти параметры, система сможет не только правильно построить изображение, но и отсечь объекты, оказавшиеся вне поля зрения.

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

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

OpenGL является на данный момент одним из самых популярных программных интерфейсов (API) для разработки приложений в области двумерной и трехмерной графики. Стандарт OpenGL был разработан и утвержден в 1992 году ведущими фирмами в области разработки программного обеспечения, а его основой стала библиотека IRIS GL, разработанная Silicon Graphics.

На данный момент реализация OpenGL включает в себя несколько библиотек (описание базовых функций OpenGL, GLU,GLUT,GLAUX и другие), назначение которых будет описано ниже.

Характерными особенностями OpenGL, которые обеспечили распространение и развитие этого графического стандарта, являются:

Стабильность - дополнения и изменения в стандарте реализуются таким образом, чтобы сохранить совместимость с разработанным ранее программным обеспечением.

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

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

Основные возможности OpenGL

    Набор базовых примитивов: точки, линии, многоугольники и т.п.

    Видовые и координатные преобразования

    Удаление невидимых линий и поверхностей (z-буфер)

    Использование сплайнов для построения линий и поверхностей

    Наложение текстуры и применение освещения

    Добавление специальных эффектов: тумана, изменение прозрачности,сопряжение цветов (blending), устранение ступенчатости (anti-aliasing).

Как уже было сказано, существует реализация OpenGL для разных платформ, для чего было удобно разделить базовые функции графической системы и функции для отображения графической информации и взаимодействия с пользователем. Были созданы библиотеки для отображения информации с помощью оконной подсистемы для операционных систем Windows и Unix (WGL и GLX соответственно), а также библиотеки GLAUX и GLUT, которые используются для создания так называемых консольных приложений.

Библиотека GLAUX уступает по популярности написанной несколько позже библиотеке GLUT, хотя они предоставляют примерно одинаковые возможности. В состав библиотеки GLU вошла реализация более сложных функций, таких как набор популярных геометрических примитивов (куб, шар, цилиндр, диск), функции построения сплайнов, реализация дополнительных операций над матрицами и т.п. Все они реализованы через базовые функции OpenGL.

Архитектура и особенности синтаксиса

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

    Аппроксимация кривых и поверхностей

    Обработка вершин и сборка примитивов

    Растеризация и обработка фрагментов

    Операции над пикселями

    Подготовка текстуры

    Передача данных в буфер кадра

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

ИНИЦИАЛИЗАЦИЯ БИБЛИОТЕКИ OpenGL В C++

Первым делом нужно подключить заголовочные файлы:

#include

#include

#include

· gl.h и glu.h содержат прототипы основных функций OpenGL определённых в opengl32.dll и glu32.dll.

· glaux.h содержит вспомогательные (auxiliary) функции (glaux.dll).

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

BOOL bSetupPixelFormat(HDC hdc)

PIXELFORMATDESCRIPTOR pfd, *ppfd;

int pixelformat;

ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);

ppfd->nVersion = 1;

ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;

ppfd->dwLayerMask = PFD_MAIN_PLANE;

ppfd->iPixelType = PFD_TYPE_RGBA;

ppfd->cColorBits = 16;

ppfd->cDepthBits = 16;

ppfd->cAccumBits = 0;

ppfd->cStencilBits = 0;

if ((pixelformat = ChoosePixelFormat(hdc, ppfd)) == 0)

MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);

if (SetPixelFormat(hdc, pixelformat, ppfd) == FALSE)

MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);

Структура PIXELFORMATDESCRIPTOR сказать надо.

cColorBits - глубина цвета

cDepthBits - размер буфера глубины (Z-Buffer)

cStencilBits - размер буфера трафарета (мы его пока не используем)

iPixelType - формат указания цвета. Может принимать значения PFD_TYPE_RGBA (цвет указывается четырьмя параметрами RGBA - красный, зленный, синий и альфа) и PFD_TYPE_COLORINDEX (цвет указывается индексом в палитре).

Функция ChoosePixelFormat() подбирает формат пикселей и возвращает его дескриптор, а SetPixelFormat() устанавливает его в контексте устройства (dc).

После того как в контексте устройства установлен формат пикселей, нужно создать контекст воспроизведения (Rendering Context) для этого в OpenGL определены следующие функции:

HGLRC wglCreateContext(HDC hdc);

BOOL wglMakeCurrent(HDC hdc, HGLRC hglrc);

В объявлении класса формы в области private необходимо добавить следующее:

ghRC - указатель на контекст воспроизведения (Rendering Context)

ghDC - дескриптор устройства (для нас - просто указатель на окно)

Процедура Draw будет отвечать за рисование.

void __fastcall TForm1::FormCreate(TObject *Sender)

ghDC = GetDC(Handle);

if (!bSetupPixelFormat(ghDC))

ghRC = wglCreateContext(ghDC);

wglMakeCurrent(ghDC, ghRC);

glClearColor(0.0, 0.0, 0.0, 0.0);

FormResize(Sender);

glEnable(GL_COLOR_MATERIAL);

glEnable(GL_DEPTH_TEST);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

float p={3,3,3,1},

glLightfv(GL_LIGHT0,GL_POSITION,p);

glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,d);

glViewport(0, 0, Width, Height);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(-5,5, -5,5, 2,12);

gluLookAt(0,0,5, 0,0,0, 0,1,0);

glMatrixMode(GL_MODELVIEW);

glClearColor() устанавливает цвет, которым будет заполняться экран при очищении. У этой процедуры - 4 параметра, что соответствует RGBA. Вместо нее можно написать glClearIndex(0.0) . Эта процедура устанавливает индекс цвета в палитре.

glViewport() устанавливает область вывода - область, в которую OpenGL будет выводить изображение.

glMatrixMode() устанавливает режим матрицы видового преобразования.

glLoadIdentity() заменяет текущую матрицу видового преобразования на единичную.

glOrtho() устанавливает режим ортогонального (прямоугольного) проецирования. Это значит, что изображение будет рисоваться как в изометрии. 6 параметров типа GLdouble (или просто double): left, right, bottom, top, near, far определяют координаты соответственно левой, правой, нижней, верхней, ближней и дальней плоскостей отсечения, т.е. всё, что окажется за этими пределами, рисоваться не будет. На самом деле эта процедура просто устанавливает масштабы координатных осей. Для того чтобы установить перспективное проецирование, используются процедуры glFrustum() и gluPerspective().

gluLookAt() устанавливает параметры камеры: первая тройка - её координаты, вторая - вектор направления, третья - направление оси Y.

В OpenGL всё включается и выключается (разрешается и запрещается) процедурами glEnable() и glDisable().

glLightfv() устанавливает свойства "лампочек": позицию и направление света.

После того, как завершена работа с OpenGL, нужно освободить занятые ресурсы: освободить контекст, вызвав wglMakeCurrent с параметром ноль для идентификатора контекста OpenGL и разрушить этот контекст функцией wglDeleteContext. Кроме того нужно удалить дескриптор ghDC. Так как обычно работу с OpenGL завершается при завершении работы приложения, то соответствующий код нужно поместить в FormClose:

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)

wglMakeCurrent(ghDC,0);

wglDeleteContext(ghRC);

ReleaseDC(Handle, ghDC);

ЗАКЛЮЧЕНИЕ

За время прохождения производственной практики с 5 июля по 31 июля 2011 г. в ЗАО «Транзас», Авиационное направление в отделе программирования, я ознакомился с работой отдела программирования. Ознакомился с устройством и функционированием комплексных авиа тренажеров, разрабатываемых в ЗАО «Транзас». Я узнал о такой системе визуализации ландшафтов и различных объектов, как «Аврора». Я получил первоначальные практические навыки и умения, необходимые для разработки приложений и программного обеспечения с помощью современного высокоуровневого языка программирования и графической библиотеки.

Лабораторная работа № 2.

1. Введение

OpenGL – Open Graphics Library, открытая графическая библиотека. Термин "открытый" – означает независимый от производителей. Имеется спецификация (стандарт) на OpenGL, где все четко задокументировано и описано. Библиотеку OpenGL может производить кто угодно. Главное, чтобы библиотека удовлетворяла спецификации OpenGL и ряду тестов. Как следствие, в библиотеке нет никаких темных мест, секретов, недокументированных возможностей и т. п, те кто программировал под MS Windows или MS DOS понимают о чем я говорю. Библиотеку выпускают такие корпорации, как Microsoft, Silicon Graphics, а также просто группы программистов. Одним из таких примеров служит реализация Mesa. Эту библиотеку написали целый ряд программистов, главным автором является Brian Paul. Библиотека Mesa распространяется в исходных текстах на языке Си и собирается почти для любой операционной системы. Стандарт OpenGL развивается с 1992 года. Он разрабатывается фирмой Silicon Graphics. С тех пор библиотека завоевала огромную популярность и была интегрирована с множеством языков и систем разработки приложений. Вы можете писать программу с использованием OpenGL на Си, С++, Pascal, Java и многих других языках. Основное предназначение OpenGL программирование трехмерной графики.

Библиотека OpenGL представляет собой интерфейс программирования трехмерной графики. Единицей информации является вершина, из них состоят более сложные объекты. Программист создает вершины, указывает, как их соединять (линиями или многоугольниками), устанавливает координаты и параметры камеры и ламп, а библиотека OpenGL берет на себя работу создания изображения на экране. OpenGL идеально подходит для программистов, которым необходимо создать небольшую трехмерную сцену и не задумываться о деталях реализации алгоритмов трехмерной графики. Для профессионалов, занимающихся программированием трехмерной графики, библиотека тоже будет полезной, т. к. она представляет основные механизмы и выполняет определенную автоматизацию. Используя OpenGL можно с легкостью создать трехмерные поверхности, наложить на них текстуры, осветить источниками света, сделать эффект тумана, прозрачности, смешивания цветов, а также наложить трафарет, передвигать объекты сцены, лампы и камеры по заданным траекториям, сделав тем самым анимацию. OpenGL непосредственно не поддерживает работу с устройствами ввода, такими как мышь или клавиатура, т. к. эта библиотека является платформенно независимой. Но можно задействовать функции конкретной операционной системы, под которую вы пишите свою программу или воспользоваться надстройками над OpenGL, такими как библиотеки GLUT или GLAUX.

2. Первая программа

Самым простым объектом, с помощью которого можно увидеть всю мощь OpenGL, является сфера. Можно попытаться ее изобразить. Для этого надо создать новый проект в VisualC++, выполнив следующие действия:

— запустить Visual C++;

— выполнить команду File | New…;

— в открывшемся диалоговом окне выбрать тип проекта Win32 Application, в поле Project Name указать имя проекта, а в поле Location – папку в которой будет находиться проект;

— нажать кнопку OK. Затем, ничего не изменяя, – кнопку Finish и еще раз OK;

— скопировать в папку проекта два файла Sample. cpp и Sample. h (выдаются преподавателем);

— подключить эти два файла к проекту выполнив команду Project | Add To Project | Files…;

— вставьте в функцию Display следующий код:

GlColor3d(1,0,0);

AuxSolidSphere(1);

— создать exe-модуль (F7).

Поясним назначение вставленных двух функций. Функция glColor3d устанавливает текущий цвет, которым будут рисоваться фигуры. Тут нужно пояснить, как устанавливается цвет и общую философию в названии функций OpenGL. Цвет устанавливается четырьмя параметрами: красный, синий, зеленый и прозрачность. Эти параметры варьируются в диапазоне от нуля до единицы. Четвертый параметр нам пока не нужен, поэтому мы вызвали glColor с тремя параметрами. В этом случае, значение четвертого параметра, прозрачности, по умолчанию считается равным единице, т. е. абсолютно непрозрачным, ноль – будет абсолютно прозрачным. Применяется следующий синтаксис вызова функций – FuncionName[тип параметров].

Доступны следующие типы:

B – GLbyte байт;

S – GLshort короткое целое;

I – GLint целое;

F – GLfloat дробное;

D – GLdouble дробное с двойной точностью;

Ub – GLubyte беззнаковый байт;

Us – GLushort беззнаковое короткое целое;

Ui – GLuint беззнаковое целое;

V – массив из n параметров указанного типа;

В нашем случае – glColor3d – означает, что в функцию передается три параметра типа GLdouble. Также можно было вызвать glColor3i, т. е. три параметра типа GLint. Если тип параметров короткое целое, целое, байт или длинное, то компонента цвета приводится к диапазону . Приведение к этому диапазону осуществляется по следующим правилам. В случае беззнакового типа возможное наибольшее значение приводится к единице, ноль к нулю. В случае знакового максимальное значение приводится к единице или к минус единице, а минус единица будет приведена к единице. На практике обычно пользуются одним из трех случаев, рассмотренных в качестве примера ниже. Например, для беззнакового байта приведение будет осуществлено по следующей формуле: значение_переменной_хранимой_в_байте/255, т. к. 255 максимальное число, хранимое в одном байте. Функция glColor3dv означает, что в качестве параметров передается массив из трех элементов типа GLdouble. Например:

Double array = {0.5, 0.75, 0.3};

GlColor3dv(array);

GlColor3ub(200,100,0); // приводится к

// 200/256, 100/256, 0,256

GlColor3d(0.25,0.25,0); // темно-желтый

GlColot3ub(0,100,0); // темно-зеленый

GlColor3ub(0,0,255); // синий

3. Простые объекты. Общие положения

Точки, линии, треугольники, четырехугольники, многоугольники –простые объекты, из которых состоят любые сложные фигуры. OpenGL непосредственно не поддерживает функций для создания таких сложных объектов как сфера, цилиндр тор и др., т. е. таких функций нет в opengl32.dll. Эти функции есть в библиотеки утилит glu32.dll, и устроены они следующим образом. Для того чтобы нарисовать сферу функция auxSolidSphere использует функции из библиотеки glu32.dll, а те в свою очередь, используют базовую библиотеку opengl32.dll и из линий или многоугольников строят сферу. Примитивы создаются следующим образом:

GlBegin(mode); // указываем, что будем рисовать

glVertex(…); // первая вершина

… // тут остальные вершины

glVertex(…); // последняя

//вершина

GlEnd(); // закончили рисовать примитив

Сначала необходимо указать начало рисования – glBegin с соответствующим параметром.

Возможные значения mode перечислены ниже в таблице. Далее указываются вершины, определяющие объекты указанного типа. Обычно вершину задают одним из четырех способов.

GlVertex2d(x, y); // две переменных типа double

GlVertex3d(x, y,z); // три переменных типа double

GlVertex2dv(array); // массив из двух переменных типа

GlVertex3d(array); // массив из трех переменных типа

Void glEnd(void);

Указывает на конец рисования объектов типа, указанного в glBegin. Далее подробно разберем создание всех примитивов.

Таблица 1.

Возможные значения mode

Значение

Описание

Каждый вызов glVertex задает отдельную точку.

Каждая пара вершин задает отрезок.

Рисуется ломанная.

Рисуется ломанная, причем ее последняя точка соединяется с первой.

Каждые три вызова glVertex задают треугольник.

GL_TRIANGLE_STRIP

Рисуются треугольники с общей стороной.

То же самое, но по другому правилу соединяются вершины.

Каждые четыре вызова glVertex задают четырехугольник.

Четырехугольники с общей стороной.

Многоугольник.

3.1. Точки

Можно нарисовать сколько угодно точек, вызывая glVertex3d, и тем самым, устанавливая новую точку. При создании точек можно изменять следующие параметры. Можно вызывать glColor3d внутри glBegin/glEnd. Размер точки можно устанавливать с помощью функции:

Void glPointSize(GLfloat size);

Режим сглаживания можно устанавливать вызовом функции

GlEnable(GL_POINT_SMOOTH);

Отключается соответственно вызовом glDisable(GL_POINT_SMOOTH). Последние функции – glPointSize и glEnable/glDisable надо вызывать вне glBegin/glEnd, иначе они будут проигнорированы. Функции glEnable/glDisable включают/выключают множество опций, но следует учитывать, что некоторые опции влекут за собой большие вычисления и, следовательно, изрядно затормаживают приложение, поэтому без надобности не стоит их включать.

// рисуем точки

GlBegin(GL_POINTS);

glColor3d(1,0,0);

glVertex3d(-4.5,4,0); // первая точка

glColor3d(0,1,0);

glVertex3d(-4,4,0); // вторая точка

glColor3d(0,0,1);

glVertex3d(-3.5,4,0); // третья

GlBegin(GL_POINTS);

glColor3d(1,0,0);

glVertex3d(-2,4,0); // первая точка

glColor3d(0,1,0);

glVertex3d(-1,4,0); // вторая точка

glColor3d(0,0,1);

glVertex3d(0,4,0); // третья

GlPointSize(10);

GlEnable(GL_POINT_SMOOTH);

GlBegin(GL_POINTS);

glColor3d(1,0,0);

glVertex3d(2,4,0); // первая точка

glColor3d(0,1,0);

glVertex3d(3,4,0); // вторая точка

glColor3d(0,0,1);

glVertex3d(4,4,0); // третья

GlDisable(GL_POINT_SMOOTH);

3.2. Линии

Для линий также можно изменять ширину, цвет, размер сглаживание. Если вы зададите разные цвета для начала и конца линии, то ее цвет будет переливающимся. OpenGL по умолчанию делает интерполяцию. Так же можно рисовать прерывистые линии, делается это путем наложения маски при помощи, следующей функции:

Void glLineStipple(GLint factor, GLushort pattern);

Второй параметр задает саму маску. Например, если его значение равно 255(0x00FF), то чтобы вычислить задаваемую маску воспользуемся калькулятором. В двоичном виде это число выглядит так: 0000000011111111, т. е. всего 16 бит. Старшие восемь установлены в ноль, значит, тут линии не будет. Младшие установлены в единицу, тут будет рисоваться линия. Первый параметр определяет, сколько раз повторяется каждый бит. Скажем, если его установить равным 2, то накладываемая маска будет выглядеть так:

GlLineWidth(1); // ширину линии

// устанавливаем 1

GlBegin(GL_LINES);

glColor3d(1,0,0); // красный цвет

glVertex3d(-4.5,3,0); // первая линия

glVertex3d(-3,3,0);

glColor3d(0,1,0); // зеленый

glVertex3d(-3,3.3,0); // вторая линия

glVertex3d(-4,3.4,0);

GlLineWidth(3); // ширина 3

GlBegin(GL_LINE_STRIP); // см. ниже

glColor3d(1,0,0);

glVertex3d(-2.7,3,0);

glVertex3d(-1,3,0);

glColor3d(0,1,0);

glVertex3d(-1.5,3.3,0);

glColor3d(0,0,1);

glVertex3d(-1,3.5,0);

GlEnable(GL_LINE_SMOOTH);

GlEnable(GL_LINE_STIPPLE); // разрешаем рисовать

// прерывистую линию

GlLineStipple(2,58360); // устанавливаем маску

// пояснения см. ниже

GlBegin(GL_LINE_LOOP);

glColor3d(1,0,0);

glVertex3d(1,3,0);

glVertex3d(4,3,0);

glColor3d(0,1,0);

glVertex3d(3,2.7,0);

glColor3d(0,0,1);

glVertex3d(2.5,3.7,0);

GlDisable(GL_LINE_SMOOTH);

GlDisable(GL_LINE_STIPPLE);

3.3. Треугольники

Для треугольника можно задавать те же параметры, что и для линии плюс есть еще одна функция

Void glPolygonMode(

Она устанавливает опции для прорисовки многоугольника. Возможные значения параметров функции приведены в таблице 2.

Таблица 2.

Значения параметров функции glPolygonMode

Первый параметр указывает, для каких сторон применяется опция, заданная вторым параметром. Треугольники можно рисовать, передав GL_TRIANGLE_STRIP или GL_TRIANGLE_FAN в glBegin. В первом случае первая, вторая и третья вершины задают первый треугольник. Вторая, третья и четвертая вершина — второй треугольник. Третья, четвертая и пятая вершина — третий треугольник и т. д. Вершины n, n+1 и n+2 определят n-ый треугольник. Во втором случае первая, вторая и третья вершина задают первый треугольник. Первая, третья и четвертая вершины задают второй треугольник и т. д. Вершины 1, n+1, n+2 определяют n-ый треугольник. Далее следует пример с комментариями.

GlPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // см. выше

GlBegin(GL_TRIANGLES);

glColor3d(1,0,0); // рисуем треугольник

glVertex3d(-4,2,0);

glVertex3d(-3,2.9,0);

glVertex3d(-2,2,0);

//рисуем проволочные треугольники

GlBegin(GL_TRIANGLE_STRIP); // обратите внимание на

// порядок вершин

glColor3d(0,1,0);

glVertex3d(1,2,0);

glVertex3d(0,2.9,0);

glVertex3d(-1,2,0);

glVertex3d(0,1.1,0);

GlEnable(GL_LINE_STIPPLE);

GlPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

GlBegin(GL_TRIANGLE_FAN);

glColor3d(0,0,1);

glVertex3d(4,2,0);

glVertex3d(2.6,2.8,0);

glVertex3d(2,2,0);

glVertex3d(3,1.1,0);

GlDisable(GL_LINE_STIPPLE);

3.4. Четырехугольники и многоугольники

Четырехугольники рисуются вызовом функции glBegin с параметром GL_QUADS или GL_QUAD_STRIP. Для первого случая каждые четыре вершины определяют свой четырехугольник. Во втором случае рисуются связанные четырехугольники. Первая, вторая, третья и четвертая вершина определяют первый четырехугольник. Третья, четвертая, пятая и шестая вершина — второй четырехугольник и т. д. (2n-1), 2n, (2n+1) и (2n+2) вершины задают n-ый четырехугольник. Многоугольники задаются вызовом glBegin с параметром GL_POLYGON. Все вершины определяют один многоугольник. Для многоугольников можно задавать стили при помощи выше описанной функции glPolygonMode, толщину линии, толщину точек и цвет.

4. Переход к новым координатам

В предыдущем разделе вы научились рисовать примитивные трехмерные объекты. Но проблема в том, что они рисуются только в начале координат, т. е. в точке (0,0,0). Для того чтобы изобразить объект в точке (x0,y0,z0), надо переместить начало координат в эту точку, т. е. надо перейти к новым координатам. Эта процедура довольно распространенная при программировании графики и анимации. Часто, бывает очень удобно, сместить координаты в новую точку и повернуть их на требуемый угол, и ваши расчеты резко упростятся. Для перехода к новым координатам в OpenGL есть две функции:

Void glTranslated(Dx, Dy, Dz);

Void glRotated(j, x0,y0,z0);

Первая функция сдвигает начало системы координат на (Dx, Dy, Dz). Вторая — поворачивает на угол j против часовой стрелки вокруг вектора (x0,y0,z0). Теперь, стоит сказать еще о двух очень важных функциях:

Void glPushMatrix();

Void glPopMatrix();

Они предназначены для сохранения и восстановления текущих координат. Часто бывает неудобно переходить от одной системы координат к другой и помнить все переходы. Гораздо удобнее с помощью glPushMatrix() сохранить текущие координаты, потом сдвигаться, вертеться, как угодно, а после, вызовом glPopMatrix вернуться к старым координатам. Теперь можно поэкспериментировать. Рассмотрим сдвиг координат. Вставьте в функцию display следующий код:

GlTranslated(1.4,0,0);// сдвигаемся по оси Х на 1.4

GlColor3d(0,1,0);

AuxSolidSphere(0.5); // рисуем сферу в (1.4,0,0)

// в абсолютных координатах

GlTranslated(1,0,0); // еще раз сдвигаемся

GlColor3d(0,0,1);

AuxSolidSphere(0.3);

GlPopMatrix(); // возвращаемся к старой системе

// координат

GlColor3d(1,0,0);

AuxSolidSphere(0.75); // рисуем сферу в точке (0,0,0)

// в абсолютных координатах

5. Поворот координат

Теперь рассмотрим вращение координат. В функцию display вставьте следующий код:

GlColor3d(1,0,0);

AuxSolidCone(1, 2); // рисуем конус в центре координат

GlPushMatrix(); // сохраняем текущие координаты

glTranslated(1,0,0); // сдвигаемся в точку (1,0,0)

glRotated(75,1,0,0); // поворачиваем систему

// координат на 75 градусов

glColor3d(0,1,0);

auxSolidCone(1, 2); // рисуем конус

GlPopMatrix(); // возвращаемся к старым координатам

Как видите, конус повернулся в абсолютных координатах. Так что, для того, чтобы нарисовать фигуру не в начале координат, надо:

· сдвинуть(glTranslated), повернуть(glRotated);

· нарисовать то, что хотели;

· вернуться к старым координатам.

Вызовы glPushMatrix/PopMatrix могут быть вложенными, т. е.:

Естественно число вызовов glPopMatrix должно соответствовать числу вызовов glPushMatrix, иначе сцена улетит в неизвестном направление. Максимально допустимая глубина вложенности glPushMatrix/glPopMatrix определяется следующим образом:

GlGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &n);

Printf("n=%d ",n);

Спецификация на OpenGL гарантирует, что глубина стека не может быть меньше 32.

6. Построение поверхностей

Существует набор функций для построения сфер, цилиндров и дисков. Эти функции представляют очень мощный контроль за построением трехмерных объектов. Для рисования поверхностей используются следующие функции:

GLUquadricObj * qobj,

GLdouble radius,

Void gluCylinder(

GLUquadricObj *qobj,

GLdouble baseRadius,

GLdouble topRadius,

GLdouble height,

GLUquadricObj *qobj,

GLdouble innerRadius,

GLdouble outerRadius,

Void gluPartialDisk(

GLUquadricObj *qobj,

GLdouble innerRadius,

GLdouble outerRadius,

GLdouble startAngle,

GLdouble sweepAngle

В начале занятия вы научились строить трехмерные объекты с помощью функций из библиотеки Auxilary Library. Функции auxSphere, auxCylinder и auxCone просто вызывают gluSphere и gluCylinder. В auxCylinder и auxCone фирмы Microsoft имеются баги. Здесь будет подробно рассмотрено построение сфер и цилиндров, так что потребность в auxCylinder и auxCone отпадет.

Первым параметром для gluSphere, gluCylinder, gluDisk и gluPartialDisk является указатель на объект типа GLUquadricObj. Далее следуют параметры непосредственно создаваемой фигуры. Для сферы – это радиус; для цилиндра – радиус нижнего основания, радиус верхнего основания и высота; для диска – внутренний радиус, внешний радиус и для частичного диска – внутренний радиус, внешний радиус, угол, с которого начинать рисовать, длина дуги в градусах, которую рисовать. Последние два параметра у всех этих функций одинаковы. Это число разбиений вокруг оси Z и число разбиений вдоль оси Z. Как известно, все сложные объекты состоят из простых: точек, линий и многоугольников. Понятно, что нарисовать (создать) идеально гладкую сферу или цилиндр невозможно. Поэтому строится приближение из плоскостей. Для этого и нужно указать количество разбиений. Чем больше разбиение, тем лучше будет выглядеть ваш объект. Однако, задавать здесь число с шестью нулями не стоит. Это лишено всякого смысла. Оптимальным является число от 10 до 20. Чем больше объект, тем больше нужно разбиений. Число разбиений (вдоль и поперек) лучше выставлять одинаковыми.

Сначала необходимо создать объект типа GLUquadricObj с помощью функции

GLUquadricObj * gluNewQuadric(void);

Затем нужно установить свойства с помощью функции

Void gluQuadricDrawStyle(

GLUquadricObj *qobj,

Glenum drawStyle

Доступны стили:

GLU_FILL – рисуется сплошной объект;

GLU_LINE – проволочный объект;

GLU_POINT – рисуются только точки.

Удалить созданный объект можно, воспользовавшись функцией

Void gluDeleteQuadric(GLUquadricObj * state);

Теперь можно поэкспериментировать. Измените функцию display следующим образом.

Void display(void)

GLUquadricObj * quadObj;

// создаем новый объект для создания сфер и цилиндров

quadObj = gluNewQuadric();

glColor3d(1,0,0);

// устанавливаем стиль: сплошной

gluQuadricDrawStyle(quadObj, GLU_FILL);

// рисуем сферу радиусом 0.5

gluSphere(quadObj, 0.5, 10, 10);

glTranslated(-2,0,0); // сдвигаемся влево

glRotated(45, 1,0,0); // поворачиваем

glColor3d(0,1,0);

// устанавливаем стиль: проволочный

gluQuadricDrawStyle(quadObj, GLU_LINE);

gluCylinder(quadObj, 0.5, 0.75, 1, 15, 15);

gluDeleteQuadric(quadObj);

auxSwapBuffers();

7. Плоскости отсечения

Если требуется нарисовать сферу или любой другой объект урезанным, то это можно сделать с помощью плоскости отсечения. Плоскостей отсечения может быть шесть. По умолчанию они все запрещены. Плоскость отсечения включается командой glEnable(GL_CLIP_PLANE0). Ноль на конце GL_CLIP_PLANE означает нулевую плоскость; можно указать один, два, три и т. д. Сама плоскость устанавливается функцией

Void glClipPlane(

const GLdouble *equation

Первый аргумент этой функции – это плоскость, второй – это массив из четырех элементов, в котором хранятся коэффициенты (A, B, C, D) уравнения плоскости: A*x + B*y + C*z + D = 0. Измените функцию display, как показано ниже.

Void display(void)

GLdouble equation = {-1,-0.25,0,2};

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_CLIP_PLANE0);

glClipPlane(GL_CLIP_PLANE0, equation);

glColor3d(1,0,0);

auxSolidSphere(3);

glDisable(GL_CLIP_PLANE0);

auxSwapBuffers();

8. Задания

1. Нарисовать куб представляющий собой пространство RGB. Вершины куба имеют цвета: R – красный, G – зеленый, B – синий, C – голубой, M – пурпурный, Y – желтый, W – белый, K – черный. Цвет каждого ребра плавно изменяется от цвета одной вершины до цвета другой.

После того, как куб нарисован, осуществить сдвиг его так, чтобы начало координат совпало с центром куба, а затем поворот вокруг оси OX на угол 30° и вокруг оси OZ на угол -20°.

2. Нарисовать сцену, в которой в начале координат изображается сфера радиуса r. На расстоянии R1 от первой сферы в некоторой точке (x1, y1, 0) изображается сфера с радиусом r1. От нее на расстоянии R2 в некоторой точке (x2, y2, 0) изображается сфера радиуса r2.

После того как сцена нарисована необходимо ее «оживить», т. е. заставить вращаться сферу r1 вокруг сферы r, а сферу r2 вокруг r1. Для этого необходимо объявить глобальные переменные f1 и f2 – углы поворота соответственно r1 вокруг r и r2 вокруг r1. Затем перед каждым выводом инкрементировать f1f2 на постоянные величины и вычислять x1, y1, x2, y2 по следующим формулам.

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

Читатель, наверное, знает, что OpenGL это оптимизированная, высокопроизводительная графическая библиотека функций и типов данных для отображения двух-и трехмерной графики. Стандарт OpenGL был утвержден в 1992 г. Он основан на библиотеке IRIS GL, разработанной компанией Silicon Graphics (www.sgi.com). OpenGL поддерживают все платформы. Кроме того, OpenGL поддержана аппаратно. Существуют видеокарты с акселераторами и специализированные SD-карты, которые выполняют примитивы OpenGL на аппаратном уровне.

Материал первой части этого урока навеян очень хорошей книгой (доступной в online-варианте) издательства Addison-Wesley "OpenGL Programming Guide, The Official Guide to Learning OpenGL". Если читатель владеет английским языком, то мы рекомендуем ее прочесть.

Подключаемые библиотеки

Microsoft-реализация OpenGL включает полный набор команд OpenGL, то есть глобальных функций, входящих в ядро библиотеки OPENGL32.LIB и имеющих префикс gl (например, glLineWidth). Заметьте, что функции из ядра библиотеки имеют множество версий, что позволяет задать желаемый параметр или настройку любым удобным вам способом. Посмотрите справку по функциям из семейства glColor*. Оказывается, что задать текущий цвет можно 32 способами. Например, функция:

Void glColorSb(GLbyte red, GLbyte green, GLbyte blue);

Определяет цвет тремя компонентами типа GLbyte, а функция:

Void glColor4dv (const GLdouble *v);

Задает его с помощью адреса массива из четырех компонентов.

С учетом этих вариантов ядро библиотеки содержит более 300 команд. Кроме того, вы можете подключить библиотеку утилит GLU32.LIB, которые дополняют основное ядро. Здесь есть функции управления текстурами, преобразованием координат, генерацией сфер, цилиндров и дисков, сплайновых аппроксимаций кривых и поверхностей (NURBS - Non-Uniform Rational B-Spline ), а также обработки ошибок. Еще одна, дополнительная (auxiliary ) библиотека GLAUX.LIB позволяет простым способом создавать Windows-окна, изображать некоторые SD-объекты, обрабатывать события ввода и управлять фоновым процессом. К сожалению, эта библиотека не документирована. Компания Microsoft не рекомендует пользоваться ею для разработки коммерческих проектов, так как она содержит код цикла обработки сообщений, в который невозможно вставить обработку других произвольных сообщений.

Примечание
Тип GLbyte эквивалентен типу signed char, a GLdouble - типу double. Свои собственные типы используются в целях упрощения переносимости на другие платформы. Список типов OpenGL мы приведем ниже. Четвертый компонент цвета определяет прозрачность цвета, то есть способ смешивания цвета фона с цветом изображения. Некоторые команды OpenGL имеют в конце символ v, который указывает, что ее аргументом должен быть адрес массива (вектора). Вектор в математике - это последовательность чисел (координат), единственным образом задающих элемент векторного пространства. Многие команды имеют несколько версий, позволяя в конечном счете задать вектор разными способами
.

Около двадцати Windows GDI-функций создано специально для работы с OpenGL. Большая часть из них имеет префикс wgl (аббревиатура от Windows GL). Эти функции являются аналогами функций с префиксом glx, которые подключают OpenGL к платформе X window System. Наконец, существует несколько Win32-функций для управления форматом пикселов и двойной буферизацией. Они применимы только для специализированных окон OpenGL.