Transforace (v OpenGL) příklady a knihovna GLM Petr Felkel, Jaroslav Sloup Katedra počítačové grafiky a interakce, ČVUT FEL ístnost KN:E-413 (Karlovo náěstí, budova E) E-ail: felkel@fel.cvut.cz Poslední zěna: 15.3.2016
Modelovací transforace w z y x Souřadnice okna Modelovací a pohledová transforace odelovací Transforace Pohledová transforace Projekční transforace + Ořezání (clipping) Transforace záběru (Viewport) odelovací souřadnice světové souřadnice souřadnice kaery (oka) Noralizované souřadnice zařízení vrchol Perspektivní dělení ořezávácí souřadnice 3D 2D 2
Mikropřehled transforací a jejich inverzí Následuje přehled základních transforačních atic + Způsob jejich vytvoření v knihovně GLM (OpenGL atheatics) GLM vychází se syntaxe GLSL Lze ji najít na adrese http://gl.g-truc.net/ Knihovna je součástí balíčku -fraework. Do verze GLM 0.9.5 používá stupně, Od verze GLM 0.9.6 používá radiany // načtení halviček transforací v knihovně GLM. V fraeworku je již uděláno #include <gl/gtc/atrix_transfor.hpp> 4
Identita Jednotková atice, například funkce M = Identity() y I= 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 z Výchozí pozice a natočení odelu x Používá se na inicializaci atice v příkazech, které násobí aktuální atici aticí nově definované transforace // vytvoření atice identity poocí knihovny GLM gl::at4 = gl::at4(1.0); 5
Matice posunutí (translace) Matice posunutí (translace) realizuje posunutí dané vektore = (resp. posune lokální soustavu souřadnic o stejné hodnoty) = 1 0 0 x a = 1 0 0 -x 0 1 0 y 0 1 0 -y 0 0 1 z 0 0 1 -z 0 0 0 1 0 0 0 1 // posunutí atice o zadaný vektor. Vynásobí atici atrix aticí posunutí o vector gl::at4 = gl::translate( atrix, vector ); 6
Posunutí v GLM /* set identity to atrix */ gl::at4 atrix = gl::at4(1.0); passmatrixtovertexshader( atrix ); drawmodel(); /* original odel */ /* add translation to atrix */ gl::at4 atrix1 = gl::translate( atrix, /* atrix to be odified */ gl::vec3(1.25f, 0.0f, 0.0f)); /* aount of translation */ passmatrixtovertexshader( atrix1 ); drawmodel(); /* iage 1 */ /* add another translation to atrix */ gl::at4 atrix2 = gl::translate( atrix, /* atrix to be odified */ gl::vec3(0.0f, 1.25f, 0.0f)); /* aount of translation */ passmatrixtovertexshader( atrix2 ); drawmodel(); /* iage 2 */ orig. odel iage 1 iage 2 7
Matice pro zěnu ěřítka (škálování) Matice pro zěnu ěřítka (škálování) Souřadné osy lokální soustavy souřadnic se prodlouží či zkrátí dle sx, sy a sz as nii se transforuje i přidružený objekt Ten se protáhne, srští, nebo překlopí S = sx 0 0 0 a S -1 = 1/sx 0 0 0 0 sy 0 0 0 1/sy 0 0 0 0 sz 0 0 0 1/sz 0 0 0 0 1 0 0 0 1 // atice zěny ěřítka na jednotlivých osách. Vynásobí atrix škálovací aticí gl::at4 = gl::scale( atrix, vector ); 8
Zěna ěřítka v GLM /* set identity to atrix */ gl::at4 atrix = gl::at4(1.0); passmatrixtovertexshader( atrix ); drawmodel(); /* original odel */ gl::at4 atrix1 = gl::scale( /* add scale transfor */ atrix, /* atrix to be odified */ gl::vec3(1.75f, 1.0f, 1.0f)); /* scale coefficients */ passmatrixtovertexshader( atrix1 ); drawmodel(); /* iage 1 */ gl::at4 atrix2 = gl::scale( /* add another scale transf. */ atrix, /* atrix to be odified */ gl::vec3(-1.0f, -2.75f, 1.0f)); /* scale coefficients */ passmatrixtovertexshader( atrix2 ); drawmodel(); /* iage 2 */ orig. odel iage 1 iage 2 9
Rotace kole obecné osy z Otočení kole zadané osy o úhel ve stupních Inverzní rotace = rotace okolo stejné osy o opačný úhel - y Let v = [x, y, z] T S = 0 -z y u = v/ v =[x, y, z ] T z 0 -x P=[x,y,z] -y x 0 x M R = u T u + cos (angle) (M I - u T u) + sin (angle) S 0 3 6 0 M R = 1 4 7 0 M I identity atrix direction of object rotation 2 5 8 0 coefficients of M R 0 0 0 1 // atice rotace o úhel angle kole obecné osy axis // (do GLM 0.9.5 ve stupních / GLM 0.9.6 radianech ) gl::at4 = gl::rotate( atrix, angle, axis ); 10
Rotace kole souřadných os Speciální případy rotací rotace podle souřadnicových os X Y Z y y y x x x Y X Z z z z 1 0 0 0 0 cos() -sin() 0 0 sin() cos() 0 0 0 0 1 cos() 0 sin() 0 0 1 0 0 -sin() 0 cos() 0 0 0 0 1 cos() -sin() 0 0 sin() cos() 0 0 0 0 1 0 0 0 0 1 Inverzní rotace = rotace okolo stejné osy o opačný úhel - 12
Rotace v GLM direction of object rotation orig. odel /* set identity to atrix */ gl::at4 atrix = gl::at4(1.0); passmatrixtovertexshader( atrix ); drawmodel(); /* original odel */ gl::at4 atrix1 = gl::rotate( /* add rotation */ atrix, /* atrix to be odified */ gl::radians(45), /* angle in degrees */ gl::vec3(1.0f, 0.0f, 0.0f)); /* rotation axis */ passmatrixtovertexshader( atrix1 ); drawmodel(); /* iage 1 */ gl::at4 atrix2 = gl::rotate( /* add another rotation */ atrix, /* atrix to be odified */ gl::radians( -45), /* angle in degrees */ gl::vec3(0.0f, 0.0f, 1.0f)); /* rotation axis */ passmatrixtovertexshader( atrix2 ); drawmodel(); /* iage 2 */ z y P=[1,0,0] x iage 1 y x z P=[0,0,1] iage 2 14
Rotace není koutativní Pozor! Záleží na pořadí transforací, neboť aticové násobení není koutativní! tj., R.T není totéž co T.R R.T.[ ] T.R.[ ] 16
Rotace následovaná translací T.R.[ ] /* set identity to atrix */ gl::at4 atrix = gl::at4(1.0); passmatrixtovertexshader( atrix ); drawmodel(); /* original odel */ atrix =gl::translate( /* add translation */ atrix, /* atrix to be odified */ gl::vec3(2.5f, 0.0f, 0.0f)); /* aount of translation */ atrix =gl::rotate( /* add rotation */ atrix, /* atrix to be odified */ gl::radians(45), /* angle in degrees */ gl::vec3(0.0f, 0.0f, 1.0f)); /* rotation axis */ passmatrixtovertexshader( atrix ); drawmodel(); /* transfored object */ filled transfored object dotted original odel 17
Translace následovaná rotací R.T.[ ] /* set identity to atrix */ gl::at4 atrix = gl::at4(1.0); passmatrixtovertexshader( atrix ); drawmodel(); /* original odel */ atrix =gl::rotate( /* add rotation */ atrix, /* atrix to be odified */ gl::radians(45), /* angle in degrees */ gl::vec3(0.0f, 0.0f, 1.0f)); /* rotation axis */ atrix =gl::translate( /* add translation */ atrix, /* atrix to be odified */ gl::vec3(2.5f, 0.0f, 0.0f)); /* aount of translation */ passmatrixtovertexshader( atrix ); drawmodel(); /* transfored object */ filled transfored object dotted original odel Kód je skoro stejný, jako v předchozí příkladu Zěnilo se pořadí T a R 18
Pohledová transforace w z y x souřadnice okna Modelovací a pohledová transforace odelovací Transforace Pohledová transforace Projekční transforace + Ořezání (clipping) Transforace záběru (Viewport) odelovací souřadnice světové souřadnice souřadnice kaery (oka) noralizované souřadnice zařízení vrchol Perspektivní dělení ořezávácí souřadnice 3D 2D 19
Pohledová transforace - LookAt gl::at4 gl::lookat( gl::vec3 const & eye, /* caera position */ gl::vec3 const & center, /* point on a line of sight */ gl::vec3 const & up ); /* caera up direction */ lookat( ) vytvoří pohledovou atici Kaeru uístí do eye = [eye X, eye Y, eye Z ] center center = [center X, center Y, center Z ] lib. bod ve sěru pohledu up = (up X, up Y, up Z ) sěr nahoru natočení kaery eye 20
Pohledová transforace - LookAt gl::at4 atrix =gl::lookat( ); passmatrixtovertexshader( atrix ); drawmodel(); gl::at4 atrix = gl::lookat( gl::vec3(1.0f, 0.0f, 1.0f), gl::vec3(0.0f, 0.0f, 0.0f), gl::vec3(0.0f, 1.0f, 0.0f) ); gl::at4 atrix = gl::lookat( ); gl::vec3( 1.0f, 1.0f, 0.0f), gl::vec3( 0.0f, 0.0f, 0.0f), gl::vec3(-1.0f, 0.0f, 0.0f) AE4M39 Coputer Graphics gl::at4 atrix = gl::lookat( gl::vec3(-1.0f, -0.5f, 1.0f), gl::vec3( 0.0f, 0.0f, 0.0f), gl::vec3( 0.0f, 1.0f, 0.0f) ); 21
Transforace v OpenGL zěna ěřítka scale v' x', y', z', w' T M.v Lineární složka: rotace (zkosení) rotation (shear) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 x y. z w posunutí translation transforovaný vrchol projekce projection atice pak není afinní vrchol před transforací vertex to be transfored [Sloup] (příští týden) 22
Vytvoření libovolné atice Matici ůžee inicializovat pole 16 hodnot ( 0, 1,..., 15 ) POZOR, z pole se převezou po sloupcích #include <gl/gtc/type_ptr.hpp> /* syetry with respect to xz-plane */ float initvalues[16] = { 1.0, 0.0, 0.0, 0.0, // first colun 0.0, -1.0, 0.0, 0.0, // second colun 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; gl::at4 atrix = gl::ake_at4(initvalues); orig. odel transfored odel passmatrixtovertexshader( atrix ); drawmodel(); 23
Obecná transforace pro zobrazení Cíle je složit ze tří atic správnou atici: M = projection * view * odel Matici předáe do Vertex Shaderu (uložena po sloupcích) Vertex shader provede násobení každého vrcholu 0 4 8 12 x T 1 5 9 13 y v' x', y', z', w' M.v. 2 6 10 14 z 3 7 11 15 w souřadnice k zobrazení na obrazové rovině souřadnice v objektové prostoru 24
Skládání transforací = násobení atic Matice se skládají násobení - přetížený operátor * vynásobí dvě atice M1 a M2 a výsledek uloží do nové atice atrix #include <gl/gtc/type_ptr.hpp> /* syetry with respect to xz-plane */ float initvalues[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; gl::at4 M1 = gl::ake_at4(initvalues); /* syetry - yz-plane */ gl::at4 M2 = gl::at4( gl::vec4(-1.0, 0.0, 0.0, 0.0), gl::vec4(0.0, 1.0, 0.0, 0.0,), gl::vec4(0.0, 0.0, 1.0, 0.0), gl::vec4(0.0, 0.0, 0.0, 1.0) ); gl::at4 atrix = M1 * M2; passmatrixtovertexshader( atrix ); drawmodel(); orig. odel after M1 transfored odel 25
Předání atice do Vertex Shader Ukázka pro předání všech tří atic a násobení vektoru aticei přío na grafické kartě: #version 330 in vec4 position; unifor at4 projection ; unifor at4 view ; unifor at4 odel; // P // E-1, V // O, M void ain() { vec4 worldpos = odel * position; vec4 caerapos = view * worldpos; gl_position = projection * caerapos; } 26
Na straně CPU je se atice nahraje na GPU poocí následujícího kódu projectionmatrixloc = glgetuniforlocation(theprogra, projection ); float ffrustuscale = 1.0f; float fznear = 0.5f; float fzfar = 3.0f; float atrix[16]; eset(atrix, 0, sizeof(float) * 16); atrix[0] = ffrustuscale; atrix[5] = ffrustuscale; atrix[10] = (fzfar + fznear) / (fznear - fzfar); atrix[14] = (2 * fzfar * fznear) / (fznear - fzfar); atrix[11] = -1.0f; gluseprogra(theprogra); gluniformatrix4fv(projectionmatrixloc, 1, GL_FALSE, atrix); gluseprogra(0); 27