Міністерствоосвіти і науки України
Рівненськийдержавний гуманітарний університет
Факультетматематики та інформатики
Кафедраінформатики та прикладної математики
КУРСОВАРОБОТА
натему:
Використання opengl. Моделювання вогню
Виконав:
студент 4 курсу
спеціальності“інформатика”
групи І-41: АнтонішинВ.В.
Науковийкерівник:
ЯрощакСергій Вікторович
Рівне– 2010
ЗМІСТ
ВСТУП
РОЗДІЛ 1. Програмний код та синтаксисOpenGL
1.1Програмний код OpenGL
1.2Синтаксис команд OpenGL
РОзділ 2. Конвеєр візуалізації табібліотеки, що відносяться до OpenGL
2.1 Конвеєрвізуалізації OpenGL
2.1.1Конвеєр
2.1.2 Спискививоду
2.1.3Обчислювачі
2.1.4Операції обробки вершин
2.1.5 Збіркапримітивів
2.1.6Операції обробки пікселів
2.1.7 Збіркатекстури
2.1.8Растеризація
2.1.9Операції обробки фрагментів
2.2 Бібліотеки,що відносяться до OpenGL
2.2.1Бібліотека OpenGL
2.2.2 Файли,що підключаються
2.2.3 GLUT, інструментарій утиліт бібліотеки OpenGL
РОЗДІЛ 3.АНІМАЦІЯ КОМП'ЮТЕРНОЇ ГРАФІКИ НА ПРИКЛАДІ МОДЕЛЮВАННЯ ВОГНЮ
3.1 Анімація комп'ютерної графіки
3.2 Моделювання вогню
ВИСНОВКИ
ЛІТЕРАТУРА
/>ВСТУП
Комп'ютерна графіка знайшла широкепоширення і застосування в повсякденному житті. Учені використовуютькомп'ютерну графіку для аналізу результатів моделювання. Інженери і архітекторивикористовують тривимірну графіку для створення віртуальних моделей.Кінематографісти створюють спецефекти або повністю анімовані фільми («Шрек»,«Історія іграшок» та ін.). Останніми роками широке поширення отримали такожкомп'ютерні ігри, що максимально використовують тривимірну графіку длястворення віртуальних світів.
Поширення комп'ютерної графікисупроводили свої труднощі. У 1990-х розробка програмного продукту, здатногопрацювати на великій кількості графічного устаткування, була зв'язана звеликими часовими і фінансовими витратами. Було необхідно окремо створюватимодулі для кожного типу графічних адаптерів, що іноді призводило до розмноженняоднакового програмного коду. Це сильно гальмувало розвиток і поширеннякомп'ютерної графіки.
Silicon Graphics Incorporated (SGI)спеціалізувалася на створенні високотехнологічного графічного устаткування іпрограмних засобів. Будучи у той час лідером в тривимірній графіці, SGI бачилапроблеми і бар'єри в рості ринку. Тому було прийнято рішення стандартизуватиметод доступу до графічної апаратури на рівні програмного інтерфейсу.
Таким чином з'явився програмнийінтерфейс OpenGL, який стандартизує доступ до графічної апаратури шляхомзміщення відповідальності за створення апаратного драйвера на виробникаграфічного пристрою. Це дозволило розробникам програмного забезпеченнявикористовувати вищий рівень абстракції від графічного устаткування, що значноприскорило створення нових програмних продуктів і понизило на них витрати.
У 1992 році компанія SGI очолила OpenGLARB — групу компаній по розробці специфікації OpenGL. OpenGL еволюціонував з3D-інтерфейса SGI — IRIS GL. Одним з обмежень IRIS GL було те, що він дозволяввикористовувати тільки можливості, підтримувані устаткуванням; якщо можливістьне була реалізована апаратно, застосування не могло її використовувати. OpenGLдолає цю проблему за рахунок програмної реалізації можливостей, що не надаютьсяапаратно і дозволяє використовувати цей інтерфейс на відносно малопотужнихсистемах.
У 1995 році була випущена бібліотекаDirect3D від Microsoft. Незабаром Microsoft, SGI і Hewlett — Packard почалипроект під назвою Fahrenheit, який передбачав створення більше універсальногопрограмного інтерфейсу на основі Direct3D і OpenGL. Ідея здаваласябагатообіцяючою, покликаною навести лад в області інтерактивної тривимірноїграфіки, проте, в результаті фінансових труднощів в SGI і відсутності належноїіндустріальної підтримки, проект був закритий. Правда, пізніше, 16 вересня 2005року, він все-таки був випущений.
OpenGL орієнтується на наступні двазавдання:
· Приховатискладнощі адаптації різних 3D-прискорювачів, надаючи розробникові єдиний API.
· Приховативідмінності в можливостях апаратних платформ, вимагаючи реалізації бракуючоїфункціональності за допомогою програмної емуляції.
Основним принципом роботи OpenGL єотримання наборів векторних графічних примітивів у вигляді точок, ліній ібагатокутників з наступною математичною обробкою отриманих даних і побудовоюрастрової картинки на екрані і в пам'яті. Векторні трансформації ірастеризування виконуються графічним конвеєром, який по суті представляє зсебе дискретний автомат. Абсолютна більшість команд OpenGL потрапляють в одну здвох груп: або вони додають графічні примітиви на вхід в конвеєр, абоконфігурують конвеєр на різне виконання трансформацій.
OpenGL є низькорівневим процедурнимAPI, що змушує програміста диктувати точну послідовність кроків, щоб побудуватирезультуючу растрову графіку (імперативний підхід). Це є основною відмінністювід дескрипторних підходів, коли уся сцена передається у вигляді структуриданих, які обробляються і будуються на екрані. З одного боку, імперативнийпідхід вимагає від програміста глибокого знання законів тривимірної графіки іматематичних моделей, з іншого боку — дає свободу впровадження різнихінновацій.
Метою цієї роботи є вивчитиособливості роботи з відкритою графічною бібліотекою OpenGL та навчитися їїзастосовувати в комп’ютерному моделюванні.
Завдання полягає у написанні програмимоделювання горіння вогню з використанням графічної бібліотеки OpenGL.
Предметом дослідження є комп’ютернаграфіка, а об’єктом дослідження побудова графічних зображень з використаннямвідкритої графічної бібліотеки OpenGL.
/>РОЗДІЛ 1. />Програмний код та синтаксис команд OpenGL
1.1 Програмний код OpenGL
Оскільки за допомогоюграфічної системи OpenGL можна вирішити так багато завдань, OpenGL-програмаможе бути досить важкою для розуміння. Проте основна структура програми можебути проста: її завдання полягають в тому, щоб ініціалізувати деякі стани, якіуправляють тим, як бібліотека OpenGL виконує візуалізацію, і визначити об'єкти,які будуть візуалізовані.
Перш ніж приступити доаналізу деякого програмного коду OpenGL, давайте познайомимося з декількоматермінами. Візуалізація є процесом, за допомогою якого комп'ютер створюєзображення з моделей. Ці моделі, або об'єкти, створюються з геометричнихпримітивів, — точок, ліній і багатокутників, — які визначаються їх вершинами.
Кінцеве візуалізованезображення складається з пікселів, що виводяться на екран; піксель є найменшимвидимим елементом, який апаратні засоби відображення можуть помістити на екран.
Інформація про пікселі(наприклад, який колір передбачається для цих пікселів) організована в пам'ятіу вигляді бітових площин. Бітова площина є областю пам'яті, яка містить одинбіт інформації для кожного пікселя на екрані; цей біт міг би вказувати,наприклад, на те, що конкретний піксель, як передбачається, є червоним. Бітовіплощини, у свою чергу, організовані у буфер кадру, який містить усю інформацію,необхідну графічному дисплею для того, щоб управляти кольором і яскравістю усіхпікселів на екрані.
Приклад 1. Фрагментпрограмного коду OpenGL
finclude,
main () {
InitializeAWindowPlease();
glClearColor(0.0, 0.0, 0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0);
glOrtho(0.0, 1.0, 0.0, 1.0, — 1.0, 1.0); glBegin(GL_POLYGON);
glVertex3f(0.25, 0.25, 0.0);
glVertex3f (0.75, 0.25, 0.0);
glVertex3f(0.75, 0.75, 0.0);
glVertex3f(0.25, 0.75, 0.0);glEnd(); glFlush () ;
UpdateTheWindowAndCheckForEvents();}
Перший рядок функції main()ініціалізував певне вікно на екрані: функція InitializeAWindowPlease() використовуєтьсяв даному випадку в якості мітки-«заповнювача» для підпрограмспецифічних віконних систем, які в загальному випадку не є викликами OpenGL.Наступні два рядки містять команди OpenGL, які встановлюють чорний колір фонудля вікна: функція glCIearCoIor() визначає, який колір фону буде встановленийдля вікна, а функція glClear() фактично встановлює колір вікна. Як тільки колірфону встановлений, вікно заливається цим кольором всякий раз, коли викликаєтьсяфункція glClear(). Цей колір фону може бути змінений за допомогою другоговиклику функції glClearColor(). Так само функція glColor3f() встановлює, якийколір слід використовувати для промальовування об'єктів на екрані — в даномувипадку цей колір є білим. Усі об'єкти, що виводяться на екран після цього моменту,використовують цей колір до тих пір, поки він не буде змінений за допомогоюнаступного виклику команди установки кольору.
Наступна функція OpenGL,використовувана в даній програмі, glOrtho(), визначає систему координат, якуOpenGL приймає для промальовування остаточного зображення, і те, як цезображення відображається на екрані. Виклики, розміщені між функціями glBegin()і glЈnd(), визначають об'єкт, який буде виведений на екран, в даному прикладіце багатокутник з чотирма вершинами. «Кути» багатокутникавизначаються за допомогою функції glVertex3f(). Як ви, напевно, вжездогадалися, виходячи зі значень параметрів цієї функції, які є координатами(х, у, z), цей багатокутник є прямокутником, розташованим на площині z(z — 0).
Нарешті, функція gIFlush() гарантує, що командипромальовування фактично виконуються, а не просто зберігаються в деякомубуфері, чекаючи додаткових команд OpenGL. Підпрограмма-«заповнювач»UpdateTheWindowAndCheckForEvents() управляє вмістом вікна і починає обробкуподій.
1.2 Cинтаксис команд OpenGL
Як ви, ймовірно, моглипомітити з прикладу програми, приведеного в попередньому розділі, командибібліотеки OpenGL використовують префікс gl. Кожне слово, що становитьнайменування команди, починається із заголовної букви (згадайте, наприклад,функцію glClearColor()). Так само імена констант, визначених у бібліотеціOpenGL, починаються з префікса GL_, записуються заголовними буквами івикористовують символи підкреслення, щоб розділити окремі слова (наприклад,GL__COLOR_BUFFER_BIT).
Ви, ймовірно, також змоглипомітити деякі символи, які здалися вам сторонніми, вони додаються в кінецьнайменування деяких команд (наприклад, 3f у функціях glColor3f() іglVertex3f()). Дійсно, частина Color в найменуванні функції glColor3f()достатньо для того, щоб визначити цю команду як команду, що встановлює поточнийколір. Проте було визначено декілька таких команд, щоб ви змогливикористовувати їх з різними типами параметрів. Зокрема, частина 3 суфіксавказує, що для цієї команди задаються три параметри; інша версія команди Colorвикористовує чотири параметри. Частина f суфікса вказує на те, що параметрицієї команди є числами з плаваючою крапкою. Наявність різних форматів дозволяєбібліотеці OpenGL приймати дані користувача в його власному форматі даних.
Деякі команди бібліотекиOpenGL допускають використання 8 різних типів даних в якості своїх параметрів.Букви, використовувані в якості суфіксів для того, щоб визначити ці типи данихдля реалізації ISO З бібліотеки OpenGL, представлені в Таблиці 1.2; там жеприведені відповідні визначення типів у бібліотеці OpenGL. Конкретна реалізаціябібліотеки OpenGL, яку ви використовуєте, може не співпадати в точності зприведеною схемою; наприклад, реалізації для мов програмування C++ або Ada, невимагають цього.
Таблиця 1.2. Суфіксинайменування команд і типи параметрівТип даних Тип, що відповідає типу даних мови програмування С Визначення типів даних бібліотеки OpenGL 8-розрядне ціле signed char GLbyte 16-розрядне ціле short GLshort 32-розрядне ціле Int або long GLint, GLsizei 32-розрядне число з плаваючою крапкою float GLfloat, GLclampf 64-розрядне число з плаваючою крапкою double GLdouble, GLclampd 8-розрядне беззнакове ціле unsigned char GLubyte, GLboolean 16-розрядне беззнакове ціле unsigned short GLushort 32-розрядне беззнакове ціле
unsignedint або
unsigned long GLuint, GLenum, GLbitfield
Таким чином, дві командиglVertex2i (1,3); glVertex2f (1.0, 3.0); є еквівалентними, за винятком того, що перша з них визначаєкоординати вершини як 32-розрядні цілі числа, а друга визначають їх як числа зплаваючою крапкою з одинарною точністю.
Найменування деяких командбібліотеки OpenGL можуть мати завершальний символ v, який вказує на те, що цякоманда приймає покажчик на вектор (чи масив) значень, а не набір індивідуальнихпараметрів. Багато команд мають як векторні, так і невекторні версії, але деякікоманди приймають тільки індивідуальні параметри, тоді як інші командивимагають, щоб, принаймні, деякі з їх параметрів були визначені як вектори.Наступні рядки показують, як можна було б використовувати векторну і невекторнуверсію команди, яка встановлює поточний колір :
glColor3f (1.0, 0.0, 0.0);
gLfloat color_array [] ={1.0, 0.0, 0.0); glColor3fv (color_array);
Нарешті, бібліотека OpenGL визначає тип даних GLvoid. Цейтип даних найчастіше використовується для тих команд бібліотеки OpenGL, якіприймаються як параметри покажчики на масиви значень.
РОЗДІЛ 2. />Конвеєр візуалізації та бібліотеки,що відносяться до OpenGL
2.1 Конвеєр візуалізаціїOpenGL
2.1.1 Конвеєр
Більшість реалізаційбібліотеки OpenGL мають однаковий порядок операцій, певну послідовність стадійобробки, яка називається конвеєром візуалізації OpenGL. Цей порядокфункціонування не є суворим правилом реалізації бібліотеки OpenGL, проте він єнадійним керівництвом для передбачення результату роботи OpenGL.
/>
Рис. 2.1.1. Конвеєрвізуалізації
Наступна діаграма демонструєконцепцію складального конвеєра Генрі Форда, яку бібліотека OpenGL використовуєдля обробки даних. Геометричні дані (вершини, прямі і багатокутники) проходятьчерез послідовність блоків, до числа яких входять обчислювачі і операціїобробки вершин, тоді як піксельні дані (пікселі, зображення і растрові образи)для певної частини процесу візуалізації обробляються по-іншому. Обидва типиданих піддаються одним і тим же завершальним операціям (операції растеризуванняі пофрагментной обробки), перш ніж підсумкові піксельні дані записуються убуфер кадру.
2.1.2 Списки виводу
Усі дані, незалежно від того,чи описують вони геометрію або пікселі, можуть бути збережені в списку виводудля поточного або пізнішого використання. (Альтернативою збереженню даних всписку виводу являється негайна обробка даних, вона також відома під назвоюбезпосередній режим роботи.) Після того, як список виводу був створений,збережені дані посилаються з цього списку виводу точно так, якби вони булипослані прикладною програмою у безпосередньому режимі роботи.
2.1.3 Обчислювачі
Усі геометричні примітивиописуються вершинами. Параметричні криві і поверхні можуть бути спочаткуописані контрольними точками і поліноміальними функціями, які називаютьсябазовими функціями. Обчислювачі надають метод отримання вершин,використовуваний для представлення поверхні по контрольних точках. Такимметодом є поліноміальне відображення, яке може формувати нормаль до поверхні,координати текстури, кольори і значення просторових координат по контрольнихточках.
2.1.4 Операції обробки вершин
Для даних по вершинахнаступною є стадія «операцій обробки вершин», яка перетворює вершинив примітиви. Деякі типи даних по вершинах (наприклад, просторові координати)перетворюються в матриці чисел з плаваючою точкою розміром 4x4. Просторовікоординати проектуються з положення в тривимірному просторі в положення навашому екрані. Якщо дозволено використання розширених функціональнихможливостей, то ця стадія обробки даних ще більше насичена. Якщовикористовується накладення текстур, то на цій стадії можуть бути згенеровані іперетворені координати текстури. Якщо дозволено освітлення, то тут виконуютьсяобчислення параметрів освітлення, для чого використовуються перетворенівершини, нормаль до поверхні, положення джерела освітлення, властивостіматеріалу і інша інформація освітлення, необхідна для набуття значення кольору.
2.1.5 Збірка примітивів
Операція відсікання, основначастина збірки примітивів, є видаленням частин геометрії, яка виходить за межінапівпростору, визначеного деякою площиною. При відсіканні точок простопропускаються або відкидаються вершини; при відсіканні ліній або багатокутниківможуть додаватися додаткові вершини залежно від того, як відсікається лінія абобагатокутник.
В деяких випадках цей процессупроводжується перспективним діленням, яке примушує видалені геометричніоб'єкти здаватися меншими, ніж ближчі об'єкти. Після цього застосовуютьсяоперації отримання вікна перегляду і глибини. Якщо відсікання дозволене, і цейпримітив є багатокутником, тоді він може бути відкинутий в процесі виконаннятесту на відсікання. Залежно від способу побудови багатокутник може бутививедений на екран у вигляді точок або у вигляді ліній.
Результатом виконання цієїстадії є закінчені геометричні примітиви, які є перетвореними і відсіченимивершинами і пов'язаними з ними значеннями кольору, глибини і іноді координатамитекстур, а також вказівки для виконання стадії растеризування.
2.1.6 Операції обробкипікселів
Тоді як геометричні даніслідують одним шляхом по конвеєру візуалізації OpenGL, піксельні дані слідуютьіншим маршрутом. Пікселі з певного масиву в системній пам'яті спочаткурозпаковуються з якого-небудь одного з безлічі форматів в належну кількістькомпонентів. Потім ці дані масштабуються, зміщуються і обробляються задопомогою карти елементів відображення. Після цього результати фіксуються і абозаписуються в область пам'яті, виділеній під текстури, або передаються настадію растеризування.
Якщо піксельні данізчитуються з буфера кадру, то виконуються операції по передачі пікселя(масштабування, зміщення, відображення і фіксація). Потім отримані результатиупаковуються у відповідний формат і повертаються в деякий масив системноїпам'яті.
Існують спеціальні операціїкопіювання пікселів для копіювання даних з буфера кадру в інші частини буферакадру або в область пам'яті, виділену для текстур. Виконується однопрохіднареалізація операцій при передачі пікселя, а потім дані записуються в областьпам'яті, виділену для текстур або назад у буфер кадру.
2.1.7 Збірка текстури
OpenGL-програми можутьнакладати зображення текстури на геометричні об'єкти для того, щоб зробити їхвид реалістичнішим. Якщо використовується декілька зображень текстури, то дужерозумно буде помістити їх в об'єкти текстури для спрощення перемикання міжними.
Деякі реалізації бібліотекиOpenGL можуть мати спеціальні ресурси для прискореного виконання операцій надтекстурами. Це може бути реалізовано як спеціалізована, високопродуктивнаобласть пам'яті, виділена для текстур. Якщо така пам'ять доступна, об'єктитекстури можуть бути впорядковані по пріоритетах для полегшення управління цимобмеженим і цінним ресурсом.
2.1.8 Растеризація
Растеризація є перетвореннямяк геометричних, так і піксельних даних у фрагменти. Кожен квадратний фрагментвідповідає певному пікселю у буфері кадру. Штрихування ліній і багатокутників,ширина лінії, розмір точки, модель зафарбовування і обчислення покриття,необхідні для підтримки згладжування, враховуються як вершини, які з'єднуютьсяв лінії, або як внутрішні пікселі, розраховані для зафарбованого багатокутника.Значення кольору і глибини призначаються для кожного квадратного фрагмента.
2.1.9 Операції обробкифрагментів
Перш ніж значення збережутьсяу буфері кадру, виконується ряд операцій, внаслідок чого фрагменти можуть бутизмінені або навіть відкинуті. Усі ці операції можуть бути включені абовідключені.
Першою операцією, з якоюможна зіткнутися, є накладення текстур. Ця операція полягає в тому, що тексель(елемент текстури) генерується з пам'яті текстур для кожного фрагмента ізастосовується до конкретного фрагмента. Після цього можуть застосовуватисяобчислення туману, які супроводжуються тестом ножиць, альфа-тестом, тестомтрафарету і тестом буфера глибини (тест буфера глибини є видаленням невидимихповерхонь). Невдале завершення включеного теста може припинити тривалу обробкуквадрата фрагмента. Потім можуть бути виконані операції змішування кольорів,псевдозмішування (розмивання) кольорів для передачі півтонів, логічної обробкиі маскування за допомогою бітової маски. Нарешті, повністю оброблений фрагментвиводиться у відповідний буфер, де він остаточно перетворюється на піксель ідосягає свого кінцевого місця розташування.
2.2 Бібліотеки, щовідносяться до OpenGL
2.2.1 Бібліотека OpenGL
Бібліотека OpenGL надаєпотужний, але примітивний набір команд візуалізації, і усі зображення більшвисокого рівня мають бути створені з використанням саме цих команд. Окрім цьогоOpenGL-програми повинні використовувати основні механізми системи управліннявікнами. Існує декілька бібліотек, які дозволяють спростити рішення вашихзавдань в області програмування. До числа цих бібліотек входять наступні:
Бібліотека утиліт OpenGL (GLU- OpenGL Utility Library) містить декілька підпрограм, які використовуютьOpenGL-команди низького рівня для виконання таких завдання, як установкаматриць для певного орієнтування і проектування перегляду, виконання тесселяціїбагатокутників(розбиття довільного багатокутника на опуклі багатокутники) івізуалізацію поверхні. Ця бібліотека надається в якості складової частиникожної реалізації бібліотеки OpenGL. Складові частини біблиотеки GLU описуютьсяв Довіднику по OpenGL {OpenGL Reference Manual).
Для кожної віконної системиіснує бібліотека, яка розширює функціональні можливості цієї віконної системи,щоб забезпечити підтримку візуалізації OpenGL. Для обчислювальних машин, яківикористовують оболонку X Window System, в якості доповнення до бібліотекиOpenGL надається розширення бібліотеки OpenGL для оболонки X Window System(GLX- OpenGL Extension to the X Window System). Підпрограми GLX використовуютьпрефікс glX. Для операційних систем Microsoft Windows 95/98/NT інтерфейсопераційної системи Windows до бібліотеки OpenGL забезпечується підпрограмамибібліотеки WGL. Усі підпрограми WGL використовують префікс wgl.
Для операційної системи OS/2корпорації IBM використовуються PGL-інтерфейс адміністратора представлень(Presentation Manager) до бібліотеки OpenGL, і його підпрограми використовуютьпрефікс pgl. Для комп'ютерів фірми Apple інтерфейсом для графічних систем, щопідтримують бібліотеку OpenGL, являється AGL, і підпрограми AGL використовуютьпрефікс agl.
Інструментарій утилітбібліотеки OpenGL (GLUT — Graphics Library UtilityToolkit) є незалежним відвіконної системи інструментарієм, написаним Марком Килгардом (Mark Kilgard) длятого, щоб приховати складність програмного інтерфейсу прикладних програм (API — ApplicationProgramming Interface) різних віконних систем. Підпрограми GLUTвикористовують префікс glut.
FSG (Fahrenheit Scene Graph)є об'єктно-орієнтованим набором інструментальних засобів, заснованим набібліотеці OpenGL і надаючим об'єкти і методи для створення інтерактивнихтривимірних графічних прикладних програм. FSG написаний на мові програмуванняC++, містить заздалегідь підготовлені об'єкти і вбудовану модель обробки подійпри взаємодії з користувачем, компоненти прикладних програм високого рівня длястворення і редагування тривимірних сцен і можливості для обміну даними в іншихграфічних форматах. FSG не залежний від OpenGL.
2.2.2 Файли, що підключаються
Для усіх OpenGL-програм виможете підключити заголовний файл gl.h в кожен файл проекту. Майже усіOpenGL-програми використовують GLU, вищезгадану Бібліотеку утиліт OpenGL, якавимагає включення заголовного файлу glu.h. Отже майже кожен початковий файлOpenGL-програми починається з наступних рядків:
#include
#include
Операційна система MicrosoftWindows вимагає, щоб заголовний файл windows.h був включений до підключеннязаголовних файлів gl.h або glu.h, оскільки деякі макрокоманди, визначені вMicrosoft Windows, версіях заголовних файлів gl.h і glu.h, визначаються взаголовному файлі windows.h.
Якщо ви звертаєтесябезпосередньо до бібліотеки віконного інтерфейсу, яка забезпечує підтримкуOpenGL, наприклад, до бібліотеки GLX, AGL, PGL або WGL, то необхідно включитидодаткові заголовні файли. Наприклад, якщо ви викликаєте бібліотеку GLX, то,можливо, потрібно буде додати до вашого програмного коду рядки, приведені нижче:
#include
#include
У операційній системіMicrosoft Windows для підключення підпрограм WGL слід додати до вашогопрограмного коду наступний рядок:
#include
(і рядок
#include
якщо вам потрібні розширеніможливості OpenGL).
Якщо ви використовуєтебібліотеку GLUT для управління завданнями віконного менеджера, то необхіднобуде включити наступний рядок:
#include
Більшість OpenGL-програмтакож використовують системні виклики для стандартної бібліотеки мовипрограмування С, тому зазвичай слід включати заголовні файли, не пов'язані зобробкою графіки, такі як:
#include
#include
2.2.3 GLUT, інструментарійутиліт бібліотеки OpenGL
Інструментарій бібліотек
Як ви вже знаєте, бібліотекаOpenGL містить команди візуалізації, проте вона розроблялася так, щоб бутинезалежною від будь-якої конкретної віконної або операційної системи. Отже, цябібліотека не містить ніяких команд для відкриття вікон або зчитування подійвід клавіатури або миші. На жаль, неможливо написати закінчену графічнупрограму, не відкриваючи, принаймні, одне вікно, а найцікавіші програмивимагають певного об'єму обробки даних, що вводяться користувачем, або іншихпослуг від віконної або операційної системи. У багатьох випадках закінченіпрограми дають найцікавіші приклади, тому справжня програма використовуєбібліотеку GLUT для того, щоб спростити процедури відкриття вікон, виявленнявведення даних користувачем і так далі. Якщо на вашій системі є реалізаціябібліотеки OpenGL і інструментарію GLUT, то приклади повинні працювати без змінпри роботі з вашими бібліотеками OpenGL і GLUT.
Крім того, оскільки складкоманд малювання у бібліотеці OpenGL обмежений тільки командами, які генеруютьпрості геометричні примітиви (точки, лінії і багатокутники), бібліотека GLUTвключає декілька підпрограм, що створюють складніші тривимірні об'єкти, такі яксфера, тор і чайник. Таким чином, можна отримати для перегляду досить цікавікадри виведення програми. (Зверніть увагу на те, що бібліотека утиліт OpenGL,GLU, також має у своєму складі підпрограми побудови двовимірних поверхонь, якістворюють деякі тривимірні об'єкти, такі ж, як і ті, які створює інструментарійGLUT, у тому числі сферу, циліндр або конус.)
Інструментарій GLUT може бутине достатнім для повнофункціональних OpenGL-програм, але він може виявитисяхорошою відправною точкою для вивчення OpenGL. Інша частина розділу короткоописує невелику підмножину підпрограм бібліотеки GLUT так, щоб ви змоглирозібратися з прикладами програмування.
Управління вікнами
П'ять підпрограмінструментарію GLUT виконують завдання, необхідні для того, щоб ініціалізувативікно.
Підпрограма glutlnit(int*argc, char **argv) ініціалізує бібліотеку GLUT і опрацьовує будь-які аргументикомандного рядка (для оболонки X WindowSystem це могли б бути такі опції, як — display і — geometry). Підпрограма glutlnit() має бути викликана передбудь-якою іншою підпрограмою бібліотеки GLUT.
ПідпрограмаglutInitDisplayMode(unsigned int mode) визначає, яку колірну модель слідвикористовувати: режим RGBA або режим індексації кольору. Можна такожвизначити, чи хочете ви працювати з буфером кадру вікна з одинарною або зподвійною буферизацією. (Якщо ви працюєте в режимі індексації кольору, то ви,можливо, захочете завантажити деякі кольори в таблицю компонентів кольору; длятого, щоб зробити це, скористайтеся командою glutSetColor().) Нарешті, можнавикористовувати цю підпрограму для того, щоб вказати, що ви хочете зв'язати з цимвікном буфери глибини, трафарету і буфер-накопичувач. Наприклад, якщо ви хочетевикористовувати вікно з подвійною буферизацією, колірною моделлю RGBA і буферомглибини, то для цього можна викликати дану підпрограму з наступнимипараметрами: g\utlnitmsv\&yMote{GLUT_DOUBLE\ GLUT^RGB \ GLUTJ) EPTH).
ПідпрограмаglutInitWindowPosition(int х, int у) визначає місце розташування лівоговерхнього кута створюваного вікна на екрані монітора.
ПідпрограмаglutInitWindowSize(int width, int size) визначає розмір створюваного вікна впікселях.
Підпрограма intglutCreateWindow(char *string) створює вікно з контекстомOpenGL. Ця підпрограмаповертає унікальний ідентифікатор для нового вікна. Майте на увазі: до тихпір, поки викликається підпрограма glutMainLoopO, це вікно ще не відображаєтьсяна екрані.
Функція зворотного викликувідображення
ПідпрограмаgIutDisplayFunc(void(void)) є першою і найбільш важливою функцією зворотноговиклику по події, з якою належить зіткнутися. Всякий раз, коли бібліотека GLUTвизначає, що вміст цього вікна має бути відновлений, виконується функціязворотного виклику, зареєстрована підпрограмою glutDisplayFunc(). Тому виповинні помістити усі підпрограми, які потрібні для перемальовування сцени, вцю функцію зворотного виклику відображення.
Якщо ваша програма змінюєвміст вікна, то іноді ви повинні викликати підпрограму glutPostRedisplay(void),яка змушує підпрограму glutMainLoopO викликати зареєстровану функцію зворотноговиклику відображення при наступній слушній нагоді.
Виконання програми
Саме останнє, що ви повиннізробити, це викликати підпрограму glutMainLoop(void). При цьому відображаютьсяусі вікна, які були створені, і в цих вікнах тепер працює візуалізація.Починається обробка подій, і викликається зареєстрована функція зворотного викликувідображення. Увійшовши одного разу до цього циклу, з нього не виходять ніколи!
Для того, щоб зробитиефективність програми максимальної, усі операції, які повинні викликатисяодноразово (установка кольору фону і системи координат), тепер включені до складупроцедури, названої init(). Операції, необхідні для візуалізації (і, можливо,для повторної візуалізації) сцени, включені до складу процедури display(), якає зареєстрованою функцією зворотного виклику відображення бібліотеки GLUT.
Приклад 2. Проста програмаOpenGL, що використовує інструментарій GLUT: hello.c
#include
#include
void display(void)
/* Очистити усі пікселі */
glClear(GL_COLOR_BUFFER_BIT);
/* намалювати білийбагатокутник (прямокутник) з кутами,
розташованими в точках зкоординатами (0.25, 0.25, 0.0)
і (0.75, 0.75, 0.0) */
glColor3f(1.0, 1.0, 1.0);glBegin(GL_POLYGON);
glVertex3f(0.25, 0.25, 0.0);
glVertex3f(0.75, 0.25, 0.0);
glVertex3f(0.75, 0.75, 0.0);
glVertex3f(0.25, 0.75,0.0);glEnd() ;
/* He чекати! Запустити обробкутих, що буферизують
* підпрограм OpenGL*/
glFlushO; }
void init(void){
/* Вибрати колір очищення(колір фону) */
glClearColor (0.0, 0.0, 0.0,0.0);
/* Ініціалізувати значення,що переглядаються, */
glMatrixMode(GL_PROJECTION);
glLoadldentity();
glOrtho(0.0, 1.0, 0.0, 1.0, — 1.0, 1.0); }
/* Оголосити початковийрозмір вікна, його положення на екрані і режим відображення (одинарнабуферизація і режим RGBA).
Відкрити вікно із словом«hello» в рядку заголовка. Викликати підпрограми ініціалізації. Зареєструватифункцію зворотного виклику для відображення графіки. Увійти до основного циклуі обробляти події.*/
int main(int argc, char**argv){
glutInit(Sargc, argv);
glutInitDisplayMode(GLUT_SINGLE| GLUT_RGB);
glutInitWindowSize(250, 250);
glutInitWindowPosition(100,100);
glutCreateWindow(«hello»);
init();
glutDisplayFunc(display);
glutMainLoop();
return 0; /* Мовапрограмування С, згідно ISO, вимагає, щоб функція main повертала значення типуint. */ }
Обробка подій введення данихкористувачем
Для того, щоб зареєструватизворотний виклик команд, які викликаються у тому випадку, коли відбуваютьсявказані події, можна скористатися наступними підпрограмами.
ПідпрограмаglutReshapeFunc(void(int w, int h)) вказує на те, яка саме дія має бути виконанапри зміні розміру вікна.
ПідпрограмиglutKeyboardFunc(void(unsigned char key, int x, int у)) і glutMouseFunc(void(int button, int state, int x, int у)) дозволяють зв'язувати певну клавішуклавіатури або кнопку миші з підпрограмою, яка викликається, коли ця клавішаабо кнопка миші натискається або відпускається користувачем.
ПідпрограмаglutMotionFunc(void(int x, int у)) реєструє деяку підпрограму для зворотноговиклику при переміщенні миші з натиснутою кнопкою.
Управління фоновим процесом
Можна визначити деякуфункцію, яка має бути виконана за допомогою підпрограмиglutIdleFunc(void(void)) у тому випадку, якщо не очікуються ніякі інші події,наприклад, коли цикл обробки подій перейшов би в стан простою. Ця підпрограма вякості свого єдиного параметра приймає покажчик на цю функцію. Для того, щобвідключити виконання цієї функції, передайте їй значення NULL (нуль).
Малювання тривимірнихоб'єктів
Бібліотека GLUT включаєдекілька підпрограм для малювання перерахованих нижче тривимірних об'єктів:Конус, Ікосаедр, Чайник, Куб, Октаедр, Тетраедр, Додекаедр, Сфера, Тор.
Ви можете намалювати ціоб'єкти у вигляді каркасних моделей або у вигляді суцільних зафарбованихоб'єктів з певними нормалями до поверхонь. Наприклад, підпрограми для куба ісфери мають наступний синтаксис:
void glutWireCube(GLdoublesize);
void glutSolidCube(GLdoublesize);
void glutWireSphere(GLdoubleradius, GLint slices, GLint stacks);
void glutSolidSphere(GLdoubleradius, GLint slices, GLint stacks);
Усі ці моделі малюютьсяцентрованими відносно початку світової системи координат.
/>РОЗДІЛ 3. />Анімація комп'ютерної графіки на прикладімоделювання вогню
3.1 Анімація комп'ютерноїграфіки
Одна з найбільш захоплюючихречей, яку ви можете зробити в області комп'ютерної графіки, — це малюваннязображень, що рухаються. Незалежно від того, чи являєтеся ви інженером, щонамагається побачити усі сторони механічного вузла, що розробляється, пілотом,що вивчає з використанням моделювання процес пілотування літака, або ж простопристрасним любителем комп'ютерних ігор, очевидно, що анімація є важливоюскладовою частиною комп'ютерної графіки.
У кінотеатрі ілюзія рухудосягається за рахунок використання послідовності зображень і проектування їхна екран з частотою 24 кадри в секунду. Кожен кадр послідовно переміщається вположення позаду об'єктиву, затвор відкривається, і цей кадр відображається наекрані. Затвор на мить закривається, тоді як плівка простягається до наступногокадру, потім на екрані відображається цей наступний кадр, і так далі. Хочакожну секунду ви спостерігаєте на екрані 24 різні кадру, ваш мозок змішує усіці кадри в «безперервну» анімацію. (Старі фільми Чарлі Чаплина знімалисяз частотою 16 кадрів в секунду і при відтворенні фігури рухалися помітнимирізкими поштовхами.) Екран в комп'ютерній графіці зазвичай оновлюється(перемальовував зображення) приблизно від 60 до 76 разів в секунду, а інодіприкладні програми забезпечують навіть приблизно 120 оновлень в секунду.Очевидно, що анімація з частотою 60 кадрів в секунду виглядає«гладшими», ніж при частоті 30 кадрів в секунду, а 120 кадрів всекунду помітно краще, ніж 60 кадрів в секунду. Проте частоти регенерації, щоперевищують 120 кадрів в секунду, можуть бути за межами точки зменшенняповторної появи, залежно від меж сприйняття.
Головна причина того, щотехнологія проектування кінофільму працює, полягає в тому, що кожен кадр єзакінченим у момент його відображення на екрані. Припустимо, що ви намагаєтесязробити комп'ютерну анімацію зі свого кінофільму, що складається з одногомільйона кадрів, за допомогою програми, подібної до приведеного нижче фрагментапсевдокоду :
відкрити вікно();
for (i = 0; i
очистити вікно();
намалювати_кадр (i);
почекати_доки_не_закінчиться_інтервал_в_1_24__частку_секунди();)
Якщо ви додасте час, якийпотрібно вашій обчислювальній системі для того, щоб очистити екран і намалюватитиповий кадр, то приведена вище програма показує результати, що усе більштривожать, залежно від того, наскільки близько підходить час, потрібний їй дляочищення екрану і промальовування кадру до 1/ 24 частці секунди. Припустимо, щопроцедура малювання в цій програмі майже повністю займає 1/24 частку секунди.Елементи, намальовані на самому початку, видимі впродовж повної 1/24 часткисекунди і представляють суцільне зображення на екрані; елементи, намальовані укінці даного інтервалу, негайно очищаються, як тільки програма запускається длямалювання наступного кадру. Вони є у кращому разі деякою подібністю примарногозображення, оскільки велику частину інтервалу в 1/24 секунди ваше око розглядаєочищений фон замість тих елементів, які, до нещастя для них, були намальованіостанніми. Проблема в даному випадку полягає в тому, що приведена вище програмане відображає повністю намальовані кадри; замість цього ви спостерігаєте процесмалювання в його розвитку.
Більшість реалізаційбібліотеки OpenGL забезпечують подвійну буферизацію — апаратну або програмну,яка надає два готові буфери з кольоровими зображеннями. Зображення з одногобуфера відображається на екрані, тоді як в іншому буфері малюється новезображення. Коли малювання чергового кадру завершується, ці два буфериміняються місцями, і той буфер, що містив зображення, що відображалося, тепервикористовується для малювання, і навпаки. Це схоже на роботу кінопроектора,плівка в якому містить всього два кадри і склеєна в петлю; тоді як одинпроектується на екран, кіномеханік відчайдушно стирає і перемальовувавневидимий глядачеві кадр. Якщо кіномеханік працює досить швидко, то глядач непомічає відмінностей між таким «кінопроектором» і реальною системою,в якій усі кадри вже намальовані, і кінопроектор просто відображає їх один заіншим. При використанні подвійної буферизації кожен кадр відображається тількитоді, коли його малювання завершене; глядач ніколи не побачить частковонамальованого кадру.
Псевдокод зміненої версіїприведеної вище програми, яка відображає плавно анімовану графіку,використовуючи при цьому подвійну буферизацію, міг би виглядати таким чином:
відкрити_вікно_в_режимі_подвійної_буфериэації();for (i = 0; i
очистити_вікно();
намалювати_кадр(i);
поміняти_буфери_місцями(); }
3.2 Моделювання вогню
Крім того, частота оновленнявідеоінформації, що відображається, є постійною величиною, яка може мати деякінесподівані наслідки з точки зору продуктивності. Наприклад, при періодіоновлення інформації, що відображається на моніторі, рівної 1/60 часток секундиі при постійній швидкості передачі кадрів ви можете працювати зі швидкостями 60fps, 30 fps, 20 fps, 15 fps, 12 fps і т. д. (60/1, 60/2, 60/3, 60/4, 60/5, і т.д.). Це означає, що якщо ви пишете прикладну програму і поступово додаєте донеї нові функціональні можливості (припустимо, що ця програма — імітаторпольоту, і ви додаєте наземний пейзаж), то спочатку кожна нова деталь, щододається, не робитиме ніякого ефекту на сумарну продуктивність — ви все одноотримуєте швидкість передачі кадрів, рівну 60 fps. Потім, коли ви додаєте щеодну нову деталь, система вже не може намалювати усе це впродовж 1/60 часткисекунди, і анімація різко сповільнюється — з 60 fps до 30 fps, оскільки вонапропускає перший можливий момент зміни буферів. Аналогічна ситуаціявідбувається, коли час малювання одного кадру стає більше, ніж 1/30 часткасекунди — швидкість передачі кадрів анімації стрибком зменшується від 30 fps до20 fps.
В даному випадку програма длямоделювання горіння вогню була написана на основі системи часток. Ці часткимоделюють різні шари — «домени» іонізованого повітря і їх випадковийрух в просторі. В ході руху ці шари-частки світяться, поступово втрачаючияскравість. У цій програмі використовується лінійна інтерполяція загасанняяскравості шарів. Напрям і величина початкової швидкості вибирається випадковов деякому діапазоні. Так само випадково вибирається і так звана швидкістьгасіння частки — швидкість, з якою задана частка втрачає яскравість свогосвітіння. Вважається, що початкова величина яскравості частки дорівнює одиниці.Для імітування архімедівської сили, що піднімає шари повітря, використовується«антигравітація», тобто умовно задається середній напрям прискоренняруху. Для розрахунку руху часток використовується метод Ейлера в простомусвоєму варіанті. Цього вистачає, оскільки рух окремої частки в даному випадкуневажливий — нам необхідно створити випадковий розподіл руху часток длявідтворення хаотичної динаміки досліджуваного явища. Ну і нарешті не меншвізуально важливим параметром є колір вогню. Світловий спектр вогню можнавважати схожим із спектром Сонця. У програмі використовується лише чотирикольори з червоної області спектру по черзі змінюючі один-одного. Ось їхзначення в системі RGB: (255,128,128) (255,128,64) (255,161,102) (255,128,51).Проте кількість використовуваних кольорів нескладна істотно збільшити.
При запуску програми впам'яті комп'ютера створюється масив, що містить поточний стан кожної з часток.У нім також міститься така величина, як «прожите життя» частки. Прирусі окрім яскравості зменшується і життя частки. Коли спочатку рівна одиниціжиття обнуляється, частка відроджується в основі полум'я з новими параметрами.Таким чином кількість задіяних часток постійна (у цій програмі їх 2000), ачастки проживають усі нові і нові «життя». Як уже згадувалося, поведінкаполум'я цілком залежить від того з якими параметрами відроджуються частки. Осьці параметри: по-перше, початкове положення часток (x, y, z -координат, деz=const=3, а x і y вибираються згідно з розподілом, згідно з яким вірогідністьпояви частки в центральній частині (квадраті 1х1) квадрата 2х2 з центром в нулівтричі вище чим по околиці), далі початкові швидкості часток(x, y, z-координати вибираються випадково зі змінюваних інтервалів) і швидкість гасіннячастки (також в межах заданого інтервалу). Наступна діаграма ілюструє усевищесказане.
/>
Рис. 3.2 Циклічна схемапереміщення часток
Далі приводиться код самоїпрограми:
#include // Заголовочний файл Windows
#include
#include // Заголовочний файлвводу/виводу
#include // Заголовочний файлбібліотеки OpenGL32
#include // Заголовочний файлбібліотеки GLu32
#include // Заголовочний файлбібліотеки The Glaux
#defineMAX_PARTICLES1000
#define MAX_COLORS 4// Кількість кольорів полум’я
#define BOTTOM-3.0f
HDChDC=NULL;
HGLRChRC=NULL;
HWNDhWnd=NULL;
HINSTANCEhInstance;
boolkeys[256];
boolactive=TRUE;
boolfullscreen=FALSE;
boolrainbow=TRUE;
floatslowdown=6.0f;// Сповільнення часток
floatxspeed;
floatyspeed;
floatzoom=-20.0f;
GLuintloop;// Параметр циклу
GLuintcol;// Поточний колір
GLuintdelay;// Затримка ефекту веселки
GLuinttexture[1];// Пам’ять для текстури часток
GLfloatr;
typedef struct// Оголошення змінних
{
boolactive;
floatlife;
floatfade;
floatr;
floatg;
floatb;
floatx;
floaty;
floatz;
floatxi;
floatyi;
floatzi;
floatxg;
floatyg;
floatzg;
}
particles;// Структура часток
particles particle[MAX_PARTICLES];// Масив часток
static GLfloat colors[MAX_COLORS][4]=// Кольоривеселки
{
{1.0f,0.5f,0.5f},{1.0f,0.5f,0.24f},{1.0f,0.63f,0.4f},{1.0f,0.2f,0.5f}
};
LRESULTCALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
AUX_RGBImageRec *LoadBMP(char *Filename)//Завантаження Bitmap зображення
{
FILE *File=NULL;// Дескриптор файлу
if (!Filename)// Переконатися у наданні імені файлу
{
return NULL;
}
File=fopen(Filename,«r»);// Перевірити чиіснує файл
if (File)
{
fclose(File);
return auxDIBImageLoad(Filename)
}
return NULL; // Якщо завантаження не вдалося, топовертається NULL
}
int LoadGLTextures()
{
int Status=FALSE;// Індикатор стану
AUX_RGBImageRec *TextureImage[1];// Створити простірпам’яті длятекстур
memset(TextureImage,0,sizeof(void *)*1);// Встановитипокажчик на NULL
if(TextureImage[0]=LoadBMP(«Data/Particle.bmp»))// Завантажити текстури
{
Status=TRUE;glGenTextures(1, &texture[0]);//Створення однієї текстури
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3,TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, TextureImage[0]->data);
}
if (TextureImage[0])
{
if (TextureImage[0]->data) // Якщо текстури неіснує
{
free(TextureImage[0]->data); // Звільнити пам’ять
}
free(TextureImage[0]);
}
return Status;
}
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) //Перевизначити розмір вікна
{
if (height==0)
{
height=1;// Висота рівна одиниці
}
glViewport(0,0,width,height);// Перезавантажитипоточну область перегляду
glMatrixMode(GL_PROJECTION);// Вибір матриці проекту
glLoadIdentity();// Перезавантаження матриці проекту
// Обчислити коефіцієнт стискування вікна
gluPerspective(20.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int InitGL(GLvoid)// Налаштування OpenGL
{
if (!LoadGLTextures())
return FALSE;
srand((DWORD)GetTickCount);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f,0.0f,0.0f,0.0f);// Чорний фон
glClearDepth(1.0f);// Буфер глибини
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);// Змішування
glBlendFunc(GL_SRC_ALPHA,GL_ONE);// Тип змішування
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,texture[0]);// Вибіртекстури
for (loop=0;loop
{
particle[loop].active=TRUE;// Make All The ParticlesActive
particle[loop].life=1.0f;// Give All The ParticlesFull Life
particle[loop].fade=float(rand()%100)/100.0f+0.3f;
particle[loop].r=colors[loop*(MAX_COLORS/MAX_PARTICLES)][0];//Вибір червоного кольору
particle[loop].g=colors[loop*(MAX_COLORS/MAX_PARTICLES)][1];//Вибір червоного кольору
particle[loop].b=colors[loop*(MAX_COLORS/MAX_PARTICLES)][2];//Вибір червоного кольору
particle[loop].xi=float((rand()%50)-26.0f)*10.0f;//Випадкова Швидкість На Осі X
particle[loop].yi=float((rand()%100)-25.0f)*10.0f;//Випадкова Швидкість На Осі Y
particle[loop].zi=float((rand()%50)-25.0f)*10.0f;;//Випадкова Швидкість На Осі Z
particle[loop].xg=0.0f;particle[loop].yg=-0.08f;particle[loop].zg=0.0f;
particle[loop].y=BOTTOM;
}
return TRUE;// Ініціалізація
}
int DrawGLScene(GLvoid)// Малювання
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Очищення екрану і буфера глибини
glLoadIdentity();
for (loop=0;loop
{
if (particle[loop].active)// Якщо частки активні
{
float x=particle[loop].x;// Захопити позицію Xfloaty=particle[loop].y;// Захопити позицію Y
float z=particle[loop].z+zoom;// Захопити позицію Z
int coin;
glColor4f(particle[loop].r,particle[loop].g,particle[loop].b,particle[loop].life)
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); glVertex3f(x+0.5f,y+0.5f,z);
glTexCoord2d(0,1); glVertex3f(x-0.5f,y+0.5f,z);
glTexCoord2d(1,0); glVertex3f(x+0.5f,y-0.5f,z);
glTexCoord2d(0,0); glVertex3f(x-0.5f,y-0.5f,z);
glEnd();
particle[loop].x+=particle[loop].xi/(slowdown*1000);
particle[loop].y+=particle[loop].yi/(slowdown*1000);
particle[loop].z+=particle[loop].zi/(slowdown*1000);
particle[loop].xi+=particle[loop].xg;
particle[loop].yi+=particle[loop].yg;
particle[loop].zi+=particle[loop].zg;
particle[loop].life-=particle[loop].fade;// Скороченнятерміну життя часток
if (particle[loop].life
{
particle[loop].life=1.0f;// Дати нове життя
particle[loop].fade=float(rand()%100)/1000.0f+0.01f;// Випадкове значення
particle[loop].y=BOTTOM;
coin=rand();
if (coin
else
if (coin
else particle[loop].x=2*float(rand())/(RAND_MAX)-1.0f;
coin=rand();
if (coin
else
if (coin
else particle[loop].z=2*float(rand())/(RAND_MAX)-1.0f;
particle[loop].xi=xspeed+float((rand()%60)-32.0f);
particle[loop].yi=yspeed+float((rand()%700)-200.0f);
particle[loop].zi=float((rand()%60)-30.0f);
col=rand()*(MAX_COLORS+1)/RAND_MAX;
if (col>3) col=0;
particle[loop].r=colors[col][0];// Вибір червоногокольору
particle[loop].g=colors[col][1];// Вибір зеленогокольору
particle[loop].b=colors[col][2];// Вибір синьогокольору
}
if (keys[VK_NUMPAD8] &&(particle[loop].yg
if (keys[VK_NUMPAD2] &&(particle[loop].yg>-1.5f)) particle[loop].yg-=0.01f;
if (keys[VK_NUMPAD6] &&(particle[loop].xg
if (keys[VK_NUMPAD4] &&(particle[loop].xg>-1.5f)) particle[loop].xg-=0.01f;
}
}
return TRUE;
}
GLvoid KillGLWindow(GLvoid)
{
if (fullscreen)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);// Відображення курсора
}
if (hRC)
{
if (!wglMakeCurrent(NULL,NULL)){
MessageBox(NULL,«Release Of DC And RCFailed.»,«SHUTDOWN ERROR»,MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC))
{
MessageBox(NULL,«Release Rendering ContextFailed.»,«SHUTDOWN ERROR»,MB_OK | MB_ICONINFORMATION);
}
hRC=NULL;
}
if (hDC && !ReleaseDC(hWnd,hDC))
{
MessageBox(NULL,«Release Device ContextFailed.»,«SHUTDOWN ERROR»,MB_OK | MB_ICONINFORMATION);
hDC=NULL;
}
if (hWnd && !DestroyWindow(hWnd))// Ми млжемознищити вікно?
{
MessageBox(NULL,«Could Not ReleasehWnd.»,«SHUTDOWN ERROR»,MB_OK | MB_ICONINFORMATION);
hWnd=NULL;// Set hWnd To NULL
}
if (!UnregisterClass(«OpenGL»,hInstance))//Ми можемо не зареєструвати клас
{
MessageBox(NULL,«Could Not UnregisterClass.»,«SHUTDOWN ERROR»,MB_OK | MB_ICONINFORMATION);
hInstance=NULL;// Set hInstance To NULL
}
}
/*Наступний код створює вікно OpenGL:
*title- заголовок вікна
* width- довжина вікна
*height- висота вікна
*bits- кількість бітів для відображення кольору(8/16/24/32)
*fullscreenflag- використання повноекранного режиму*/
BOOL CreateGLWindow(char* title, int width, intheight, int bits, bool fullscreenflag)
{
GLuintPixelFormat;// Уртимання результату після пошукувідповідності
WNDCLASSwc;// Клас структури вікна
DWORDdwExStyle;// Розширений Стиль вікна
DWORDdwStyle;// Стиль вікна
RECTWindowRect;
WindowRect.left=(long)0;
WindowRect.right=(long)width;
WindowRect.top=(long)0;
WindowRect.bottom=(long)height;
fullscreen=fullscreenflag;// Повноекранний режим
hInstance= GetModuleHandle(NULL);
wc.style= CS_HREDRAW | CS_VREDRAW | CS_OWNDC; //Перемалювання вікна
wc.lpfnWndProc= (WNDPROC) WndProc;
wc.cbClsExtra= 0;// Жодних додаткових вікон
wc.cbWndExtra= 0;// Жодних додаткових вікон
wc.hInstance= hInstance;// Встановтти зразок
wc.hIcon= LoadIcon(NULL, IDI_WINLOGO); // Завантаженнястандартного значка
wc.hCursor= LoadCursor(NULL, IDC_ARROW); //Завантаження координит курсора
wc.hbrBackground= NULL;wc.lpszMenuName=NULL;wc.lpszClassName= «OpenGL»;// Вказання ім’я класу
if (!RegisterClass(&wc))// Зареєструвати класвікна
{
MessageBox(NULL,«Failed To Register The WindowClass.»,«ERROR»,MB_OK|MB_ICONEXCLAMATION);
return FALSE;}
if (fullscreen)
{
DEVMODE dmScreenSettings;// Режим пристрою
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));//Перевірка очищення пам’яті
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth= width;// Довжина вікна
dmScreenSettings.dmPelsHeight= height;// Висота вікна
dmScreenSettings.dmBitsPerPel= bits;// Кількість бітів
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// При збої
if (MessageBox(NULL,«The Requested FullscreenMode Is Not Supported By\nYour Video Card. Use Windowed ModeInstead?»,«NeHe GL»,MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE;// Присвоїти повноекранному режимузначення = FALSE
}
else
{
// Виштовхнути дані зі стека.
MessageBox(NULL,«Program Will NowClose.»,«ERROR»,MB_OK|MB_ICONSTOP);
return FALSE;
}
}
}
if (fullscreen)
{
dwExStyle=WS_EX_APPWINDOW;dwStyle=WS_POPUP;ShowCursor(FALSE);}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle=WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE,dwExStyle);
// Створення вікна
if(!(hWnd=CreateWindowEx(dwExStyle,«OpenGL»,// Ім’я класу
title,// Заголовок вікна
dwStyle |// Певний стиль вікна
WS_CLIPSIBLINGS |// Необхідний стиль вікна
WS_CLIPCHILDREN,// Необхідний стиль вікна
0, 0,// Позиція вікна
WindowRect.right-WindowRect.left,// Розрахунок довжини
WindowRect.bottom-WindowRect.top,// Розрахунок висоти
NULL,
NULL,// Без меню
hInstance,// Зразок
NULL)))// Не передавати нічого для WM_CREATE
{
KillGLWindow();// Оновлення екрану
MessageBox(NULL,«Window CreationError.»,«ERROR»,MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
staticPIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR), // Розмір пікселів
1,// Номер версії
PFD_DRAW_TO_WINDOW |// Вікно повинно підтримуватиформат
PFD_SUPPORT_OPENGL |// OpenGL повинен підтримуватиформат
PFD_DOUBLEBUFFER,// Підтримка буферу
PFD_TYPE_RGBA,// Підтримка формату RGBA
bits,// Глибина кольору
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,// 16-бітний Z-буфер
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0// Проігнорувати маски слою
};
if (!(hDC=GetDC(hWnd)))
{
KillGLWindow();// Оновлення екрану
MessageBox(NULL,«Can't Create A GL DeviceContext.»,«ERROR»,MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
{
KillGLWindow();// Оновлення екрану
MessageBox(NULL,«Can't Find A SuitablePixelFormat.»,«ERROR»,MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd))
{
KillGLWindow();// Оновлення екрану
MessageBox(NULL,«Can't Set ThePixelFormat.»,«ERROR»,MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if (!(hRC=wglCreateContext(hDC)))
{
KillGLWindow();// Оновлення екрану
MessageBox(NULL,«Can't Create A GL RenderingContext.»,«ERROR»,MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if(!wglMakeCurrent(hDC,hRC))
{
KillGLWindow();// Оновлення екрану
MessageBox(NULL,«Can't Activate The GL RenderingContext.»,«ERROR»,MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
ShowWindow(hWnd,SW_SHOW);// Показ вікна
SetForegroundWindow(hWnd);
SetFocus(hWnd);
ReSizeGLScene(width, height);
if (!InitGL())// Ініціалізація вікна
{
KillGLWindow();// Оновлення екрану
MessageBox(NULL,«InitializationFailed.»,«ERROR»,MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
return TRUE;
}
LRESULT CALLBACK WndProc(HWNDhWnd,// обробка вікна
UINTuMsg, // Повідлмлення вікна
WPARAMwParam,LPARAMlParam){
switch (uMsg)// Перевірка повідомлень
{
case WM_ACTIVATE:// Спостерігати за повідомленнями
{
if (!HIWORD(wParam))
{
active=TRUE;// Програма активна
}
else// Або
{
active=FALSE;// Програма більше не активна
}
return 0;// Повернення до циклу повідомлень
}
case WM_SYSCOMMAND:// Перевірка системних команд
{
switch (wParam)// Перевірка системних викликів
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}
break;// Вихід
}
case WM_CLOSE:// Чи отримали повідомлення?
{
PostQuitMessage(0);// Відправити повідомлення
return 0;
}
case WM_KEYDOWN: // Чи натиснена клавіша?
{
keys[wParam] = TRUE;
return 0;
}
case WM_KEYUP:// Чи клавіша відпущена?
{
keys[wParam] = FALSE;
return 0;
}
case WM_SIZE:// Зміна розміра вікна OpenGL
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); //LoWord=Width, HiWord=Height
return 0;
}
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int WINAPI WinMain(HINSTANCEhInstance, // Зразок
HINSTANCEhPrevInstance,// Попередній Instance
LPSTRlpCmdLine, // Командний рядок Parameters
intnCmdShow) // Вікно стану
{
MSGmsg;// Структури повідомлень вікна
BOOLdone=FALSE;// Вихід з циклу
// Створення вікна OpenGL
if (!CreateGLWindow(«Fire Simulation Based OnParticles»,640,480,16,fullscreen))
{
return 0;// Вихід, якщо вікно не вдалося створити
}
while(!done)// Цикл працює поки=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))//
{
if (msg.message==WM_QUIT) // Чи є нові повідомлення?
{
done=TRUE;
}
else
{
TranslateMessage(&msg);// Перекласти повідомлення
DispatchMessage(&msg);// Відіслати повідомлення
}
}
else// Немає повідомлень
{
// Малювання сцени DrawGLScene()
if ((active && !DrawGLScene()) ||keys[VK_ESCAPE]){
done=TRUE;// ESC для виходу
}
else
{
SwapBuffers(hDC);// Зміна буфера
if (keys[VK_ADD] && (slowdown>0.0f))slowdown-=0.1f;// Швидкість руху часток вверх
if (keys[VK_SUBTRACT] && (slowdown
if (keys[VK_PRIOR])zoom+=0.1f;// Приближення
if (keys[VK_NEXT])zoom-=0.1f;// Віддалення
if (keys[VK_UP] && (yspeed
if (keys[VK_DOWN] && (yspeed>-2000))yspeed-=1.0f;
if (keys[VK_RIGHT] && (xspeed
if (keys[VK_LEFT] && (xspeed>-2000))xspeed-=1.0f;
delay++; // Збільшити кольри
if (keys[VK_F1])// Якщо натиснено F1?
{
keys[VK_F1]=FALSE;
KillGLWindow();// Знащити поточне вікно
fullscreen=!fullscreen;// Відновлення вікна
if (!CreateGLWindow(«Fire Simulation Based OnParticles»,1024,768,16,fullscreen))
{
return 0;// Quit If Window Was Not Created
}
}
}
}
}
// Вимикання
KillGLWindow();// Знищення вікна
return (msg.wParam);// Вихід з програми
}
Таким чином, ґрунтуючись нанескладній моделі поведінки вогню, мені вдалося ефективно реалізуватиреалістичну імітацію оптичних процесів що виникають при горінні в повітрянійатмосфері.
/>ВИСНОВКИ
В процесі написання курсової роботи була розглянутаграфічна бібліотека OpenGL з метою використання її в комп'ютерному моделюванні.Був розглянутий синтаксис команд та програмний код команд, а також бібліотеки,що відносяться до OpenGL.
Основним завданням цієї курсової роботи буломаксимально реалістично змоделювання горіння вогню.
Для вирішення завдання була написана програма на мовіС з використанням технології OpenGL. Вона реалізує поставлене завдання наоснові системи часток. Це найбільш простий і ефективний підхід, що показуєнепоганий результат і високу продуктивність, не накладаючи високі вимоги на відеоадаптер.
/>ЛІТЕРАТУРА
1. Эйнджел Э. Интерактивнаякомпьютерная графика. Вводний курс на базе OpenGL / Э. Эйнджел. 2001. – 590 с.
2. Тихомиров Ю.Программирование трехмерной графики. Серия '' Мастер''. – СПб.:BHV-Санкт-Петербург. 2000. – 256 с.
3. Майер Р. В. Компьютерноемоделирование физических явлений / Р. В. Майер. – Глазов: ГГПИ, 2009. – 111 с.
4. Мейсон Ву. OpenGL.Официальное руководство программиста / Ву Мейсон, Нейдер Д., Девис Т., ШрайнерД. 2002. – 592 с.
5. Роджерс Д. Алгоритмическиеосновы машинной графики / Д. Роджерс. М.: Мир. 1989. – 512 с.