OpenGL a nadstavbová knihovna GLU (3)

10. 8. 2004
Doba čtení: 7 minut

Sdílet

Ve třetí části seriálu o grafické knihovně GLU se budeme zabývat funkcemi, pomocí nichž je možné nastavit pozici a orientaci kamery (pozorovatele) v trojrozměrné scéně. Také si popíšeme funkce používané pro nastavení ortogonálního pohledu při zobrazování plošných dat v rovině.

Obsah

1. Funkce pro zjednodušené nastavení kamery ve scéně
2. Jednoduché nastavení ortogonálního pohledu v rovině
3. Nastavení pozice kamery a směru jejího pohledu
4. Lokální souřadný systém kamery a jeho význam
5. Demonstrační příklady
6. Obsah dalšího pokračování
7. Seznam funkcí OpenGL a GLUT zmíněných v této části
8. Nové funkce z knihovny GLU popsané v této části
9. Zkomprimovaná verze článku i s přílohami
 

1. Funkce pro zjednodušené nastavení kamery ve scéně

Mezi základní příkazy, které musí každý programátor při vykreslování trojrozměrné scény s využitím prakticky všech grafických knihoven používat, patří příkazy pro nastavení kamery. Kamera (někdy se též nazývá pozorovatel) je specifikovaná svou pozicí v prostoru, směrem pohledu, natočením a zorným úhlem.

Z těchto hodnot je interně získán lokální souřadný systém kamery, který je představován trojicí vzájemně kolmých vektorů up, front a left – viz první ilustrační obrázek:

Obrázek 1: lokální souřadný systém kamery
Obrázek 1: lokální souřadný systém kamery

Nastavení kamery (pozorovatele) se však pomocí funkcí z knihovny OpenGL nedá provést přímo – jedinou možností je změna prvků transformační matice Projection a ModelView, což sice může vypadat jako zbytečně složité a omezující, na druhou stranu se však tímto způsobem zabrání vzniku mnoha chyb, protože programátor z kontextu programu vždy přesně ví (nebo by alespoň měl vědět), kterou transformační matici nastavuje.

V základní knihovně OpenGL existují pro zjednodušené nastavení kamery pouhopouhé dvě funkce: glOrtho() a glFrustum(). Tyto funkce sice již známe z předchozích seriálů, ale pro připomenutí v dalším textu uvedu jejich hlavičky a stručný popis.

Hlavička funkce glOrtho() vypadá následovně:

void glOrtho(
    GLdouble left,
    GLdouble right,
    GLdouble bottom,
    GLdouble top,
    GLdouble near,
    GLdouble far
);

Pomocí výše zmíněné funkce glOrtho() se provádí nastavení takzvaného ortogonálního pohledu, tj. takové projekce, u které není zkreslována velikost objektů se vzrůstající vzdáleností od kamery. Využití této funkce je možné zejména v technických aplikacích a v „izometrických“ hrách – simulátorech, tzv. 2.5D strategiích apod.

Funkce glOrtho() nastavuje v nekonečném trojrozměrném prostoru kvádr, který je promítán na obrazovku. Veškeré body, které se nachází vně tohoto kvádru, jsou z dalšího zpracování v grafickém vykreslovacím řetězci odstraněny a nejsou proto vykresleny. Vztah parametrů funkce glOrtho()a velikosti kvádru je patrný z druhého ilustračního obrázku:

Obrázek 2: význam parametrů funkce glOrtho()
Obrázek 2: význam parametrů funkce glOrtho()

Hlavička funkce glFrustum() vypadá následovně

void glFrustum(
    GLdouble left,
    GLdouble right,
    GLdouble bottom,
    GLdouble top,
    GLdouble zNear,
    GLdouble zFar
);

Pomocí funkce glFrustum() je možné provést nastavení takzvaného perspektivního pohledu, tj. projekce, při jejímž použití se zdánlivá velikost objektů na obrazovce zmenšuje s jejich rostoucí vzdáleností od kamery. Tento typ pohledu je vhodné použít téměř ve všech grafických scénách s výjimkou výše zmíněných situací (hry apod.). Pro korektně zobrazenou scénu však velmi záleží na správném nastavení perspektivy, jejíž míra by měla alespoň zhruba odpovídat optickým vlastnostem lidského oka.

Obrázek 3: význam parametrů funkce glFrustum()
Obrázek 3: význam parametrů funkce glFrustum()

V grafické knihovně OpenGL však dále neexistují žádné další funkce, pomocí nichž by bylo možné kamerou ve scéně posouvat a natáčet ji. Pro tyto účely se používají základní funkce pro manipulaci s transformačními maticemi:glTran­slatef(), glRotatef() a glScalef().

Všechny výše zmíněné funkce, tj. glOrtho(), glFrustum(), glTranslatef(), glRotatef() a glScalef(), jsou však pro běžné použití značně nevhodné, protože jejich parametry vychází pouze z interních potřeb knihovny OpenGL a grafických akcelerátorů, přičemž nemají v reálném světě obdobu – programátor si ve většině případů pod zadávanými čísly nic konkrétního nepředstavuje, nebo má pouze mlhavou představu o konkrétním dopadu jednotlivých parametrů na vykreslovanou­ scénu.

Proto byly do nadstavbové knihovny GLU zahrnuty funkce, které umožňují práci s kamerou přirozeným způsobem. Tyto funkce budou postupně popsány v následujících odstavcích.

2. Jednoduché nastavení ortogonálního pohledu v rovině

První a patrně nejjednodušší funkcí pro práci s kamerou je funkce pro nastavení ortogonálního pohledu v rovině. Při nastavení ortogonálního pohledu se používá taková projekce, u níž nedochází ke zmenšování zobrazovaných objektů vlivem jejich vzdálenosti od kamery, přičemž se kamera většinou dívá ze Z-ové osy do roviny X-Y.

Pro nastavení ortogonálního pohledu existuje i v základním OpenGL funkce, která se nazývá glOrtho() – viz předchozí odstavec. Pomocí této funkce se nastaví transformační matice Projection tak, že všechna vykreslovaná grafická primitiva jsou ořezána podle šesti ořezávacích rovin. Tyto ořezávací roviny jsou paralelní s osami souřadného systému, vykreslovaný prostor je tedy tvořen osově orientovaným kvádrem (viewing volume). Všechny vrcholy, jež leží mimo tento kvádr, jsou z dalšího zpracování v grafickém vykreslovacím řetězci odstraněny.

Na funkci glOrtho() není nic špatného, pouze po programátorovi vyžaduje specifikaci přední a zadní ořezávací roviny – existuje zde tedy možnost vzniku chyb ze strany programátora. Při práci v ploše (rovině) X-Y však tyto informace nejsou důležité, proto byla do knihovny GLU zahrnuta jednodušší funkce gluOrtho2D(), která má následující hlavičku:

void gluOrtho2D(
    GLdouble left,
    GLdouble right,
    GLdouble bottom,
    GLdouble top
);

Zavolání této funkce má stejný význam jako volání funkce glOrtho(), s tím, že parametr near je nastaven na hodnotu –1 a parametr far na hodnotu +1. Tato funkce je tedy velmi jednoduše použitelná při specifikaci rozsahu souřadnic plochy, jež se má zobrazit v okně aplikace bez nutnosti korektního nastavení přední a zadní ořezávací roviny. Význam parametrů funkce gluOrtho2D() je patrný ze čtvrtého obrázku.

Obrázek 4: význam parametrů funkce gluOrtho2D()
Obrázek 4: význam parametrů funkce gluOrtho2D()

3. Nastavení pozice kamery a směru jejího pohledu

Nastavení pozice a orientace kamery pomocí funkcí glTranslatef(),glRo­tatef() a glScalef() je poměrně složité a ne vždy vede ke správným výsledkům – i zkušeným programátorům se stane, že se kamera „dívá“ do volného prostoru mimo scénu, nebo že je umístěna pod podlahou. Proto je v nadstavbové knihovně GLU implementována funkce gluLookAt(), pomocí níž je možné kameru velmi jednoduše umístit do libovolné pozice v prostoru, orientovat kameru určitým směrem a natočit ji okolo osy objektivu.

Funkce gluLookAt() má následující hlavičku:

void gluLookAt(
    GLdouble eyeX,
    GLdouble eyeY,
    GLdouble eyeZ,
    GLdouble centerX,
    GLdouble centerY,
    GLdouble centerZ,
    GLdouble upX,
    GLdouble upY,
    GLdouble upZ
);

ve které mají jednotlivé parametry následující význam:

  • Pomocí parametrů eyeX, eyeY, eyeZ se specifikují souřadnice v prostoru, na kterých se kamera nachází.
  • Parametry centerX, centerY a centerZ specifikují souřadnice bodu, na který se kamera dívá. Vzhledem k tomu, že je vypočítán vektor z pozice kamery do zde zadaného bodu, nesmí být tyto body (tj. eye=[eyeX, eyeY, eyeZ] a center=[centerX, centerY, centerZ]). totožné.
  • Parametry upX, upY a upZ specifikují vektor směřující „nahoru“ do stropu (na vykreslované scéně vertikální směr). Tento vektor nesmí být rovnoběžný s vektorem vytvořeným ze souřadnice pozice kamery a bodu pohledu, jinak by pomocí těchto tří vektorů nebylo možné jednoznačně vytvořit lokální souřadný systém kamery.

Vzhledem k tomu, že se při zavolání funkce gluLookAt() vytvoří pomocná transformační matice, která se vynásobí se stávající transformační maticí, musí se prakticky ve všech aplikacích před nastavením kamery zavolat funkce glLoadIdentity(), pomocí níž se do příslušné transformační matice Projection nebo ModelView nahraje jednotková matice (identita). Tento postup je ukázán i u uvedených demonstračních příkladů.

4. Lokální souřadný systém kamery a jeho význam

Pomocí všech devíti parametrů funkce gluLookAt() lze vytvořit úplný a jednoznačný lokální souřadný systém kamery. Parametry lze rozdělit do tří skupin:

  1. První tři parametry určují bod eye=[eyeX, eyeY, eyeZ].
  2. Další tři parametry určují bod center=[centerX, centerY, centerZ].
  3. A konečně, poslední trojicí parametrů je určen vektor up=(upX, upY, upZ).

Body eye a center nesmí být shodné a nesmí ležet v jedné přímce, jež je kolineární s vektorem up. To mimo jiné znamená, že se pomocí těchto bodů specifikuje rovina, v níž jsou vyznačeny dva významné vektory a vektor normálový:

  1. Z bodů eye a center se vypočte vektor F=center-eye (forward), jímž je určen směr pohledu kamery.
  2. Dalším vektorem je vektor L (left), jež je vypočten vektorovým součinem L=up x F. Tento vektor směřuje v lokálním souřadném systému kamery doleva a je samozřejmě kolmý na vektory upF.
  3. Poslední vektor U (up) je taktéž vypočten pomocí vektorového součinu: U=F x L. Tento vektor je kolmý k vektorům FL.

Význam všech výše zmíněných bodů a vektorů byl naznačen na prvním obrázku.

5. Demonstrační příklady

V prvním demonstračním příkladu se vykreslí objekt v ploše, přičemž parametry projekce jsou nastaveny pomocí funkce glOrtho() z knihovny OpenGL.

Zdrojový kód prvního demonstračního příkladu je dostupný zde, jeho HTML verze se zvýrazněním syntaxe zde.

Screenshot prvního demonstračního příkladu
Obrázek 5: Screenshot prvního demonstračního příkladu

Druhý demonstrační příklad vychází z příkladu prvního, zde je však pro nastavení projekce použita funkce gluOrtho2D() z nadstavbové knihovny GLU. Z tohoto příkladu je patrné zjednodušení specifikace parametrů funkce gluOrtho2D() oproti funkci glOrtho().

Zdrojový kód druhého demonstračního příkladu je dostupný zde, jeho HTML verze se zvýrazněním syntaxe zde.

Screenshot druhého demonstračního příkladu
Obrázek 6: Screenshot druhého demonstračního příkladu

Ve třetím demonstračním příkladu je předvedeno nastavení pozice a orientace kamery funkcí gluLookAt() z knihovny GLU. Pomocí klávesnice a myši je možné měnit veškeré vlastnosti kamery.

Zdrojový kód třetího demonstračního příkladu je dostupný zde, jeho HTML verze se zvýrazněním syntaxe zde.

Screenshot třetího demonstračního příkladu
Obrázek 7: Screenshot třetího demonstračního příkladu

bitcoin školení listopad 24

6. Obsah dalšího pokračování

V dalším pokračování tohoto seriálu se budeme zabývat funkcemi, pomocí nichž je možné provádět projekci a zpětnou projekci bodů či vektorů z 3D světového prostoru do okna aplikace.

7. Seznam funkcí OpenGL a GLUT zmíněných v této části

glOrtho()
glFrustum()
glTranslatef()
glRotatef()
glScalef()
 

8. Nové funkce z knihovny GLU popsané v této části

gluOrtho2D()
gluLookAt()

9. Zkomprimovaná verze článku i s přílohami

Zkomprimovaná verze tohoto článku i s přílohami a demonstračními příklady je uložena zde.

Autor článku

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