Hlavní navigace

OpenGL evaluátory (5)

Pavel Tišnovský

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?