Главная страница

Планета знаний


Скачать 1.68 Mb.
НазваниеПланета знаний
АнкорOpenGL book
Дата14.06.2021
Размер1.68 Mb.
Формат файлаpdf
Имя файлаgltutorialcourse2.pdf
ТипКнига
#217321
страница6 из 9
1   2   3   4   5   6   7   8   9
2) Почему предпочтительнее использование связанных при- митивов?

9.3. Контрольные вопросы

129 3) Какая из двух команд выполняется OpenGL быстрее?
g l V e r t e x 3 f ( 1 , 1 , 1 ) ;
или float vct [ 3 ] = { 1 , 1 , 1 } ;
glVertex3fv ( vct ) ;

Часть III
Создание приложений с
OpenGL
131

Глава 10.
OpenGL-приложения с помощью GLUT
10.1. Структура GLUT-приложения
Далее будем рассматривать построение консольного прило- жения при помощи библиотеки GLUT. Эта библиотека обеспечи- вает единый интерфейс для работы с окнами вне зависимости от платформы, поэтому описываемая ниже структура приложения остается неизменной для операционных систем Windows, Linux и других.
Функции GLUT могут быть классифицированы на несколько групп по своему назначению:
€ инициализация;
€ начало обработки событий;
€ управление окнами;
€ управление меню;
€ регистрация функций с обратным вызовом;
133

134
Глава 10. OPENGL-приложения с помощью GLUT
€ управление индексированной палитрой цветов;
€ отображение шрифтов;
€ отображение дополнительных геометрических фигур (тор,
конус и др.).
Инициализация проводится с помощью функции:
g l u t I n i t ( int * argcp , char ** argv )
Переменная argcp есть указатель на стандартную перемен- ную argc
, описываемую в функции main()
, а argv
 указатель на параметры, передаваемые программе при запуске, который опи- сывается там же. Эта функция проводит необходимые начальные действия для построения окна приложения, и только несколько функций GLUT могут быть вызваны до нее. К ним относятся:
glutInitWindowPosition
( int x , int y )
glutInitWindowSize
( int width , int height )
glutInitDisplayMode
( unsigned int mode)
Первые две функции задают соответственно положение и размер окна, а последняя функция определяет различные режи- мы отображения информации, которые могут совместно зада- ваться с использованием операции побитового ѕилиї (ѕ | ї):
GLUT_RGBA Режим RGBA. Используется по умолчанию, ес- ли не указаны режимы GLUT_RGBA или
GLUT_INDEX
GLUT_RGB То же, что и
GLUT_RGBA
GLUT_INDEX Режим индексированных цветов (использова- ние палитры). Отменяет
GLUT_RGBA
GLUT_SINGLE Окно с одиночным буфером. Используется по умолчанию.
GLUT_DOUBLE Окно с двойным буфером.
Отменяет
GLUT_SINGLE

10.1. Структура GLUT-приложения
135
GLUT_STENCIL Окно с буфером маски.
GLUT_ACCUM Окно с буфером-накопителем.
GLUT_DEPTH Окно с буфером глубины.
Это неполный список параметров для данной функции, од- нако для большинства случаев этого бывает достаточно.
Работа с буфером маски и буфером накопления описана в главе 7.
Функции библиотеки GLUT реализуют так называемый со- бытийно-управляемый механизм. Это означает, что есть некото- рый внутренний цикл, который запускается после соответству- ющей инициализации и обрабатывает одно за другим все собы- тия, объявленные во время инициализации. К событиям отно- сятся: щелчок мыши, закрытие окна, изменение свойств окна,
передвижение курсора, нажатие клавиши и ѕпустоеї (idle) собы- тие, когда ничего не происходит. Для проведения периодической проверки совершения того или иного события надо зарегистри- ровать функцию, которая будет его обрабатывать. Для этого ис- пользуются функции вида:
void glutDisplayFunc
( void (* func ) ( void ) )
void glutReshapeFunc ( void (* func ) ( int width ,
int height ) )
void glutMouseFunc
( void (* func ) ( int button ,
int state , int x , int y ) )
void glutIdleFunc ( void (* func ) ( void ) )
void glutMotionFunc ( void (* func ) ( int x , int y ) ) ;
void glutPassiveMotionFunc (
void (* func ) ( int x , int y ) ) ;
Параметром для них является имя соответствующей функ- ции заданного типа. С помощью glutDisplayFunc()
задается функ- ция рисования для окна приложения, которая вызывается при необходимости создания или восстановления изображения. Для

136
Глава 10. OPENGL-приложения с помощью GLUT
явного указания, что окно надо обновить, иногда удобно исполь- зовать функцию void glutPostRedisplay ( void )
Через glutReshapeFunc()
устанавливается функция обработки изменения размеров окна пользователем, которой передаются новые размеры.
glutMouseFunc()
определяет функцию-обработчик команд от мыши, а glutIdleFunc()
задает функцию, которая будет вызывать- ся каждый раз, когда нет событий от пользователя.
Функция, определяемая glutMotionFunс()
, вызывается, когда пользователь двигает указатель мыши, удерживая кнопку мы- ши.
glutPassiveMotionFunc регистрирует функцию, вызываемую,
если пользователь двигает указатель мыши и не нажато ни од- ной кпопки мыши.
Контроль всех событий происходит внутри бесконечного цик- ла в функции void glutMainLoop
( void )
которая обычно вызывается в конце любой программы, исполь- зующей GLUT. Структура приложения, использующего анима- цию, будет следующей:
#i n c l u d e
void MyIdle ( void )
{
/* Код , который меняет переменные ,
определяющие следующий кадр */
} ;
void MyDisplay ( void )
{
/* Код OpenGL, который отображает кадр */

10.2. GLUT в среде MICROSOFT VISUAL C++ 6.0 137
/* После рисования переставляем буферы */
glutSwapBuffers ( ) ;
} ;
void main ( int argcp , char ** argv )
{
/* Инициализация GLUT */
g l u t I n i t (&argcp , argv ) ;
glutInitWindowSize (640 , 4 8 0 ) ;
glutInitWindowPosition (0 , 0 ) ;
/* Открытие окна */
glutCreateWindow ( "My OpenGL Application " ) ;
/* Выбор режима:
двойной буфер и RGBA цвета */
glutInitDisplayMode (GLUT_RGBA |
GLUT_DOUBLE | GLUT_DEPTH) ;
/* Регистрация вызываемых функций */
glutDisplayFunc ( MyDisplay ) ;
glutIdleFunc ( MyIdle ) ;
/* Запуск механизма обработки событий */
glutMainLoop ( ) ;
} ;
В случае , если приложение должно строить статичное изоб- ражение, можно заменить
GLUT_DOUBLE
на
GLUT_SINGLE
,
так как одного буфера в этом случае будет достаточно, и убрать вызов функции glutIdleFunc()
10.2. GLUT в среде Microsoft Visual C++ 6.0
Перед началом работы необходимо скопировать файлы glut.h,
glut32.lib glut32.dll в каталоги MSVC\Include\Gl, MSVC\Lib,
Windows\System соответственно. Также в этих каталогах на- до проверить наличие файлов gl.h, glu.h, opengl32.lib, glu32.lib,
opengl32.dll, glu32.dll, которые обычно входят в состав Visual
C++ и Windows. При использовании команд из библиотеки

138
Глава 10. OPENGL-приложения с помощью GLUT
GLAUX к перечисленным файлам надо добавить подключаемые файлы библиотеки  glaux.h и glaux.lib.
Для создания приложения надо выполнить следующие дей- ствия:
€ Создание проекта: для этого надо выбрать FileNew
ProjectsWin32 Console Application, набрать имя проекта,
OK.
€ В появившемся окне выбрать ѕAn empty projectї, Finish,
OK.
€ Текст программы можно либо разместить в созданном тек- стовом файле (выбрав FileNewFilesText File), либо добавить файл с расширением *.c или *.cpp в проект (вы- брав ProjectAdd To ProjectFiles).
€ Подключить к проекту библиотеки OpenGL. Для этого на- до выбрать ProjectSettingsLink и в поле Object\library modules набрать названия нужных библиотек: opengl32.lib,
glu32.lib, glut32.lib и, если надо, glaux.lib.
€ Для компиляции выбрать BuildBuild program.exe, для выполнения  BuildExecute program.exe.
€ Чтобы при запуске не появлялось текстовое окно, надо вы- брать ProjectSettingsLink и в поле Project Options вме- сто ѕsubsystem:consoleї набрать ѕsubsystem:windowsї, и на- брать там же строку ѕ/entry:mainCRTStartupї.
Когда программа готова, рекомендуется перекомпилировать ее в режиме ѕReleaseї для оптимизации по быстродействию и объему. Для этого надо выбрать BuildSet Active Conguration и отметить ѕ. . . -Win32 Releaseї, а затем заново подключить необ- ходимые библиотеки.

10.3. GLUT в среде MICROSOFT VISUAL C++ 2005 139 10.3. GLUT в среде Microsoft Visual C++
2005
Перед началом работы необходимо скопировать файлы glut.h,
glut32.lib и glut32.dll в каталоги MVS8\VC\PlatformSDK\Include,
MVS8\VC\PlatformSDK\Lib, Windows\System соответственно.
Также в этих каталогах надо проверить наличие файлов gl.h,
glu.h, opengl32.lib, glu32.lib, opengl32.dll, glu32.dll, которые обыч- но входят в состав Visual C++ и Windows. При использовании команд из библиотеки GLAUX к перечисленным файлам надо добавить подключаемые файлы библиотеки  glaux.h и glaux.lib.
Для создания приложения надо выполнить следующие дей- ствия:
€ Создание проекта: для этого надо выбрать FileNew
ProjectsWin32Win32 Console Application, набрать имя проекта, OK.
€ В появившемся окне во вкладке Application Settings вы- брать ѕConsole applicationї, ѕAn empty projectї, Finish.
€ Текст программы можно либо разместить в созданном текстовом файле (выбрав FileNewFilesVisual C++
C++File ), либо добавить файл с расширением *.c или *.cpp в проект (выбрав ProjectAdd To ProjectFiles).
€ Подключить к проекту библиотеки OpenGL. Для этого на- до выбрать ProjectPropertiesConguration Properties
LinkerInput и в поле Additional dependencies набрать на- звания нужных библиотек: opengl32.lib, glu32.lib, glut32.lib и, если надо, glaux.lib.
€ Для компиляции выбрать Build program.exe, для выпол- нения  DebugStart Debugging или DebugStart Without
Debugging.

140
Глава 10. OPENGL-приложения с помощью GLUT
€ Чтобы при запуске программы не появлялось консольное текстовое окно, надо выбрать ProjectProperties
Conguration
PropertiesLinkerSystem и
в поле
SubSystem вместо ѕConsoleї выбрать ѕWindowsї. Пе- рейти в раздел LinkerAdvanced и в поле Entry Point написать ѕwmainCRTStartupї (без кавычек).
Когда программа готова, рекомендуется перекомпилировать ее в режиме ѕReleaseї для оптимизации по быстродействию и объему. Для этого надо выбрать BuildConguration Manager и в поле ѕActive solution congurationї выбрать ѕReleaseї, а затем заново подключить необходимые библиотеки для этой конфигу- рации.
10.4. GLUT в среде Borland C++ Builder 6
Перед началом работы необходимо скопировать файлы glut.h, glut32.lib, glut32.dll в каталоги CBuilder6\Include\Gl,
CBuilder6\Lib, Windows\System соответственно. Также в этих каталогах надо проверить наличие файлов gl.h, glu.h,
opengl32.lib, glu32.lib, opengl32.dll, glu32.dll, которые обычно входят в состав Borland C++ и Windows.
При этом надо учитывать, что оригинальные (для Microsoft
Visual C++) версии файла glut32.lib c Borland C++ Builder
6 работать не будут, и следует использовать только совмести- мую версию. Чтобы создать такую версию, надо использовать стандартную программу 'implib', которая находится в каталоге
СBuilder6\Bin. Для этого в командной строке надо выполнить команду implib glut32.lib glut32.dll которая создает нужный lib-файл из соответствующего dll-фай- ла.

10.5. GLUT в среде BORLAND C++ BUILDER 2006 141
Для создания приложения надо выполнить следующие дей- ствия:
€ Создание проекта: для этого надо выбрать FileNew
OtherConsole Wizard, OK.
€ В появившемся окне выбрать Source Type  С++, Console
Application, сбросить опции ѕUse VCLї, ѕUse CLXї, ѕMulti
Threadedї. Нажать ОК.
€ Текст программы можно либо разместить в созданном текстовом файле, либо удалить его из проекта (Project
Remove From Project) и добавить файл с расширением *.c или *.cpp в проект (выбрав ProjectAdd To Project).
€ Сохраните созданный проект в желаемом каталоге (выбрав
FileSave All).
€ Подключить к проекту библиотеку GLUT. Для этого надо выбрать ProjectAdd To Project и добавить файл glut32.lib
€ Для компиляции выбрать ProjectBuild . . . , для выполне- ния  RunRun.
Когда программа готова, рекомендуется перекомпилировать ее в режиме ѕReleaseї для оптимизации по быстродействию и объему. Для этого сначала надо выбрать ProjectOptions
Compiler и нажать кнопку ѕReleaseї.
10.5. GLUT в среде Borland C++ Builder
2006
Перед началом работы необходимо скопиро- вать файлы glut.h,
glut32.lib,
glut32.dll в
катало- ги
Borland\BDS\4.0\Include\Gl,
Borland\BDS\4.0\Lib,

142
Глава 10. OPENGL-приложения с помощью GLUT
Windows\System соответственно. Также в этих каталогах надо проверить наличие файлов gl.h, glu.h, opengl32.lib, glu32.lib,
opengl32.dll, glu32.dll, которые обычно входят в состав Borland
C++ и Windows.
При этом надо учитывать, что оригинальные (для Microsoft
Visual C++) версии файла glut32.lib c Borland C++ Builder
6 работать не будут, и следует использовать только совмести- мую версию. Чтобы создать такую версию, надо использовать стандартную программу 'implib', которая находится в каталоге
Borland\BDS\4.0\Bin. Для этого в командной строке надо вы- полнить команду implib glut32.lib glut32.dll которая создает нужный lib-файл из соответствующего dll-фай- ла.
Для создания приложения надо выполнить следующие дей- ствия:
€ Создание проекта: для этого надо выбрать FileNew
OtherConsole Application, OK.
€ В появившемся окне выбрать Source Type  ѕС++ї, ѕConsole
Applicationї, сбросить опции ѕUse VCLї, ѕMulti Threadedї.
Нажать ОК.
€ Текст программы можно либо разместить в созданном текстовом файле, либо удалить его из проекта (Project
Remove From Project) и добавить файл с расширением *.c или *.cpp в проект (выбрав ProjectAdd To Project).
€ Сохраните созданный проект в желаемом каталоге (выбрав
FileSave All).
€ Подключить к проекту библиотеку GLUT. Для этого надо выбрать ProjectAdd To Project и добавить файл glut32.lib

10.5. GLUT в среде BORLAND C++ BUILDER 2006 143
€ Для компиляции выбрать ProjectBuild . . . , для выполне- ния  RunRun.
Когда программа готова, рекомендуется перекомпилировать ее в режиме ѕReleaseї для оптимизации по быстродействию и объему. Для этого надо выбрать ProjectBuild Congurations и в списке ѕConguration nameї выбрать ѕRelease Buildї.

Глава 11.
Использование OpenGL в
MFC и VCL
Далее будем рассматривать принципы построение оконного приложения Windows с поддержкой OpenGL при помощи воз- можностей библиотек MFC (Microsoft Foundation Classes) и VCL
(Visual Component Library).
Поскольку Windows является многооконной операционной системой, основная задача приложения на этапе инициализа- ции  ѕпривязатьї команды OpenGL к конкретному окну и со- здать для этого окна все вспомогательные буферы (буфер кадра,
буфер глубины и т.п.). Сама библиотека не содержит средств для этого, поэтому каждая операционная система, поддерживающая
OpenGL, предоставляет свои. Библиотека GLUT представля- ет унифицированный интерфейс для доступа к этой функцио- нальности, однако платой за унификацию является достаточно скромные возможности построения графического интерфейса пользователя, реализованные в GLUT. Для создания приложе- ний с развитым интерфейсом необходимо применять средства конкретной операционной системы для работы с OpenGL.
Для инициализации и работы с OpenGL в Windows необхо-
145

146
Глава 11. Использование OPENGL в MFC и VCL
димо выполнить следующие шаги:
1) инициализация (при создании окна);
а) получение и установка контекста графического устрой- ства (см. п.11.1);
б) установка пиксельного формата (п.11.2);
в) получение и установка контекста рисования (п.11.3);
2) рисование с помощью OpenGL в окне;
3) освобождение контекстов (при удалении окна).
11.1. Контекст устройства
Контекст устройства (device context)  важный элемент гра- фики в среде ОС Windows. Контекст устройства указывает место отображения графических команд. Контекстом может быть окно программы на экране, принтер, или другое устройство, поддер- живающее графический вывод.
Идентификатор контекста устройства  это числовое значе- ние, знание которого позволяет направить графический вывод в нужный контекст. Перед началом рисования необходимо по- лучить это числовое значение, а после рисования нужно кон- текст освободить, т.е. вернуть используемые ресурсы в систему.
Несоблюдение этого правила чревато такими последствиями как утечки памяти и прекращение нормальной работы программы.
Поскольку нашей задачей является рисование в окне, кон- текст устройства hDC
можно получить по идентификатору окна hWnd
:
HWND hWnd = <код получение идентификатора окна >;
HDC hDC = GetDC(hWnd) ;
Для освобождения контекста используется команда
ReleaseDC
:
ReleaseDC (hWnd, hDC) ;

11.2. Установка формата пикселей
147 11.2. Установка формата пикселей
После получения контекста устройств нужно установить фор- мат пикселей (pixel format) контекста. Это нужно для того, что- бы сообщить операционной системе, какие ресурсы необходимо выделить для данного контекста. Формат пикселей указывает,
какие возможности OpenGL мы будем использовать: двойной буфер, буфер маски, буфер глубины, формат цвета и т.д.
Чтобы установить формат пикселя, нужно заполнить струк- туру
PIXELFORMATDESCRIPTOR
и передать ее в текущий кон- текст:
PIXELFORMATDESCRIPTOR pfd ;
// обнуляем все только что созданной структуры ;
ZeroMemory(&pfd , sizeof ( pfd ) ) ;
// заполняем структуру pfd . nSize = sizeof ( pfd ) ;
pfd . nVersion = 1 ;
// флаги показывают , что мы будем использовать
// дублирующую буферизацию OpenGL в этом окне
Pfd . dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER;
pfd . iPixelType = PFD_TYPE_RGBA;
// полноцветный буфер цвета (8 бит на канал )
pfd . cColorBits = 2 4;
// запрашиваем 16 бит на пиксель для буфера глубины pfd . cDepthBits = 1 6 ;
pfd . iLayerType = PFD_MAIN_PLANE;
int iFormat = ChoosePixelFormat (hDC, &pfd ) ;
SetPixelFormat (hDC, iFormat , &pfd ) ;
Рассмотрим подробнее функции, которые используются для установки формата пикселя:
int ChoosePixelFormat (
HDC hdc ,
CONST PIXELFORMATDESCRIPTOR *
ppfd ) ;

148
Глава 11. Использование OPENGL в MFC и VCL
Эта функция позволяет по контексту графического устрой- ства найти пиксельный формат, максимально удовлетворяющий нашим требованиям, и возвращает его дескриптор. Например,
если запрошен 24-битный буфер цвета, а контекст графического устройства предоставляет только 8-битный буфер, то функция возвратит формат пикселя с 8-битным буфером.
Функция
SetPixelFormat устанавливает формат пикселя в кон- текст графического устройства:
BOOL SetPixelFormat (
HDC hdc ,
int iPixelFormat ,
CONST PIXELFORMATDESCRIPTOR *
ppfd ) ;
Поскольку мы используем контекст графического устройства с двойным буфером, OpenGL-рисование в контекст происходит в невидимое на экране место в памяти. Это необходимо для предотвращения мерцания. Для того, чтобы изображение появи- лось на экране, нужно вызвать следующую функцию:
SwapBuffers ( hDC ) ;
11.3. Контекст рисования (render context)
Контекст рисования определяет в какой контекст устройства будут направляться команды OpenGL. Например, если в про- грамме есть несколько окон OpenGL, то перед вызовом команд
OpenGL необходимо указать окно, в которое будут направлены эти команды. С контекстом рисования ассоциировано текущее состояние OpenGL, текстуры, дисплейные списки и т.п.
Создание контекста рисования hRC
:
HGLRC hRC;
hRC = wglCreateContext (hDC) ;
Перед использованием контекста необходимо сделать его те- кущим:

11.4. Класс GLRC
149
wglMakeCurrent (hDC, hRC) ;
Далее можно свободно использовать команды OpenGL, не за- бывая вызывать
SwapBuers после окончания рисования кадра.
После использования контекста рисования его нужно освобо- дить (обычно перед освобождением соответствующего контекста устройства):
wglDeleteContext (hRC) ;
11.4. Класс GLRC
В п.Б.5 приведен пример класса
GLRC
, реализующий пере- численные операции. Цикл инициализации и рисования с исполь- зованием этого класса выглядит следующим образом:
GLRC* m_pGLRC;
// 1. инициализация окна m_pGLRC = new GLRC(hWnd) ;
bool r e s = m_pGLRC?>Create ( ) ;
i f ( ! r e s )
Error ( "Невозможно создать контекст OpenGL" ) ;
// 2. рисование
// ( обычно в обработчиках события WM_PAINT)
bool r e s = m_pGLRC?>MakeCurrent ( ) ;
i f ( ! r e s )
Error ( "Невозможно сделать контекст текущим" ) ;
// команды OpenGL
g l C l e a r (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
// завершение кадра m_pGLRC?>SwapBuffers ( ) ;

150
Глава 11. Использование OPENGL в MFC и VCL
// 3. уничтожение окна
//
( обычно в обработчиках события WM_DESTROY)
m_pGLRC?>Destroy ( ) ;
delete m_pGLRC;
11.5. Использование OpenGL c MFC
Если при создании Windows-приложения используется биб- лиотека MFC, то необходимо встроить инициализацию, освобож- дение контекстов и рисование OpenGL в различные обработчики унаследованных классов MFC. Данная книга не является руко- водством по программированию с использованием MFC, поэтому ограничимся советами по использованию OpenGL с этой библио- текой:
€ Код инициализации и рисования теперь должен находиться в методах (или вызываться из этих методов) класса, уна- следованного от класса
CWnd напрямую или косвенно.
€ Для инициализации OpenGL лучше всего использовать ме- тод
OnCreate
, для рисования 
OnPaint
,
OnUpdate
,
OnDraw или
OnTimer
(это зависит от разных факторов, например,
от какого именно класса унаследован класс OpenGL-окна и что именно изображается).
€ Для предотвращения мерцания необходимо перегрузить обработчик сообщения
WM_ERASEBKGND
, иначе Windows будет заливать фон окна перед вызовом обработчика
OnPaint
€ Для освобождения подойдет обработчик
OnDestroy
, а для обработки изменений размера окна 
OnSize
€ Получить идентификатор окна можно с помощью метода
CWnd::GetSafeHwnd

11.5. Использование OPENGL C MFC
151
Пример класса окна, рисование в которое осуществляется при помощи OpenGL.
class OpenGLWindow : public CWnd
{
public :
OpenGLWindow ( ) ;
// открытые члены класса private :
// закрытые члены класса
// сигнатуры этих методов определены заранее MFC
// и должны выглядеть именно так afx_msg int OnCreate (LPCREATESTRUCT l p C rea teS tru c t ) ;
afx_msg BOOL OnEraseBkgnd (CDC* pDC) ;
afx_msg void OnPaint ( ) ;
afx_msg void OnDestroy ( ) ;
// объявление карты сообщений Windows
DECLARE_MESSAGE_MAP( )
// класс для хранения контекстов OpenGL
GLRC* m_pGLRC;
} ;
Реализация методов:
// конструктор
OpenGLWindow : : OpenGLWindow( )
: m_pGLRC(NULL)
{
}
// заполнение карты сообщений
BEGIN_MESSAGE_MAP(OpenGLWindow , CWnd)
// стандартные макросы MFC
ON_WM_CREATE( )
ON_WM_PAINT( )

152
Глава 11. Использование OPENGL в MFC и VCL
ON_WM_DESTROY( )
ON_WM_ERASEBKGND( )
END_MESSAGE_MAP( )
// в этом методе реализуем инициализацию afx_msg int OpenGLWindow : : OnCreate (
LPCREATESTRUCT l pCre at e St ruct )
{
m_pGLRC = new GLRC( GetSafeHwnd ( ) ) ;
bool r e s = m_pGLRC?>Create ( ) ;
i f ( ! r e s )
return FALSE;
return CWnd: : OnCreate ( l pC reat eS tru c t ) ;
}
// запрещаем заливку фона afx_msg BOOL OpenGLWindow : : OnEraseBkgnd (CDC* pDC)
{
return FALSE;
}
// здесь рисуем afx_msg void OpenGLWindow : : OnPaint ( )
{
CWnd: : OnPaint ( ) ;
// делаем текущим m_glRC?>MakeCurrent ( ) ;
g l C l e a r (GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT) ;
// рисуем то, что хотим нарисовать
<методы рисования OpenGL>

11.6. Использование OPENGL C VCL
153
m_glRC?>SwapBuffers ( ) ;
}
// здесь происходит освобождение ресурсов afx_msg void OpenGLWindow : : OnDestroy ( )
{
m_glRC?>Destroy ( ) ;
delete m_glRC;
CWnd: : OnDestroy ( ) ;
}
11.6. Использование OpenGL c VCL
Использование OpenGL с VCL  другой популярной биб- лиотекой для разработки Windows-приложений, отличается от предыдущего примера только деталям и названиями классов.
Вот пример минимального кода на С++, который добавит
OpenGL к форме (окну) VCL:
class OpenGLForm : public TForm
{
public :
__fastcall OpenGLForm(TComponent* owner ) ;
// открытые члены класса private :
// закрытые члены класса
GLRC* m_pGLRC;
// контекст устройства окна published :
// сигнатуры этих методов определены заранее void __fastcall FormCreate ( TObject* sender ) ;
void __fastcall FormDestroy ( TObject* sender ) ;

154
Глава 11. Использование OPENGL в MFC и VCL
void __fastcall FormPaint ( TObject* sender ) ;
} ;
// конструктор
__fastcall OpenGLForm : : OpenGLForm(
TComponent* owner )
: TForm( owner ) ,
m_pGLRC(NULL)
{
}
// в этом методе реализуем инициализацию void __fastcall OpenGLForm : : FormCreate (
TObject* sender )
{
m_pGLRC = new GLRC( Handle ) ;
bool r e s = m_pGLRC?>Create ( ) ;
a s s e r t ( r e s ) ;
}
// здесь рисуем void __fastcall OpenGLForm : : FormPaint (
TObject* sender )
{
// делаем текущим m_glRC?>MakeCurrent ( ) ;
g l C l e a r (GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT) ;
// рисуем то, что хотим нарисовать
<методы рисования OpenGL>
m_glRC?>SwapBuffers ( ) ;
}
// здесь происходит деинициализация

11.6. Использование OPENGL C VCL
155
void __fastcall OpenGLForm : : FormDestroy ( )
{
m_glRC?>Destroy ( ) ;
delete m_glRC;
}

Глава 12.
OpenGL в .NET
В этом разделе рассматривается построение оконного прило- жения с поддержкой OpenGL на платформе Microsoft .NET.
Несмотря на то, что OpenGL не имеет встроенной поддерж- ки в .NET, в настоящее время существует достаточно много ре- шений, позволяющих подключать OpenGL к .NET-программам.
Мы рассмотрим работу с одной из них  свободно-распространя- емой библиотекой Tao Framework.
Tao Framеwork (http://www.taoframework.com) реализует про- межуточный уровень между .NET приложением и различными
Win32-библиотеками, в частности GL, GLU, GLUT, WGL.
12.1. GLUT в среде Microsoft Visual C# 2005
Простейшим способом создания OpenGL-приложения с среде
.NET можно считать использование библиотеки GLUT, доступ- ной через .NET-компоненту Tao.FreeGlut.
Далее приводятся шаги, необходимые для создания консоль- ного .NET-приложения в среде Microsoft Visual C# 2005 на C#
с GLUT и OpenGL:
157

158
Глава 12. OPENGL в .NET
€ Убедиться, что на машине установлен GLUT (glut32.dll ле- жит в Windows\System32).
€ Создание проекта консольного приложения: FileNew
ProjectsVisual C#WindowsConsole Application, на- брать имя проекта, OK.
€ Добавление Tao к проекту: ProjectAdd Reference.NET,
найти в списке ѕTao Framework OpenGL Binding For .NETї
и ѕTao Framework FreeGLUT Binding For .NETї, выделить оба, ОК. Если компонент нет в списке, необходимо найти их в инсталляционном каталоге библиотеки Tao Framework и добавить через вкладку Browse.
Программирование с использование GLUT и OpenGL в .NET
на C# практически не отличается от варианта для Win32 и C++.
Ниже приведен пример простой программы, аналогичной приме- ру из п.2.5:
Программа 12.1. Простой пример OpenGL в C#.
using Tao . FreeGlut ;
using Tao . OpenGl ;
namespace gl_glut_net
{
class Program
{
private static int Width = 512;
private static int Height = 512;
public const int CubeSize = 200;
static void Display ( )
{
int l e f t , right , top , bottom ;

12.1. GLUT в среде MICROSOFT VISUAL C# 2005 159
l e f t = ( Width ? CubeSize ) / 2 ;
r i g h t = l e f t + CubeSize ;
bottom = ( Height ? CubeSize ) / 2 ;
top = bottom + CubeSize ;
Gl . gl Cl e a rC o l o r ( 0 . 7 f , 0 . 7 f , 0 . 7 f , 1 ) ;
Gl . g l C l e a r ( Gl .GL_COLOR_BUFFER_BIT) ;
Gl . glColor3ub (255 , 0 , 0 ) ;
Gl . glBegin ( Gl .GL_QUADS) ;
Gl . g l V e r t e x 2 f ( l e f t , bottom ) ;
Gl . g l V e r t e x 2 f ( l e f t , top ) ;
Gl . g l V e r t e x 2 f ( right , top ) ;
Gl . g l V e r t e x 2 f ( right , bottom ) ;
Gl . glEnd ( ) ;
Gl . g l F i n i s h ( ) ;
}
static void Reshape ( int w, int h)
{
Width = w;
Height = h ;
Gl . glViewport (0 , 0 , w, h ) ;
Gl . glMatrixMode ( Gl .GL_PROJECTION) ;
Gl . g lLo ad Identity ( ) ;
Gl . glOrtho (0 , w, 0 , h , ?1.0 , 1 . 0 ) ;
Gl . glMatrixMode ( Gl .GL_MODELVIEW) ;
Gl . glLo ad Ide nt it y ( ) ;
}
static void Keyboard ( byte key , int x , int y )

160
Глава 12. OPENGL в .NET
{
const int ESCAPE = 2 7 ;
i f ( key == ESCAPE)
Glut . glutLeaveMainLoop ( ) ;
}
static void Main ( s t r i n g [ ] args )
{
Glut . g l u t I n i t ( ) ;
Glut . glutInitDisplayMode ( Glut .GLUT_RGB) ;
Glut . glutInitWindowSize ( Width , Height ) ;
Glut . glutCreateWindow ( "Red square example" ) ;
Glut . glutDisplayFunc ( Display ) ;
Glut . glutReshapeFunc ( Reshape ) ;
Glut . glutKeyboardFunc ( Keyboard ) ;
Glut . glutMainLoop ( ) ;
}
}
}
Обратите внимание, что все команды и константы GL, GLU
и GLUT находятся в пространствах имен
Gl
,
Glu и
Glut
, соответ- ственно.
12.2. Использование OpenGL в WindowsForms
OpenGL в WindowsForms требует инициализации, аналогич- ной рассмотренной для библиотек MFC и VCL (см. п.11). В
Tao Framework уже реализован простой класс окна OpenGL 
Tao.Platform.Windows.SimpleOpenGlControl
Рассмотрим последовательность действий, необходимую для

12.2. Использование OPENGL в WINDOWSFORMS
161
создания простого оконного приложения в WindowsForms и с поддержкой OpenGL:
€ Создание проекта приложения: FileNewProjectsVisual
C#WindowsWindows Application, набрать имя проек- та, OK.
€ Добавление Tao к проекту: ProjectAdd Reference.NET,
найти в списке ѕTao Framework OpenGL Binding For .NETї
и ѕTao Framework Windows Platform API Binding For .NETї,
выделить оба, ОК. Если компонент нет в списке, необходи- мо найти их в инсталляционном каталоге библиотеки Tao
Framework и добавить через вкладку Browse.
€ Чтобы удобно создать окно OpenGL, необходимо добавить соответствующий объект на панель инструментов. Для этого нужно в контекстном меню панели ѕToolboxї вы- брать пункт ѕChoose Items...ї, в появившемся списке най- ти ѕSimpleOpenGLControlї, поставить галочку около него,
ОК.
€ Добавление окна OpenGL на форму: на панели ѕToolboxї
найдите ѕSimpleOpenGLControlї и перетащите на форму приложения. Окно должно заполняться черным цветом.
€ Инициализация OpenGL: в конструкторе формы после вы- зова
InitializeComponent()
добавить вызов функции создания контекста simpleOpenGlControl1.InitializeContexts()
Функции рисования OpenGL можно добавлять в обработчик события
Paint окна OpenGL (не путать с
Paint формы).

Часть IV
Приложения
163

Приложение А.
Примитивы библиотек
GLU и GLUT
Рассмотрим стандартные команды построения примитивов,
которые реализованы в библиотеках GLU и GLUT.
Чтобы построить примитив из библиотеки GLU, надо сна- чала создать указатель на quadric-объект с помощью коман- ды gluNewQuadric()
, а затем вызвать одну из команд gluSphere()
,
gluCylinder()
,
gluDisk()
,
gluPartialDisk()
. Рассмотрим эти команды отдельно:
void gluSphere ( GLUquadricObj
* qobj , GLdouble radius ,
GLint s l i c e s , GLint s t a c k s )
Эта функция строит сферу с центром в начале координат и радиусом radius
. При этом число разбиений сферы вокруг оси z задается параметром slices
, а вдоль оси z  параметром stacks void gluCylinder ( GLUquadricObj
* qobj ,
GLdouble baseRadius ,
GLdouble topRadius ,
GLdouble height , GLint s l i c e s ,
GLint s t a c k s )
165

166
Приложение А. Примитивы библиотек GLU и GLUT
Данная функция строит цилиндр без оснований (кольцо),
продольная ось параллельна оси z, заднее основание имеет ра- диус baseRadius
, и расположено в плоскости z = 0, переднее основание имеет радиус topRadius и расположено в плоскости z = height
. Если задать один из радиусов равным нулю, то будет построен конус. Параметры slices и
stacks имеют аналогичный смысл, что и в предыдущей команде.
void gluDisk ( GLUquadricObj
* qobj ,
GLdouble innerRadius ,
GLdouble outerRadius ,
GLint s l i c e s ,
GLint loops )
Функция строит плоский диск (круг) с центром в начале ко- ординат и радиусом outerRadius
. Если значение innerRadius отлич- но от нуля, то в центре диска будет находиться отверстие ради- усом innerRadius
. Параметр slices задает число разбиений диска вокруг оси z, а параметр loops
 число концентрических колец,
перпендикулярных оси z.
void g l u P a r t i a l D i s k ( GLUquadricObj * qobj ,
GLdouble innerRadius ,
GLdouble outerRadius ,
GLint s l i c e s ,
GLint loops ,
GLdouble startAngle ,
GLdouble sweepAngle ) ;
Отличие этой команды от предыдущей заключается в том,
что она строит сектор круга, начальный и конечный углы ко- торого отсчитываются против часовой стрелки от положитель- ного направления оси y и задаются параметрами startAngle и
sweepAngle
. Углы измеряются в градусах.
Команды, проводящие построение примитивов из библиоте- ки GLUT, реализованы через стандартные примитивы OpenGL

167
и GLU. Для построения нужного примитива достаточно произ- вести вызов соответствующей команды.
void g l u t S o l i d S p h e r e
( GLdouble radius ,
GLint s l i c e s ,
GLint s t a c k s )
void glutWireSphere
( GLdouble radius ,
GLint s l i c e s ,
GLint s t a c k s )
Команда glutSolidSphere()
строит сферу, а glutWireSphere()

каркас сферы радиусом radius. Остальные параметры те же, что и в предыдущих командах.
void glutSolidCube ( GLdouble s i z e )
void glutWireCube
( GLdouble s i z e )
Команды строят куб или каркас куба с центром в начале координат и длиной ребра size.
void glutSolidCone
( GLdouble base , GLdouble height ,
GLint s l i c e s , GLint s t a c k s )
void glutWireCone
( GLdouble base , GLdouble height ,
GLint s l i c e s , GLint s t a c k s )
Эти команды строят конус или его каркас высотой height и
радиусом основания base, расположенный вдоль оси z. Основа- ние находится в плоскости z = 0.
void g lut S o l id T o rus ( GLdouble innerRadius ,
GLdouble outerRadius ,
GLint nsides ,
GLint r i n g s )
void glutWireTorus
( GLdouble innerRadius ,
GLdouble outerRadius ,
GLint nsides ,
GLint r i n g s )
Эти команды строят тор или его каркас в плоскости z = 0.
Внутренний и внешний радиусы контролируются параметрами

168
Приложение А. Примитивы библиотек GLU и GLUT
innerRadius и
outerRadius
. Параметр nsides задает число сторон в кольцах, составляющих ортогональное сечение тора, а rings

число радиальных разбиений тора.
void glutSolidTetrahedron
( void )
void glutWireTetrahedron
( void )
Эти команды строят тетраэдр (правильную треугольную пи- рамиду) или его каркас, при этом радиус описанной сферы во- круг него равен 1.
void glutSolidOctahedron
( void )
void glutWireOctahedron
( void )
Эти команды строят октаэдр или его каркас, радиус описан- ной вокруг него сферы равен 1.
void glutSolidDodecahedron
( void )
void glutWireDodecahedron
( void )
Эти команды строят додекаэдр или его каркас, радиус опи- санной вокруг него сферы равен квадратному корню из трех.
void g l u t S o l i d I c o s a h e d r o n
( void )
void glutWireIcosahedron
( void )
Эти команды строят икосаэдр или его каркас, радиус описан- ной вокруг него сферы равен 1.
Правильное построение перечисленных примитивов возмож- но при удалении невидимых линии и поверхностей, для че- го надо включить соответствующий режим вызовом команды glEnable(GL_DEPTH_TEST)

Приложение Б.
Демонстрационные программы
Б.1. Пример 1: Простое GLUT-приложение
Этот простой пример предназначен для демонстрации струк- туры GLUT-приложения и простейших основ OpenGL. Резуль- татом работы программы является случайный набор цветных прямоугольников, который меняется при нажатии левой кнопки мыши. С помощью правой кнопки мыши можно менять режим заливки прямоугольников.
Программа Б.1. Простой пример OpenGL.
#include
#include
#i f d e f random
#undef random
#endif
#define random (m) ( float ) rand ( ) *m/RAND_MAX
169

170
Приложение Б. Демонстрационные программы
// ширина и высота окна
GLint Width = 512 , Height = 512;
// число прямоугольников в окне int
Times = 100;

1   2   3   4   5   6   7   8   9


написать администратору сайта