OpenGL.Hu – III. rész

Az előző cikkben eljutottunk odáig, hogy megcsináltunk egy programot, amely az egyik legalapvetőbb primitive-et, a QUAD-ot, vagyis téglalapot (négyzetet) jelenítette meg. Ezek után logikus lépésnek tűnik, ha sorra vesszük a többi alakzatot is, mert később igen hasznosak lehetnek számunkra. Vágjunk is bele! Példaprogramokat most nem fogok felírni, csak a glBegin()-hez tartozó paraméterüket és a szükséges vertexek számát mindegyikre. Ennek alapján könnyen átírható az első programunk, hogy a négyzet helyett más alakzatokat jelenítsen meg, így kipróbálhatjuk gyorsan és egyszerűen az összes primitive-et.

Bűvészkedjünk a vertexekkel!

  1. GL_POINTS - Az összes megadott vertexet különálló pontként jeleníti meg, nem húz szakaszt köztük. Tetszőleges számú pont adható meg.
  2. GL_LINES - Kettesével veszi a megadott vertexeket és vonalakat rajzol belőlük. Pl. Az 1-t összeköti a 2-kal, a 3-at a 4-el, stb. Itt is tetszőleges mennyiségű vertex adható meg, de a vertexek száma páros kell, hogy legyen.
  3. GL_LINE_STRIP - Hasonló az előzőhöz, azzal a különbséggel, hogy sorban összeköti a pontokat, gyakorlatilag egy tetszőleges hosszú görbét alkotva belőlük ezáltal.
  4. GL_LINE_LOOP - Ugyanaz, mint az előző, de az utolsónak megadott vertexet automatikusan összeköti az elsőnek megadottal.
  5. GL_TRIANGLES - Úgy működik, mint a GL_LINES, de itt hármasával veszi a vertexeket és háromszögeket formál belőlük. A vertexek számának hárommal oszthatónak kell lennie!
  6. GL_TRIANGLE_STRIP - Arra használják, hogy háromszögekből összefüggő felületeket alakítsanak ki. A megadott vertexekből úgy formál a GL_TRIANGLES -hez hasonló alakzatokat, hogy a körüljárási irányuk ugyanaz maradjon. Megfelelő mennyiségű vertex megadása után egy gyűrű alakul ki az összekapcsolódó háromszögekből.
  7. GL_TRIANGLE_FAN - Az elsőnek megadott vertex köré rendezi el az összekapcsolódó háromszögeket legyezőszerűen.
  8. GL_QUADS - Ezt már remélhetőleg mindenki ismeri: téglalapokat gyárthatunk vele kedvünkre.
  9. GL_QUAD_STRIP - A GL_TRIANGLE_STRIP -hez hasonlóan működik, de négyszögekkel teszi ugyanazt. A vertexek számának minimum négynek és mindenképpen párosnak kell lennie!
  10. GL_POLYGON - A megadott vertexekből egy tetszőleges sokszöget alakíthatunk ki ennek a segítségével. A vertexek által alkotott poligonnak konvexnek kell lennie és nem metszheti önmagát.

 

Huh! Ez gyors és tömör volt, remélem azért mindenki értette, melyik primitive mire való! Biztosan volt jó néhány lelkes olvasó, aki próbálgatott egyszerre egynél több primitive-et elhelyezni az ablakba, a következő módon:

glBegin(valami_primitive)

      .

      .                 //vertexek

      .

glEnd();

glBegin(masik_primitive)

      .

      .                 //újabb vertexek

      .

glEnd();

És mit tapasztaltak, akik ezt próbálták? Összetalálkoztak azzal a problémával, hogy az összes primitive egymás hegyére-hátára kerül az ablakban! A megoldás: pozicionálás! Arról van szó, hogy amikor egy (x,y,z) koordinátát itt megadunk, a hozzárendelt vertex egy origóhoz képest lesz elhelyezve a térben, tehát ezek relatív koordináták! Ebből már egész egyszerűen jön az ötlet, hogy ha meg tudnánk változatni két primitive megadása között a viszonyítási pontot, akkor a második már valószínűleg nem oda kerülne, ahová az első került.

Erre szolgál a glTranslatef() függvény, amely a viszonyítási pontot helyezi át. Három paramétere logikusan egy (x,y,z) hármas, amelyek megadják, hogy melyik tengelyen hány egységgel toljuk el a kiindulási pontot. Azonban ezt az új függvényt használva a feladattól függően új problémával is találkozhatunk: nem várt eltolódások és hasonlók jöhetnek elő. Ennek a jelenségnek a magyarázata abban rejlik, hogy a glTranslatef() megváltoztatja a korábban említett mátrixokat. Az OpenGL a következő render-ciklusban természetesen már a módosított mátrixokkal számol, nem pedig azokkal, amik eredetileg adottak voltak, így a módosítások halmozódnak és ez néha beláthatatlan következményekkel lehet a koordináta-transzformációkra. Ez úgy küszöbölhető ki, hogy egy glLoadIdentity() nevű függvénnyel a RenderScene() legelső sorában visszaállítjuk a mátrixokat eredeti értékeikre (az egységmátrixra). Így már minden render-ciklusban a helyreállított mátrixokkal számol a rendszer és a hiba megszűnt!

Ebben a cikkben nem szándékoztam már új témába belevágni, de azért még néhány érdekes ötletet felvetnék a vertexekkel kapcsolatban:

  1. Ha a vertexeknek változókat adunk meg koordinátának és ezek értékeit a RenderScene() függvényben folyamatosan változtatjuk, kezdetleges animációkat állíthatunk elő. (Hasonlóképpen tehetünk a rajzolószínnel is...)
  2. A glBegin() és a glEnd() között gyakorlatilag minden ciklusszervező és egyéb hasonló utasítás megengedett, így leegyszerűsíthetjük elég sok geometriai alakzat megjelenítését.
  3. Jó néhány 3D modellező program tud vertex-listát exportálni szövegfájlba, így nem túl nagy erőfeszítés árán be tudjuk ezt tölteni egy OpenGL programba, igaz egyenlőre csak vonalhálóként megjelenítve.

Remélem még mindig tud mindenki követni, mert lassan ugyan, de biztosan haladunk előre és egy kis idő múltán nagy szükségünk lesz az eddigi alapokra.

Továbbra is várom leveleiket, kérdéseiket a témával kapcsolatban!

Merczel László