OpenGL a nadstavbová knihovna GLU (2)

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

Sdílet

Dnešní díl seriálu o nadstavbové knihovně GLU bude věnován popisu funkcí, pomocí nichž je možné zjistit základní informace o grafickém subsystému počítače a o nainstalovaných rozšířeních k základní verzi grafických knihoven OpenGL a GLU.

Obsah

1. Konvence pojmenování funkcí z knihovny GLU
2. Příklady názvů vybraných funkcí
3. Zjištění základních informací o grafickém subsystému
4. Zjištění a výpis všech dostupných rozšíření
5. Rozdíl mezi funkcemi glGetString() a gluGetString()
6. Dotaz na existující rozšíření OpenGL
7. Demonstrační příklady
8. Obsah dalšího pokračování
9. Seznam funkcí OpenGL a GLUT zmíněných v této části
10. Seznam funkcí GLU zmíněných v této části
11. Nové funkce GLU popsané v této části
12. Zkomprimovaná verze článku i s přílohami
 

1. Konvence pojmenování funkcí z knihovny GLU

Prefixy názvů všech funkcí poskytovaných knihovnou GLU začínají třemi malými písmeny glu…, po nichž následuje další slovo či slova, z nichž každé začíná velkým písmenem. U většiny funkcí se, na rozdíl od funkcí OpenGL, z jejich názvu nedá získat počet ani typ jednotlivých parametrů – knihovna GLU obsahuje funkce na vyšší úrovni, které také mají složitější, strukturované parametry a ne jednoduché datové typy (či ukazatele na tyto typy), jak tomu bylo u funkcí z knihovny OpenGL.

Pokud funkce získává a poté vrací nějaké údaje, začíná její název písmeny gluGet…. Některé skupiny funkcí pracují s takzvanými objekty, ve skutečnosti se však jedná o zapouzdření C-čkových paměťových struktur. Funkce pro vytvoření nového objektu začíná písmeny gluNew…, funkce pro zrušení objektu má na začátku uveden řetězecgluDele­te…. Při práci s některými typy objektů se mohou v případě chyby či jiné významné události volat callback funkce. Ukazatele na tyto funkce se předávají (registrují) ve funkci, která má název glu…Callback(), kde se místo tří teček udává typ objektu, pro nějž se callback funkce registruje.

V následujícím odstavci budou uvedeny příklady názvů vybraných funkcí z knihovny GLU.

2. Příklady názvů vybraných funkcí

Funkce pro zpětné získání hodnot, jež byly nastaveny během práce aplikace nebo při její inicializaci:

gluGetNurbsProperty();
gluGetString();
gluGetTessProperty();

Funkce pro vytvoření některých objektů, se kterými se v knihovně GLU pracuje (při překladu programu pomocí překladače jazyka C se použijí struktury, objekty jsou použity pouze u C++, a to ještě ne zcela plnohodnotně):

gluNewNurbsRenderer();
gluNewQuadric();
gluNewTess();

Funkce pro zrušení dříve vytvořených objektů:

gluDeleteNurbsRenderer();
gluDeleteQuadric();
gluDeleteTess();

Funkce pro registraci callback funkcí:

gluQuadricCallback();
gluNurbsCallback();
gluTessCallback();

Výkonné funkce:

gluOrtho2D();
gluLookAt();
gluProject();

3. Zjištění základních informací o grafickém subsystému

Jednou ze základních funkcí, kterou knihovna GLU programátorům poskytuje, je funkce gluGetString(), která má následující hlavičku:

const GLubyte *gluGetString(
    GLenum name
);

Jak je z hlavičky této funkce patrné, předává se funkci gluGetString() jeden parametr typu GLenum a vrací se ukazatel na znak. Ve skutečnosti se vrací ukazatel na C-čkovský řetězec ukončený nulou, který však není modifikovatelný, protože je umístěn v paměti alokované knihovnou GLU při inicializaci, a je tedy určen pouze pro čtení. Pro případnou změnu tohoto řetězce (například před jeho zobrazením) se řetězec musí zkopírovat do oblasti paměti, která byla alokována běžící aplikací.

Funkce gluGetString() může být použita například pro zjištění verze knihovny GLU, nebo, což je mnohem zajímavější a užitečnější, pro zjištění přítomnosti a případně i verzí různých rozšíření knihovny OpenGL (jedná se o známé extensions) od výrobců grafických karet nebo výrobců operačního systému.

Dostupnou verzi knihovny GLU získáme v řetězcové podobě (tj. klasický C-čkový, nulou ukončený řetězec) po provedení následujícího příkazu:

GLubyte *version=gluGetString(GLU_VERSION);

Na prakticky všech platformách je datový typ GLubyte totožný s typem unsigned char, takže je pro zpracování vráceného řetězce možné použít libovolnou funkci z knihoven string astdio. Vrácený řetězec je ve formátu:

<číslo verze><mezera><další informace o výrobci>

Číslo (lépe řečeno označení) verze nesmí obsahovat mezeru, další informace o výrobci však mezery obsahovat mohou – oddělovačem obou částí je pouze první mezera.

To znamená, že se v praxi může vrátit například řetězec:

"1.1.2 SGI Octane"

(bohužel se jedná o prakticky mrtvou platformu), nebo na systémech Win32:

"1.2.11 Microsoft Windows NT"

Dalším důležitým úkolem bývá zjištění nainstalovaných rozšíření, které lze získat po provedení příkazu:

GLubyte *extensions=gluGetString(GLU_EXTENSIONS);

Vrácený řetězec je ve formátu:

<jméno rozšíření><mezera><jméno rozšíření><mezera><jméno rozšíření>... 

tj. jména jednotlivých rozšíření jsou v řetězci oddělena mezerami. V samotném jménu být mezera nesmí, proto se místo ní používají v C-čku běžná podtržítka nebo pomlčky.

4. Výpis všech dostupných rozšíření

Všechna dostupná rozšíření lze jednoduše vypsat pomocí následující funkce:

// ----------------------------------------------
// Tato funkce získá všechna dostupná rozšíření
// knihovny GLU a vypíše je na konzoli.
// ----------------------------------------------
void displayExtensions(void)
{
    int  i;
    char *s;
    char str[100];

    // získání seznamu všech dostupných rozšíření
    // (pro jistotu přetypujeme ukazatel)
    s=(char *)gluGetString(GLU_EXTENSIONS);

    puts("Podporovaná rozšíření knihovny GLU:");

    if (!s) {     // ukazatel na NULL
        puts("Žádná rozšíření nejsou podporována");
    }
    else {
        // projít řetězec a postupně najít a vypsat
        // všechna nalezená rozšíření
        for (i=0; *s; s++) {
            // hledání oddělovačů názvů
            if (*s!=' ') {
                str[i]=*s;
                i++;
            }
            // našli jsme v řetězci oddělovač
            else {
                // ukončení řetězce pro výpis
                // pomocí funkce puts()
                str[i]=0;
                puts(str);
                i=0;
            }
        }
        // výpis posledního rozšíření
        str[i]=0;
        puts(str);
    }
}

5. Rozdíl mezi funkcemi glGetString() a gluGetString()

Možná si z mých předchozích seriálů pamatujete, že i v grafické knihovně OpenGL se vyskytovala podobná funkce, pomocí které se daly zjistit nainstalovaná rozšíření. Tato funkce se jmenovala glGetString(), tedy velmi podobně jako gluGetString(), a měla hlavičku:

const GLubyte* glGetString(
    GLenum name
);

Po zavolání této funkce s parametrem enum nastaveným na hodnotu GL_EXTENSIONS je možné zjistit nainstalovaná rozšíření knihovny OpenGL, nikoli však relevantní informace o případných rozšířeních knihovny GLU. Proto i v knihovně GLU existuje podobná funkce s téměř shodným jménem a použitím. Ukázka použití obou funkcí bude uvedena v demonstračních příkladech.

6. Dotaz na existující rozšíření OpenGL

Při práci s různými rozšířeními OpenGL je možné použít funkci, která přímo otestuje dostupnost nějakého rozšíření. Tato funkce se jmenuje gluCheckExten­sion() a má následující hlavičku:

GLboolean gluCheckExtension(
    const GLubyte *extName,
    const GLubyte *extString
);

V prvním parametru této funkce se předává řetězec, ve kterém je jméno rozšíření, jehož dostupnost testujeme. Ve druhém parametru je předáván řetězec, který je získán pomocí výše popsané funkce gluGetString(). Funkce vrací podle dostupnosti či nedostupnosti rozšíření pravdivostní hodnotu GLtrue čiGLfalse.

Tato funkce vlastně pouze prochází zadaný řetězec a hledá v něm jméno zadaného rozšíření. Kromě toho se provádí test, zda je jméno zadáno korektně, tj. zda se v něm nevyskytují například mezery, číslice na začátku jména či další nepřípustné znaky.

7. Demonstrační příklady

Po překladu a spuštění prvního demonstračního příkladu se na konzoli (tj. na standardní výstup, který lze přesměrovat) vypíše verze knihovny GLU a základní informace o podpoře výrobce grafické karty nebo ovladačů. Pro získání těchto údajů je použita funkce gluGetString(GLU_VER­SION) z knihovny GLU.

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 1: Screenshot prvního demonstračního příkladu

Druhý demonstrační příklad se podobá příkladu prvnímu s tím rozdílem, že se informace nebudou vypisovat na konzoli, ale přímo do GUI okna aplikace. Výpis znaků je proveden pomocí funkce glutBitmapCha­racter() z knihovny GLUT. Pro získání potřebných informací je, stejně jako u předchozího příkladu, použita funkcegluGetStrin­g(GLU_VERSION).

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 2: Screenshot druhého demonstračního příkladu

Po spuštění třetího demonstračního příkladu se na konzoli (standardní výstup) vypíšou všechna dostupná rozšíření. Pro jejich získání se používá funkce gluGetString(GLU_EX­TENSIONS) z knihovny GLU.

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 3: Screenshot třetího demonstračního příkladu

Čtvrtý demonstrační příklad po svém překladu a spuštění také vypíše dostupná rozšíření, nikoli však na konzoli, nýbrž přímo do okna aplikace pomocí funkce glutBitmapCha­racter(). Také zde je, podobně jako u předchozího příkladu, pro zjištění podporovaných rozšíření použita funkce gluGetString(GLU_EX­TENSIONS) z knihovny GLU.

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

Screenshot čtvrtého demonstračního příkladu
Obrázek 4: Screenshot čtvrtého demonstračního příkladu

bitcoin_skoleni

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

V dalším pokračování tohoto seriálu, které se již bude zaobírat zajímavějšími problémy počítačové grafiky, se budu věnovat funkcím, pomocí nichž je možné jednoduše a rychle nastavovat transformační matice Projection a ModelView (tj. kameru – pozorovatele) a dokonce programově transformovat jednotlivé body s použitím různě nastavených transformačních ma­tic.

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

glutBitmapCha­racter()
glGetString()

10. Seznam funkcí GLU zmíněných v této části

gluGetNurbsPro­perty();
gluGetString();
gluGetTessPro­perty();
gluNewNurbsRen­derer();
gluNewQuadric();
gluNewTess();
gluDeleteNurbsRen­derer();
gluDeleteQuadric();
gluDeleteTess();
gluQuadricCallbac­k();
gluNurbsCallback();
gluTessCallback();
gluOrtho2D();
gluLookAt();
gluProject();
 

11. Nové funkce GLU popsané v této části

gluGetString()
gluCheckExtension()

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

Zkomprimovaná verze tohoto článku i s přílohami, obrázky 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.