Obsah
Použití evaluátorů pro výpočet a vykreslování Bézierových plochNastavení 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
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 jednodimenzioná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í jednodimenzioná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 drawBezierSurfaceUsingEvaluators(). 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.
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.
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.
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.