Hlavní navigace

GLUT (3): práce s okny

13. 5. 2003
Doba čtení: 7 minut

Sdílet

V tomto dílu si ukážeme postup, jakým lze pomocí funkcí z knihovny GLUT vytvořit okno, do kterého lze vykreslovat pomocí příkazů OpenGL. Také si ukážeme, jak lze v jednom okně vytvořit více tzv. suboken nebo jedno okno zvětšit přes celou plochu desktopu (režim full-screen).

Práce s okny

Před jakoukoliv prací s knihovnou OpenGL je zapotřebí otevřít okno a přiřadit mu takzvaný grafický kontext OpenGL. Do tohoto okna se bude provádět vykreslování (rendering). Vlastní otevření okna je operace systémově závislá, proto bylo v knihovně GLUT pro tuto činnost vytvořeno několik funkcí. Tyto funkce jsou značně podobné funkcím z knihovny aux, jíž se autoři GLUTu zjevně inspirovali. V aplikaci používající knihovnu GLUT se nejprve musí tato knihovna inicializovat a teprve poté je možné volat další funkce starající se například o otevření oken či o jejich překreslování na žádost uživatele nebo operačního systému.

Inicializaci knihovny GLUT provádí funkce glutInit(int *argcp, char **argv) která má dva argumenty. První argument argcp představuje ukazatel na proměnnou obsahující počet parametrů programu, druhý argument argv je pole řetězců reprezentujících jednotlivé parametry. Knihovna GLUT může při inicializaci přečíst a zpracovat některé parametry, které jí náleží. Tyto parametry jsou následně odstraněny z pole řetězců parametrů (takže programátor aplikace se o tyto parametry nemusí starat, pokud provádí zpracování parametrů až za funkcí glutInit()) a je také náležitě upravena proměnná obsahující počet těchto parametrů. To je důvod, proč je počet parametrů předáván do funkce glutInit() odkazem (přes ukazatel). Pokud je funkce main volána s parametry argc a argv, potom volání funkce glutInit() vypadá následovně: glutInit(&argc, argv);.

Po inicializaci knihovny GLUT lze již vytvořit okna, k čemuž se používá funkce glutCreateWin­dow(char *name). Tato funkce má jediný argument name představující řetězec zobrazený v titulkovém pruhu okna. Konkrétní způsob zobrazení okna resp. jeho titulkového pruhu záleží na použitém operačním systému a aktivním okenním manažeru. Před vytvořením okna lze také manažeru oken zadat doporučenou velikost okna a jeho umístění. Počáteční velikost okna se nastavuje funkcí glutInitWindow­Size(int width, int height) a umístění (pozice na desktopu) funkcí glutInitWindow­Position(int x, int y). Je zapotřebí si uvědomit, že vytvořené okno se nezobrazí ihned, ale až za běhu hlavní smyčky programu spuštěné příkazem glutMainLoop(void) (viz další odstavce).

Registrace základních callback funkcí, spuštění hlavní smyčky programu

V typické aplikaci je před spuštěním hlavní smyčky programu nutné zaregistrovat takzvané callback funkce volané při změně velikosti okna a při požadavku na překreslení okna. Registraci funkce volané při změně velikosti okna provádí funkce glutReshapeFun­c(void (func)(int width, int height)), jež má jako argument ukazatel na programátorem vytvořenou callback funkci func se dvěma parametry width, height typu int, v nichž bude uložena nová velikost okna. Registraci funkce volané při požadavku na překreslení provádí funkce glutDisplayFun­c(void (func)(void)), která má jako jediný argument ukazatel na programátorem vytvořenou callback funkci, jež nemá žádné parametry.

Po registraci těchto callback funkcí je možné spustit hlavní smyčku programu, kterou nastavuje volání funkce glutMainLoop(void). Jedná se o nekonečnou smyčku, ve které program získává zprávy od uživatele i od operačního systému a reaguje na ně voláním různých callback funkcí. Vlastní podoba smyčky je před programátorem skryta, protože se jedná o systémově závislou činnost. Jedinou věc, kterou může programátor aplikace změnit, je posloupnost příkazů uvedená v callback funkcích. Z této nekonečné smyčky lze vyskočit například voláním knihovní funkce jazyka C exit(int). Není zapotřebí uzavírat okna ani provádět jiné ukončovací akce.

Ukázkový příklad číslo 1

Následuje ukázkový příklad číslo 1, kde je předvedena základní kostra aplikace, která využívá grafickou knihovnu OpenGL a GLUT. Tento program otevře jedno okno, které je při každém překreslení vybarveno černou barvou. Jelikož není explicitně naprogramována žádná akce, která by vedla k zastavení programu, je možné aplikaci zastavit pouze uzavřením okna (nebo příkazem kill u operačních systémů typu Unix). K dispozici je zdrojový kód prvního příkladu a zdrojový kód se zvýrazněnou syntaxí (HTML stránka).

Kompilaci lze v Linuxu provést takto:
gcc -o glut03_1 -L/usr/X11R6/lib glut03_1c.c -lglut -lGL -lGLU -lm -lX11 -lXmu
a na Windows s MinGW takto:
gcc -o glut03_1.exe glut03_1c.c -I lib -l opengl32 -l glut32 -mwindows

ukázka prvního příkladu

Vytvoření a otevření více oken současně

U některých aplikací může být výhodné mít v určitém čase otevřeno více oken současně. V knihovně GLUT je možné otevřít libovolné množství oken (konkrétní maximální počet závisí na operačním systému), z nichž každé může být obsluhováno jinými callback funkcemi. Tato okna se tedy z hlediska programátora aplikace chovají samostatně. Jak již bylo zmíněno v předchozí části, není možno pomocí GLUTu vytvořit modální okna (modální okna se používají například u dialogů, které nutí uživatele nejprve dialog vyplnit a až poté pokračovat v další práci s aplikací).

Otevření více oken lze provést například následující sekvencí funkcí: glutInitWindow­Position(), glutInitWindow­Size(), glutCreateWindow, glutSetWindow(), glutDisplayFunc() a glutReshapeFunc().

Funkce glutCreateWin­dow(char *name) vrací hodnotu typu int, která v běžící aplikaci jednoznačně identifikuje otevřené okno. Funkcí glutSetWindow(int win) můžeme libovolné okno nastavit jako aktuální. Veškerá další registrace callback funkcí se bude provádět s aktuálním oknem. Při běhu aplikace můžeme funkcí glutGetWindow(void) zjistit, pro které okno je volána některá callback funkce. Toho se využívá zejména v případech, že je pro více oken zaregistrována pouze jedna společná callback funkce.

Ukázkový příklad číslo 2

Následuje ukázkový příklad číslo 2, který demonstruje možnost vytvoření více oken současně. Okna jsou zobrazena vedle sebe, přičemž je každé okno vybarveno jinou barvou. Toho je dosaženo tak, že se pro všechna okna volá jedna společná callback funkce onDisplay(void), v níž se voláním funkce glutGetWindow(void) zjistí, které okno se má překreslit. Podle čísla okna se následně nastaví barva pro překreslení daného okna. K dispozici je zdrojový kód druhého příkladu a zdrojový kód se zvýrazněnou syntaxí.

ukázka druhého příkladu

Práce s podokny (subokny)

Termínem subokno se v knihovně GLUT rozumí obdelníková část běžného okna, která se z hlediska OpenGL chová samostatně. Příkladem může být vykreslování objektů, které jsou vždy ořezány na velikost svého subokna. Subokna nejsou sama o sobě viditelná, neobsahují tedy například titulkový pruh nebo scrollbary. Pomocí suboken lze realizovat například pohled na jedno těleso z více směrů – typicky se plocha hlavního okna rozdělí na čtyři subokna, ve kterých je postupně zobrazován nárys, půdorys, bokorys a perspektivní pohled na těleso či celou scénu.

Subokna lze vytvářet až po vytvoření běžného okna. Potom lze volat funkci glutCreateSub­Window(int win, int x, int y, int width, int height), která má pět argumentů. První argument win představuje identifikátor okna, ve kterém má být subokno vytvořeno. Další čtyři argumenty specifikují polohu (x, y) a rozměr (width, height) obdélníka představujícího subokno. Všechny rozměry jsou zadány v pixelech. Pro každé subokno lze volat jinou funkci starající se o překreslení.

Ukázkový příklad číslo 3

V ukázkovém příkladu číslo 3 je předveden způsob vytvoření několika suboken. Hlavní okno i subokna používají stejnou callback funkci onDisplay(), proto je nutné rozlišit, pro které okno resp. subokno je tato funkce volána. Používáme proto již známou funkci glutGetWindow(). Po spuštění aplikace je každé subokno vybarveno jinou barvou, aby byla demonstrována ta skutečnost, že se subokna skutečně ovládají nezávisle na sobě (funkce glClear() vždy vymaže celý buffer příslušející danému oknu). K dispozici je zdrojový kód třetího příkladu a zdrojový kód se zvýrazněnou syntaxí..

ukázka třetího příkladu

Přepnutí do režimu plné obrazovky

Knihovna GLUT nabízí aplikacím i takzvaný režim plné obrazovky (Full Screen). Aplikaci lze nastavit tak, že jedno z jejích oken (resp. pouze uživatelská oblast okna) je zobrazeno přes celou obrazovku tak, aby zabralo co největší plochu desktopu. Pokud to použitý operační systém a správce oken umožňuje, je okno zobrazeno bez titulkového pruhu a dalších ovládacích prvků, jako jsou například okraje okna a skrolovací lišty. Tento režim se většinou používá v případě, že aplikace obsluhuje pouze jedno okno nebo skupinu podoken. Použití více oken se v režimu Full Screen nedoporučuje, protože to může být pro uživatele aplikace matoucí.

Ukázkový příklad číslo 4

V tomto ukázkovém příkladu je demonstrována možnost přepnutí do režimu Full Screen. Po spuštění aplikace se lze klávesou [f] nebo [F] přepnout do režimu plné obrazovky. Stisknutím klávesy [w] nebo [W] se okno zmenší na původní velikost. Za zmínku stojí kód volaný pro zmenšení okna. Používá se sekvence příkazů glutReshapeWin­dow(int width, int height)a glutPositionWin­dow(int x, int y). Tyto příkazy zajistí jak zmenšení okna, tak i jeho posun do pracovní části obrazovky. Pokud by se nevolala funkce glutPositionWin­dow(), mohlo by se stát, že by okno mohlo být zobrazeno na okraji obrazovky a uživateli by nebyl umožněn přístup k jeho ovládacím prvkům. K dispozici je zdrojový kód čtvrtého příkladu a zdrojový kód se zvýrazněnou syntaxí.

UX DAy - tip 2

ukázka třetího příkladu

V dalším pokračování tohoto seriálu si povíme o zpracování zpráv od systému a o obsluze vstupních zařízení.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.