Współrzędne jednorodne Kurs ITA-106 (Grafika i multimedia) – Współrzędne jednorodne Jacek Matulewski (e-mail: jacek@fizyka.umk.pl) http://www.fizyka.umk.pl/~jacek/dydaktyka/3d/ XNA Współrzędne jednorodne Wersja: 30 stycznia 2009
Transformacje Podstawowe pojęcia grafiki 3D: Transformacje – określane we współrzędnych sceny 3D translacja (Matrix.CreateTranslation, macierz 4x4!), obrót (Matrix.CreateRotationXYZ, z osi obrotu i kąta, yaw+pitch+roll, klasa Quaternion) skalowanie (Matrix.CreateScale), pochylenie złożenie – dowolna macierz 4x4 (Matrix.Multiply) Rozdzielenie macierzy świata i widoku (wygoda!) Transformacje są wykonywane „od końca” (post-multiplication)
Historia i zalety Współrzędne jednorodne (homogenous coordinates) Wprowadzone w 1946 przez E. Maxwella (rzutowanie) W 1965 L. Roberts użył ich do zunifikowania zapisu wszystkich transformacji: translacji, obrotów, skalowanie i pochylania Opis punktów n-wymiarowej przestrzeni za pomocą n+1 współrzędnych Obcinanie we współrzędnych jednorodnych może odbywać się w sześcianie zamiast w ściętym ostrosłupie (znacznie efektywniejsze numerycznie)
Macierz translacji? We współrzędnych kartezjańskich (2D) obrót i translacja mogą być zapisane: We współrzędnych jednorodnych:
Macierze w XNA Konstruktor klasy Matrix przyjmuje elementy kolumnami (m11, m12, m13, m14, m21, m22, …,m44) Oznacza to, że macierz możemy zadeklarować instrukcją Matrix macierz = new Matrix(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F);
Macierze w XNA Jeżeli chcemy ułatwić sobie życie, możemy użyć metody wykonującej transpozycję: Matrix macierz = Matrix.Identity; macierz = Matrix.Transpose(macierz);
Metoda Matrix.Multiply Metoda Matrix.Multiply (i operator *) wykonuje mnożenie macierzy (np. macierzy świata) przez macierz podaną w argumencie tj. M → M·H (postmultiplication) Przykład użycia – mnożenie przez macierz jednostkową Matrix macierz = new Matrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); macierz = Matrix.Transpose(macierz); efekt.World *= macierz; efekt.World = efekt.World * macierz; efekt.World = Matrix.Multiply( efekt.World, macierz); W szablonie zmiany wprowadzać w funkcji Game1.Initialize (przed rysowaniem figury)
Funkcja glMultMatrix Efekt mnożenia przez macierz I: żadnych zmian
Skalowanie Macierz skalowania we współrzędnych jednorodnych efekt.World = Matrix.Identity; Matrix m..rz = new Matrix(0.5f, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); macierz = Matrix.Transpose(macierz); efekt.World *= macierz;
Skalowanie Macierz skalowania jednorodnego we wszystkich kier. efekt.World = Matrix.Identity; Matrix macierz = new Matrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2); macierz = Matrix.Transpose(macierz); efekt.World *= macierz;
Odbicie Odbicie = „ujemne skalowanie” efekt.World = Matrix.Identity; Matrix macierz = new Matrix(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); macierz = Matrix.Transpose(macierz); efekt.World *= macierz;
Obrót Macierz obrotu we współrzędnych jednorodnych rozkładana jest na obroty wokół osi (kąty Eulera): Obrót o kąt g wokół osi Z kąt a cos a sin a 0° 1 30° 0.8660 0.5 45° 0.7071 60° 90° Obrót wokół osi X Obrót wokół osi Y
Obrót Obrót wokół osi Z o kąt 45° macierz = Matrix.CreateRotationZ(MathHelper.PiOver4); Matrix macierz = new Matrix( 0.7071f, -0.7071f, 0, 0, 0.7071f, 0.7071f, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); macierz = Matrix.Transpose(macierz);
Obrót Obrót wokół osi X o kąt a: OpenGL float const a=-30; float const ar=a*M_PI/180.0f; float Rx[16]= {1,0,0,0, 0,cos(ar),-sin(ar),0, 0,sin(ar),cos(ar),0, 0,0,0,1}; glMultMatrixf(Transpozycja(Rx)); OpenGL: glRotatef(30,1,0,0); #include <math.h>
Obrót Obrót wokół osi X o kąt a: OpenGL: glRotatef(-30,1,0,0); XNA: Matrix.CreateFromAxisAngle( Vector3.UnitX, MathHelper.ToRadians(-30)); Matrix.CreateRotationX(MathHelper.ToRadians(-30));
Obrót Obrót wokół osi X o kąt a: float a = MathHelper.ToRadians(30); float cosa = (float)Math.Cos(a); float sina = (float)Math.Sin(a); Matrix macierz = new Matrix( 1, 0, 0, 0, 0, cosa, -sina, 0, 0, sina, cosa, 0, 0, 0, 0, 1); macierz = Matrix.Transpose(macierz);
Pochylenie Macierz pochylenia (ang. skew) Elementy pozadiagonalne Nie ma odpowiednika w metodach klasy Matrix
Translacja Macierz translacji we współrzędnych jednorodnych macierz = Matrix.CreateTranslation(1, 0.5f, 0.25f); macierz = new Matrix(1, 0, 0, 1, 0, 1, 0, 0.5f, 0, 0, 1, 0.25f, 0, 0, 0, 1); macierz = Matrix.Transpose(macierz);
Składanie transformacji Złożenie translacji w kier. X i obrotu wokół osi Z Złożenie translacji w kier. X i obrotu wokół osi Z
Obrót wokół wyznaczonego punktu Obrót o 45° w płaszczyźnie XY wokół punktu (2,0,0): Translacja o wektor [2,0,0] 2) Obrót wokół osi Z o 45° 3) Przesunięcie o wektor [-2,0,0]
Obrót wokół wyznaczonego punktu Obrót o 45° w płaszczyźnie XY wokół punktu (2,0,0): Translacja o wektor [2,0,0] macierz *= Matrix.CreateTranslation(2,0,0); 2) Obrót wokół osi Z o 45° macierz *= Matrix.CreateRotationZ(MathHelper.PiOver4); 3) Przesunięcie o wektor [-2,0,0] macierz *= Matrix.CreateTranslation(-2, 0, 0); Matrix macierz = Matrix.Identity; Należy pamiętać o odwrotnej kolejności transformacji!
Obrót wokół wyznaczonego punktu Obrót o 45° w płaszczyźnie XY wokół punktu (2,0,0): Translacja o wektor [2,0,0] 2) Obrót wokół osi Z o 45° 3) Przesunięcie o wektor [-2,0,0]
Rzutowania Rzutowanie równoległe na płaszczyznę XY (Matrix.CreateOrthographic) Rzutowanie perspektywiczne (Matrix.CreatePerspective)