Transzformáció
Alkalmazás
| Nézeti transzformáció | specifikálja a kamera helyzetét |
| Modellezési transzformáció | objektumok megfelelõ helyre mozgatása |
| Modell-nézet transzformáció | az elõzõ két transzformációt foglalja magába |
| Vetítési transzformáció | vágás és látótérbe méretezés |
| Ablak-transzformáció | az ablakba méretezés |
A glMatrixMode, glLoadIdentity, glLoadMatrix és glMultMatrix parancs
Az OpenGL-ben mind a vetítési (projekció), mind a modell-nézet mátrix módosítható illetve beállítható. Az érvényes mátrix módot a
void glMatrixMode( enum mode );
eljárással lehet beállítani, ahol a mode
a GL_TEXTURE, GL_MODELVIEW, GL_COLOR illetve GL_PROJECTION szimbolikus
konstansok valamelyike lehet. A vetítési mátrix a
szem koordináta rendszer (eye coordinate system) és a vetítés
koordináta rendszer (clip coordinate system) közötti transzformációt
írja le. Ha az érvényes mátrix mód a
GL_MODELVIEW, akkor a mátrix mûveletek a modell-nézet
mátrixra vannak hatással (magyarul ezen mátrix manipulálásával
tudunk geometriai transzformációkat (forgatás-glRotate,
eltolás-glTranslate, nagyítás-glScale) végezni
az objektumokon), ha GL_PROJECTION, akkor a vetítési mátrixra
(tehát így tudunk vetítést megadni). A két
alapvetõ eljárás, amellyel az aktuális mátrixot
inicializálhatjuk, a
void
glLoadMatrix{fd}( T m[16] );
void glMultMatrix{fd}( T m[16] );
A glLoadMatrix
argumentuma egy 16 elemû vektor, amely egy 4×4-ex mátrixot
reprezentál úgy, hogy 16 lebegõpontos számot
tárol oszlopfolytonosan(!!). A glLoadMatrix
az érvényes mátrixot helyettesíti a megadott
mátrixszal.
A glMultMatrix
ugyanígy mûködik, de nem helyettesíti az érvényes
mátrixot, hanem beszorozza azt balról a megadott mátrixszal.
Tehát, ha C az eredeti mátrix, M pedig a glMultMatrix
argumentuma, akkor
C' = C*M,
void glLoadIdentity(void);
eljárás egyenértékû azzal, mint ha meghívnánk a glLoadMatrix-ot az egységmátrixszal. Tehát a glLoadIdentity() parancs meghívása után az érvényes mátrix az egységmátrix lesz.
Az OpenGL alapból nem tartalmaz
nézeti transzformációt beállító
eljárásokat. A szem mindig a (0, 0, 0) koordinátákban
van. Ahhoz, hogy a kamera mozgását érzékeltessük,
az objektumokat kell a kamera transzformáció inverzével
elmozgatni.
A GLU library azonban tartalmaz egy olyan parancsot, mellyel nézeti
transzformációt végezhetünk.
void
gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery,
Gldouble centerz, GLdouble upx, GLdouble upy, GLdouble
upz);
paranccsal a nézeti transzformációt
állíthatjuk be.(eyex,
eyey, eyez) specifikálják a szem pozícióját.
(centerx,
centery, centerz) egy referenciapontot specifikál,
ahová a szem néz; (upx,
upy, upz) egy felfelé mutató vektor (up-vektor,VUP).
A gluLookAt
eljárás kiszámítja a megadott kamera transzformáció
inverzét, majd megszorozza
a kapott inverz transzformációs mátrixszal az
érvényes mátrixot, ezért arra ügyelni
kell, hogy az érvényes mátrix mód a
GL_MODELVIEW legyen.
pl.:
gluLookAt(0.0,0.0,2.0,0.0,0.0,0.0,0.0,1.0,0.0);
A lineáris transzformációk
a következõ eljárásokkal specifikálhatók
(az itt felsorolt parancsok a MODELVIEW mátrixot módosítják,
tehát pl. egy glRotate
parancs specifikál egy transzformációs mátrixot,
amely forgatást végez, majd ezzel beszorozza az érvényes
MODELVIEW mátrixot)
A
void glRotate{fd}( T a, T x, T y, T z );
eljárásban az a adja meg, hogy hány fokkal forgatunk; a kiszámolt mátrix egy óramutató járásával ellentétes forgatást specifikál az (x, y, z)-vel megadott tengely körül.
pl.: a glRotated(45,
1.0, 0.0, 0.0) egy 45 fokos forgatást specifikál
az x tengely körül
a glRotated(12.5, 0.0, 0.0,
1.0) egy 12.5 fokos forgatást specifikál a
z tengely körül
A
void glTranslate{fd}( T x, T y, T z );
argumentumai az eltolás vektort adják meg: ( x, y, z ).
pl.: a glTranslated(
50, 0, 0 ) az x-tengely mentén 50 egységgel
való eltolást specifikál
A
void glScale{fd}( T x, T y, T z );
eljárás általános skálázást végez az x, y, z tengely mentén.
pl.: a glScaled(0.5, 0.5, 0.5) egy 0.5-szörös uniform nagyítást végez
A viewport az az ablakon belüli rész, ahová rajzolunk, tehát a viewport transzformációval adjuk meg a létrejövõ kép méretét. A viewport általában maga az ablak, de elképzelhetõ az is, hogy a viewport az ablaknak csupán egy része. A következõ két ábra közül az egyik olyan viewportot ábrázol, amely az egész ablakot lefedi, a másiknál a viewport a létrehozott ablak bal alsó sarkánál helyezkedik el.
Az aktuális viewportot a
void glViewport(int x, int y, GLsizei width, GLsizei height);
eljárással specifikálhatjuk. Az eljárás egy téglalapot definiál az OpenGL ablakba, ahová rajzolni szeretnénk. Az (x, y) paraméterek specifikálják a viewport bal alsó sarkát, width és height pedig a viewport téglalap méretét. Alapértelmezésben a paraméterek a (0, 0, winWidth, winHeight) értékeket veszik fel, ahol winWidth és winHeight az ablak méretei.
pl.: glViewport(0, 0, w, h) esetén ha az ablak szélessége w, magassága pedig h, akkor a viewport az ablak lesz.
Az OpenGL-ben párhuzamos (ortografikus) és perspektivikus vetítést is specifikálhatunk. Itt némi kiegészítésre van szükség a vetítésekkel kapcsolatosan: a két alapvetõ vetítési fajtán belül még igen sokféle különbözõ vetítést meg lehet adni; perspektív vetítésnél a vetítéseket az elsõdleges távlatpontok száma szerint osztályozzuk, párhuzamos vetítés esetén pedig a vetítési irány és a vetítési sík egymáshoz való viszonya szerint. Jelen honlapon ha párhuzamos vetítésrõl van szó, akkor mindig olyan párhuzamos vetítésre gondolunk, ahol a vetítési sík merõleges a z tengelyre, és a vetítési sík normálisa párhuzamos a vetítési iránnyal (azaz az ortografikus vetítés egy speciális esete). A vetítéseket úgy adjuk meg, hogy megadjuk a látótér nagyságát és alakját. Ami a látótéren belülre esik, az fog a képernyõn látszani.
void glOrtho( double left, double right, double bottom, double top, double near, double far );
eljárással a párhuzamos vetítés látóterét
specifikálhatjuk. left
és right
adják meg a baloldai és jobboldali függõleges
vágósíkok koordinátáit. bottom
és top
az alsó és felsõ vízszintes vágósíkok
koordinátái. near
és far
adják meg a közeli és távoli vágósíkok
távolságát a szemtõl. A (left,
bottom,
-near)
és a (right,
top, -near) specifikálják tehát a közeli
vágósík pontjait, amelyek ráfeszülnek
az ablak bal alsó és jobb felsõ sarkaira ( feltételezve,
hogy a szem a (0, 0, 0) pontban van). far
adja meg a távoli vágósík távolságát
a szemtõl.
Tehát a közeli vágósík
ablakba esõ részének bal alsó sarka:
(left, bottom,
-near), a jobb felsõ sarka:
(right,
top, -near). A távoli vágósík ablakba esõ
részének bal alsó sarka: (left,
bottom, far), jobb felsõ sarka:
(right,
top, far).
Ha kétdimenziós objektumokat akarunk rajzolni, akkor
a
void gluOrtho2D(double left, double right, double
bottom, double top);
eljárással is specifikálhatjuk a vetítési
mátrixot. Ekkor a vágási téglalap egyszerûen
a (left, bottom, right, top)
koordinátákkal megadott téglalap.
A glOrtho
(gluOrtho2D)
megszorozza az aktuális projekciómátrixot a specifikált
mátrixszal és ez lesz az új projekciómátrix.
Ebben az esetben a látótér egy téglalap, amelyre
példa:
2. ábra
pl.: a glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0) egy párhuzamos vetítést specifikál, ahol a közeli vágósík(azon része, mely a látótérbe esik) bal alsó sarkának koordinátái (0.0, 0.0, -1.0) , jobb felsõ sarkának koordinátái (1.0, 1.0, -1.0); a távoli vágósík bal alsó sarkának koordinátái (0.0, 0.0, 1.0), jobb felsõ sarkának koordinátái (1.0, 1.0, 1.0). Azaz mind a közeli, mind a távoli vágósík 1.0 távolságra van a vetítési síktól.
void glFrustum( double left, double right, double bottom, double top, double znear, double zfar );
eljárással a perspektív vetítés látóterét
specifikálhatjuk. left
és right
adják meg a baloldali és jobboldali függõleges
vágósíkok koordinátáit. bottom
és top
az alsó és felsõ vízszintes vágósíkok
koordinátái. znear
és zfar
adják meg a közeli és távoli vágósíkok
távolságát a szemtõl. A (left,
bottom,- znear) és (right,
top,- znear) specifikálják tehát a közeli
vágósík pontjait, amelyek ráfeszülnek
az ablak bal alsó és jobb felsõ sarkaira. zfar
adja meg a távoli vágósík távolságát
a szemtõl. (itt is feltételezzük, hogy a szem a (0,
0, 0) pontban van).
Lehetõség van a perspektív vetítési
mátrix egy szemléletesebb specifikációjára
is, mégpedig a
void gluPerspective(double fovy, double aspect, double
near, double far);
eljárás segítségével, amely szimmetrikus látóteret specifikál. fovy adja meg a látótér szögét az x-z sík irányában, aspect a vágási téglalap szélességének és magasságának arányát, near és far pedig a vágósíkok távolságát.
A glFrustum megszorozza az aktuális projekció mátrixot a specifikált mátrixszal és ez lesz az új projekció mátrix. Ennél a vetítésnél a látótér egy csonkagúla, amely a következõképpen néz ki:
3.ábra
4.ábra
pl.: a glFrustum(0.0, 1.0, 0.0, 1.0, 1.0, 3.0) egy perspektivikus vetítést specifikál, ahol a közeli vágósík (azon része, mely a látótérbe esik) bal alsó sarkának koordinátái (0.0, 0.0, -1.0), jobb felsõ sarkának koordinátái (1.0, 1.0, -1.0); a távoli vágósík bal alsó sarkának koordinátái (0.0, 0.0, -3.0), jobb felsõ sarkának koordinátái (1.0, 1.0,- 3.0). Azaz a közeli vágósík 1.0 távolságra, a távoli vágósík pedig 3.0 távolságra van a szemtõl.
Minden mátrix mód számára van egy mátrix verem. Az érvényes mátrix minden módban a verem tetején lévõ mátrix. A mûveletek:
void
glPushMatrix( void );
void glPopMatrix( void );
A glPushMatrix és glPopMatrix az érvényes mátrix módnak megfelelõ mátrixokkal dolgoznak. Kezdetben minden veremben egy mátrix van, mégpedig az egységmátrix. A kezdõ mátrix mód a MODELVIEW mód.A mátrix veremmûveletekkel lehetõvé válik az egyes mátrixok elmentése, hogy késõbb, ha szükségünk van rájuk, akkor újra használni tudjuk. A mátrix veremmûveleteket többnyire akkor használjuk, amikor olyan objektumot akarunk pl. animálni, mely több egyszerûbb objektumból épül fel, és az egyes részeket eltérõ módon akarjuk mozgatni/transzformálni. Például, ha rajzolunk két kockát, és az egyiket forgatjuk a z-tengely mentén az óramutató járásával ellentétes irányba, a másikat pedig az óramutatóval megegyezõ irányba forgatjuk, akkor ezt úgy tudjuk megoldani, hogy a két kockára két különbozõ transzformációs mátrixunk van.