Wykład z grafiki komputerowej II (3D)
Jacek Matulewski (e-mail: jacek@fizyka.umk.pl)
http://www.fizyka.umk.pl/~jacek/dydaktyka/3d/
Grafika 3D
Współrzędne jednorodne
Wersja: 15 listopada 2007
Transformacje
Podstawowe pojęcia grafiki 3D:
• Transformacje – określane we współrzędnych sceny 3D
translacja (glTranslatef), obrót (glRotatef)
skalowanie (glScalef), pochylenie
złożenie – dowolna macierz 4x4 (glMultMatrixf)
• Transformacje muszą być ustalone
przed narysowaniem wierzchołka, np..:
glRotatef(45.0f, 0.0f, 1.0f, 0.0f); //kąt, kierunek osi
glVertex3f(…);
Transformacje
• 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)
Transformacje
• We współrzędnych kartezjańskich (2D)
obrót i translacja mogą być zapisane:
oxy x0 t x oxx x0 o yx y0 t x
o yy y0 t y o yx x0 o yy y0 t y
x0 oxx
x
ˆ
y O y T o
0
yx
• We współrzędnych jednorodnych:
x
x0 oxx
y H y o
0 yx
1
1 0
oxy
o yy
0
t x x0 oxx x0 o yx y0 t x
t y y0 o yx x0 o yy y0 t y
1 1
1
Macierze w C++
• Należy pamiętać, że macierze w C++ zapisywane są
kolumnami (M[nr kolumny+rozmiar*nr wiersza])
• Oznacza to, że macierz 0 4 8 C
1 5 9 D
2 6 A E
3 7 B F
możemy zadeklarować instrukcją
float I[16]={0,
1, 2,
I[4][4]={{0,
1, 3,
2, 3},
4,{4,
5, 5,
6, 6,
7, 7},
8,{8,
9, A,
B, B},
9, A,
C,{C,
D,D,
E, E,
F};F}};
W OpenGL
macierze 1D
Macierze w C++
• Jeżeli chcemy ułatwić sobie życie, możemy
zdefiniować funkcję wykonującą transpozycję:
0 1 2 3
0
4 5 6 7
1
8 9 A B
2
C
D
E
F
3
C
5 9 D
6 A E
7 B F
4
8
Macierze w C++
float* Transpozycja(float* M,int rozmiar=4)
{
for(int kolumna=0;kolumna<rozmiar;++kolumna)
for(int wiersz=kolumna+1;wiersz<rozmiar;++wiersz)
{
float tmp=M[kolumna+rozmiar*wiersz];
M[kolumna+rozmiar*wiersz]=M[wiersz+rozmiar*kolumna];
M[wiersz+rozmiar*kolumna]=tmp;
}
return M;
}
Funkcja glMultMatrix
Funkcja OpenGL glMultMatrixf wykonuje mnożenie
bieżącej macierzy M (np. model-widok) przez macierz H
podaną w argumencie tj. M → M·H (postmultiplication)
Przykład użycia – mnożenie przez macierz jednostkową
1
0
0
0
0 0 0
1 0 0
0 1 0
0 0 1
W szablonie zmiany wprowadzać
w funkcji TForm1::RysujScene
przed rysowaniem figury
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float I[16]={1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1};
glMultMatrixf(Transpozycja(I));
Funkcja glMultMatrix
Efekt mnożenia przez macierz I: żadnych zmian
Skalowanie
Macierz skalowania we współrzędnych jednorodnych
sx
0
0
0
0
0
sy
0
0
sz
0
0
0
0
0
1
glScalef(0.5,1,2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float S[16]={0.5,0,0,0,
0,1,0,0,
0,0,2,0,
0,0,0,1};
glMultMatrixf(Transpozycja(S));
Skalowanie
Macierz skalowania jednorodnego we wszystkich kier.
1
0
0
0
0
1 0 0
0 1 0
0 0 1/ s
0 0
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float S[16]={1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,2};
glMultMatrixf(Transpozycja(S));
Obrót
Macierz obrotu we współrzędnych jednorodnych
rozkładana jest na obroty wokół osi (kąty Eulera):
cos
sin
0
0
sin
0 0 Obrót o kąt wokół osi Z
0 0
1 0
0 1
cos
0
1
0 cos
0 sin
0
0
0
0
0
sin
cos
0
Obrót wokół osi X
0
0
0
1
cos
0
sin
0
kąt
0 0°sin
cos
01
130° 0
0
0.8660
045°cos 0.7071
0
060° 0
10.5
90° osi Y
Obrót wokół
0
sin
0
0.5
0.7071
0.8660
1
Obrót
Obrót wokół osi Z o kąt 45°
0.7071 0.7071
0.7071
0.7071
0
0
0
0
0 0
0 0
1 0
0 1
glRotatef(45,0,0,1);
float
Rz[16]={0.7071,-0.7071,0,0,
0.7071, 0.7071,0,0,
0,0,1,0,
0,0,0,1};
glMultMatrixf(Transpozycja(Rz));
Obrót
Obrót wokół osi X o kąt :
0
1
0 cos
0 sin
0
0
0
sin
cos
0
0
0
0
1
#include <math.h>
float
constconst
float a=20;
a=20;
float
glRotatef(a,1,0,0);
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));
Pochylenie
• Macierz pochylenia (ang. skew)
• Elementy pozadiagonalne
• Nie ma odpowiednika w funkcjach OpenGL
1 1 00
0.2
0.2 11
0 0 0.4
0
0 0 00
0 0
0 0
1 0
0 1
Translacja
• Macierz translacji we współrzędnych jednorodnych
1
0
0
0
0 0 1t x.5
1 0 t0y.5
0 1 t z1
0 0 11
glTranslatef(1.5,0.5,1);
float
T[16]={1,0,0,1.5,
0,1,0,0.5,
0,0,1,1,
0,0,0,1};
glMultMatrixf(Transpozycja(T));
Składanie transformacji
• Złożenie translacji w kier. X i obrotu wokół osi Z
cos
sin
0
0
sin
cos
0
0
0 t0xcos
1 0
0 1
0 0t xsin
1 0 00 0
0 1 10 0
0 tx
0 0
1 0
0 1
• Złożenie translacji w kier. X i obrotu wokół osi Z
cos 0
1
0sin 1
0 0 0
0 0 0
0 sint x cos
0 t x sin
0cos0 sin
0 0 cos
1 00 1 0 0 0
0 01 0 0 1 0
0 0
0 0
1 0
0 1
Obrót wokół wyznaczonego punktu
Obrót o 45° w płaszczyźnie XY wokół punktu (2,0,0):
1) Translacja o wektor [2,0,0]
2) Obrót wokół osi Z o 45°
3) Przesunięcie o wektor [-2,0,0]
glTranslatef(2,0,0);
glRotatef(45,0,0,1);
glTranslatef(-2,0,0);
Obrót wokół wyznaczonego punktu
Obrót o 45° w płaszczyźnie XY wokół punktu (2,0,0):
1) Translacja o wektor [2,0,0]
2) Obrót wokół osi Z o 45°
3) Przesunięcie o wektor [-2,0,0]
1
0
0
0
0 0 t x cos
cos sin
sin
1 0 0 sin
sin cos
cos
0 1 0 00
00
0 0 1 00
00
00 t0x (1 1cos0 )0 t x
00 00 t x 0sin 1 0 0
11 00 0 0 1 0
00 11 0
1 0 0 1
Rzutowania
• Rzutowanie równoległe na płaszczyznę XY (glOrtho)
1
0
0
0
0 0 0 x x
1 0 0 y y
0 0 0 z 0
0 0 1 1 1
• Rzutowanie perspektywiczne (glFrustum)
1
0
0
0
0
0
1
0
0
0
0 1d
0
0
0
0