Hlavní navigace

OpenGL evaluátory (5)

Pavel Tišnovský 8. 6. 2004

Toto pokračování seriálu o OpenGL evaluátorech bude opět věnováno problematice vykreslování Bézierových bikubických ploch. Už ve třetí části seriálu jsme si popsali teorii Bézierových ploch spolu s ukázkou programové implementace. V této části si ukážeme použití evaluátorů pro automatizovaný výpočet bodů ležících na Bézierově ploše.

Obsah

Použití evaluátorů pro výpočet a vykreslování Bézierových ploch
Nastavení souřadnic řídících bodů Bézierovy plochy
Nastavení a povolení dvojdimenzionálního evaluátoru
Vykreslení Bézierova plátu s využitím evaluátorů
Ukázka použití evaluátorů
Demonstrační příklady
Obsah dalšího pokračování
Seznam funkcí OpenGL zmíněných v této části
Nové funkce OpenGL popsané v této části
Zkomprimovaná verze článku i s přílohami

Použití evaluátorů pro výpočet a vykreslení Bézierových ploch

V tomto pokračování seriálu o evaluátorech v grafické knihovně OpenGL si popíšeme způsob vytváření Bézierových bikubických ploch, které lze použít jako pláty při vytváření opláštění vykreslovaných třídimenzionálních těles. Bézierovy bikubické plochy vznikly (z pohledu grafika) rozšířením Bézierových kubických křivek o další parametr. Zatímco jsou body na Bézierově kubické křivce specifikovány pouze jedním parametrem t, který nabývá hodnot z rozsahu 0–1, u Bézierových bikubických ploch je každý bod na ploše specifikován dvěma parametry v parametrickém prostoru, které jsou již tradičně označovány jmény u a v.

Již ve třetí části tohoto seriálu jsme si ukázali, jakým způsobem může probíhat výpočet bodů, které leží na Bézierově ploše. Z demonstračních příkladů je patrné, že výpočet bodů na Bézierově ploše může být pro vykreslování scén v reálném čase příliš pomalý, i když existují metody pro urychlení výpočtu. Z tohoto důvodu je pro rychlejší zobrazování vhodné, aby výpočet bodů na ploše probíhal přímo na grafickém akcelerátoru – samozřejmě pouze za předpokladu, že grafický akcelerátor podporuje evaluátory, v opačném případě řeší výpočet funkce zabudované v samotné knihovně OpenGL. V dalších odstavcích si popíšeme způsob nastavení evaluátorů tak, aby se pomocí nich daly vykreslovat Bézierovy plochy.

Nastavení souřadnic řídících bodů Bézierovy plochy

Podobně jako u zadávání parametrů Bézierových kubických křivek je i u bikubických ploch nutné specifikovat jejich řídící body. Tyto body tvoří mřížku o rozměrech 4×4, jak je patrné z následujícího obrázku:

Obrázek 1: Šestnáct řídících bodů Bézierova bikubického plátu
Obrázek 1: Šestnáct řídících bodů Bézierova bikubického plátu

Podobně jako u zadání řídících bodů Bézierovy kubické křivky lze i zde v aplikacích použít pole hodnot typu GLdouble nebo GLfloat. Specifikace řídících bodů Bézierovy bikubické plochy může v programovacím jazyce C nebo C++ vypadat následovně:

// řídící body Bézierovy křivky
GLfloat controlPoints[4][4][3] = {
    {   // první čtveřice řídících bodů
        {-1.5, -1.5,  4.0},
        {-0.5, -1.5,  2.0},
        { 0.5, -1.5, -1.0},
        { 1.5, -1.5,  2.0}
    },
    {   // druhá čtveřice řídících bodů
        {-1.5, -0.5,  1.0},
        {-0.5, -0.5,  3.0},
        { 0.5, -0.5,  0.0},
        { 1.5, -0.5, -1.0}
    },
    {   // třetí čtveřice řídících bodů
        {-1.5,  0.5,  4.0},
        {-0.5,  0.5,  0.0},
        { 0.5,  0.5,  3.0},
        { 1.5,  0.5,  4.0}
    },
    {   // čtvrtá čtveřice řídících bodů
        {-1.5,  1.5, -2.0},
        {-0.5,  1.5, -2.0},
        { 0.5,  1.5,  0.0},
        { 1.5,  1.5, -1.0}
    }
};

Ve výše uvedeném zlomku zdrojového kódu je specifikováno šestnáct řídících bodů, které tvoří mřížku o rozměrech 4×4 body. Bézierova plocha prochází pouze čtveřicí rohových řídících bodů, ostatní body mění jen její zakřivení.

Nastavení a povolení dvojdimenzionálního evaluátoru

Po zadání řídících bodů Bézierovy plochy je možné přistoupit k dalšímu kroku, v němž se provede povolení a nastavení dvojdimenzionálního evaluátoru, který pro každou dvojici hodnot u a v vrátí souřadnici bodu v prostoru. Povolení 2D evaluátoru se provede příkazem:

// povolení 2D evaluátoru
glEnable(GL_MAP2_VERTEX_3);

Opětovné zakázání použití evaluátorů po vykreslení všech ploch by se provedlo příkazem:

// zakázání 2D evaluátoru
glDisable(GL_MAP2_VERTEX_3);

Z předchozích příkazů je vidět podoba s jednodimenzi­onálními evaluátory, které jsme si popsali v minulé části.

Další dvojice příkazů slouží k nastavení řídících bodů Bézierovy plochy a povolených rozsahů parametrů u a v:

void glMap2d(
    GLenum   target,
    GLdouble u1,
    GLdouble u2,
    GLint    ustride,
    GLint    uorder,
    GLdouble v1,
    GLdouble v2,
    GLint    vstride,
    GLint    vorder,
    const    GLdouble *points
);

void glMap2f(
    GLenum   target,
    GLfloat  u1,
    GLfloat  u2,
    GLint    ustride,
    GLint    uorder,
    GLfloat  v1,
    GLfloat  v2,
    GLint    vstride,
    GLint    vorder,
    const    GLfloat *points
);

Význam jednotlivých argumentů funkcí glMap2d() a glMap2f() je následující:

  • V argumentu target je zadán typ hodnot, které mají být pomocí evaluátoru generovány. Význam jednotlivých hodnot je obdobný jako u funkcíglMap1f() a glMap1d().
  • V argumentech u1 a u2 je zadán rozsah hodnot prvního parametru u. Pro každou hodnotu parametru u je interně provedeno mapování do rozsahu 0–1.
  • Argumenty v1 a v2 mají podobný význam jako argumenty u1 a u2 s tím rozdílem, že je pomocí nich nastaveno mapování druhého parametru v ze zadaného rozsahu v1-v2 do interního rozsahu 0–1.
  • Hodnoty argumentů uorder a vorder značí dimenzi plochy ve směru parametru u resp. parametru v. Dimenzí plochy je určen i počet řídících bodů ve směru příslušného parametru.
  • V argumentech ustride a vstride je specifikován počet číselných hodnot, které se nacházají mezi informacemi o jednotlivých řídících bodech. Význam je stejný jako v případě použití jednodimenzio­nálního evaluátoru – možnost uložit veškerá data o řídících bodech (i s jejich barvami apod.) do jednoho pole.
  • V posledním argumentu points je předán ukazatel na oblast paměti, ve které se nachází informace o jednotlivých řídících bodech.

Vykreslení Bézierova plátu s využitím evaluátorů

Postup při vykreslování Bézierova plátu je v mnoha ohledech podobný vykreslení Bézierovy křivky. Bézierovy pláty lze vykreslit buď jako body, polyčáry, nebo jako vyplněné polygony – to závisí na způsobu použití aplikace. Pro vyčíslení každého bodu na Bézierově křivce se zavolá funkce:

void glEvalCoord2f(
    GLfloat u,
    GLfloat v
);

nebo:

void glEvalCoord2d(
    GLdouble u,
    GLdouble v
);

která podle nastavených parametrů u a v pošle do vykreslovacího řetězce požadovanou hodnotu, tj. polohu vertexu, barvu, normálu apod. Při zadávání hodnot parametrů u a v se samozřejmě provádí mapování ze zadaných rozsahů u1-u2 a v1-v2 na interní rozsah 0–1.

Ukázka použití evaluátorů

V následující C-čkovské funkci je ukázáno, jakým způsobem lze evaluátory využít při vykreslení Bézierova bikubického plátu, který je složený z jednotlivých bodů (všimněte si, jakým způsobem jsou nastaveny hodnoty argumentů ustride a vstride):

//---------------------------------------------
// Tato funkce vykreslí Bézierovu plochu
// z jednotlivých bodů pomocí OpenGL evaluátorů
//---------------------------------------------
void drawBezierSurfaceUsingEvaluators(
  GLfloat points[][4][3])
{
  int i,j;

  // předání řídících bodů Bézierovy plochy
  glMap2f(GL_MAP2_VERTEX_3, // počítat polohy vertexů
      0,              // rozsah mapování
      1,              // parametru u
      3,              // počet hodnot mezi par. u
      4,              // dimenze ve směru u
      0,              // rozsah mapování
      1,              // parametru v
      12,             // počet hodnot mezi par. v
      4,              // dimenze ve směru v
      &points[0][0][0]);

  // začátek vykreslování bodů
  glBegin(GL_POINTS);

  // osa _u_ v parametrickém prostoru
  for (i=0; i<=30; i++) {

    // osa _v_ v parametrickém prostoru
    for (j=0; j<=30; j++) {

      // změna barvy vykreslovaného bodu
      glColor3f(1.0, j/30.0, i/30.0);

      // výpočet polohy bodu a poslání
      // do vykreslovacího řetězce
      glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/30.0);
    }
  }
  glEnd();
}

Vykreslení Bézierova plátu pomocí pruhu čtyřúhelníků (quad strip) je poněkud složitější, protože se pro každý čtyřúhelník musí počítat pozice vždy dvou vrcholů (zbylé dva vrcholy jsou už v pruhu zadány):

//-----------------------------------------------
// Tato funkce vykreslí Bézierovu plochu ze
// čtyřúhelníků pomocí OpenGL evaluátorů
//-----------------------------------------------
void drawBezierSurfaceUsingEvaluators(
    GLfloat points[][4][3])
{
  int i,j;

  // předání řídících bodů Bézierovy plochy
  glMap2f(GL_MAP2_VERTEX_3, // počítat polohy vertexů
      0,                // rozsah mapování
      1,                // parametru u
      3,                // počet hodnot mezi par. u
      4,                // dimenze ve směru u
      0,                // rozsah mapování
      1,                // parametru v
      12,               // počet hodnot mezi par. v
      4,                // dimenze ve směru v
      &points[0][0][0]);

  // osa _u_ v parametrickém prostoru
  for (i=0; i<30; i++) {

    // kreslení pruhu ze čtyřúhelníků
    glBegin(GL_QUAD_STRIP);

    // osa _v_ v parametrickém prostoru
    for (j=0; j<=10; j++) {
      // změna barvy prvního vykreslovaného vertexu
      glColor3f(i/30.0, 0.5, j/10.0);
      glEvalCoord2f((GLfloat) i/30.0, (GLfloat)j/10.0);
      // změna barvy druhého vykreslovaného vertexu
      glColor3f((i+1)/30.0, 0.5, j/10.0);
      glEvalCoord2f((GLfloat)(i+1)/30.0, (GLfloat)j/10.0);
    }
    glEnd();
  }
}

Demonstrační příklady

Po spuštění prvního demonstračního příkladu se vykreslí Bézierova bikubická plocha (plát), která je vypočtena s použitím 2D evaluátoru. Výpočet probíhá ve funkci drawBezierSur­faceUsingEvalu­ators(). Bézierova plocha se zobrazí pomocí jednotlivých bodů vykreslovaných grafickou primitivou GL_POINT. Pohled na Bézierovu plochu je animovaný, animaci lze spustit a opět zastavit pomocí klávesy S. Klávesou ESC je možné program ukončit, klávesou F se provede přepnutí okna na celou obrazovku. Opětovné zmenšení okna na velikost 450×450 pixelů se provede pomocí klávesy W.

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

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

Druhý demonstrační příklad se v mnoha ohledech podobá příkladu prvnímu. Jediný rozdíl spočívá v tom, že se Bézierova bikubická plocha vykreslí pomocí lomených úseček s využitím grafické primitivy GL_LINE_STRIP. Ovládání programu včetně animace kopíruje první demonstrační příklad.

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

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

Třetí demonstrační příklad vychází z obou předchozích příkladů. Bézierova bikubická plocha je vykreslována pomocí spojených plošek vytvořených grafickou primitivou GL_QUAD_STRIP. Všimněte si způsobu výpočtu jednotlivých bodů, kdy je zapotřebí pro každou plošku zadat dva vrcholy.

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

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

Obsah dalšího pokračování

Následující díl bude věnován způsobům pro zjednodušení vykreslování.

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

glEnable()
glDisable()
glMap1d()
glMap1f()
glBegin()
glEnd()
glColor3f()
 

Nové funkce popsané v této části

glMap2d()
glMap2f()
glEvalCoord2d()
glEvalCoord2f()
 

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

Zkomprimovaná verze tohoto článku je umístěna zde.

Našli jste v článku chybu?

17. 8. 2004 16:50

Glin (neregistrovaný)

Dobry den, doufam, ze mi tu jeste nekdo odpovi, chtel bych se zeptat:
Myslim, ze asi ve 3 dilu serialu o OpenGL jste uvedl, ze u bodu ctyruhelniku (QUAD) musime zarucit ze jsou v jedne rovine. V 3. prikladu, kde jsou pouzity si myslim, ze to rozhodne neplati :-)
Kdyz jsem to zkousel, tak se mi to sice pekne vykreslilo, ale myslim (zjistoval jsem to tak, ze jsem zmensoval krok i a j), ze jsem dostal uplne stejny visualni vysledek kdyz jsem prepsal
glBegin(GL_QUAD_STRIP);
na
glBegin(GL_TRIAN…




DigiZone.cz: ČRa DVB-T2 ověřeno: Hisense a Sencor

ČRa DVB-T2 ověřeno: Hisense a Sencor

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Vitalia.cz: Z tohoto konopí dělají léčivé masti

Z tohoto konopí dělají léčivé masti

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Vitalia.cz: Znáte „černý detox“? Ani to nezkoušejte

Znáte „černý detox“? Ani to nezkoušejte

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

Podnikatel.cz: Babiš: E-shopy z EET možná vyjmeme

Babiš: E-shopy z EET možná vyjmeme

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Měšec.cz: Jak levně odeslat balík přímo z domu?

Jak levně odeslat balík přímo z domu?

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

Podnikatel.cz: Chaos u EET pokračuje. Jsou tu další návrhy

Chaos u EET pokračuje. Jsou tu další návrhy

Vitalia.cz: Dáte si jahody s plísní?

Dáte si jahody s plísní?

120na80.cz: Jak oddálit Alzheimera?

Jak oddálit Alzheimera?

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU