Download as pdf or txt
Download as pdf or txt
You are on page 1of 11

Politechnika Świętokrzyska

w Kielcach
Wydział Elektrotechniki, Automatyki i Informatyki

Grafika komputerowa
Podstawy grafiki komputerowej

Instrukcja laboratoryjna 9

„Przekształcenia geometryczne 3D
i obserwator”

Przygotowali:
mgr inż. Paweł Pięta
mgr inż. Daniel Kaczmarski
dr inż. Grzegorz Łukawski

Kielce, 2021
1 Wstęp
Celem zajęć jest omówienie podstawowych przekształceń geometrycznych wykonywa-
nych w przestrzeni trójwymiarowej, które są wykorzystywane w grafice komputerowej,
a następnie wdrożenie tych transformacji w silniku gry.

2 Przekształcenia geometryczne 3D
Notacja macierzowa:

X2 = P ∗ X1
   
x
 1
x
 2
 y1   y2 
   
X1 =   X2 =  
 z1   z2 
   
   
1 1

2.1 Translacja (przesunięcie)


 

1 0 0 tx 
0 0 0 ty 
 
T = 
0 0 0 tz 
 
 
0 0 0 1

2.2 Rotacja (obrót)


Obrót wokół osi X:
 

1 0 0 0
0 cosϕ −sinϕ 0
 
Ox =  
0 sinϕ cosϕ 0
 
 
0 0 0 1
Obrót wokół osi Y:
 

cosϕ 0 −sinϕ 0
 0 1 0 0
 
Oy =  
sinϕ 0 cosϕ 0
 
 
0 0 0 1
Obrót wokół osi Z:
 

cosϕ −sinϕ 0 0
sinϕ cosϕ 0 0
 
Oz = 
 
 0 0 1 0


 
0 0 0 1

2
Obrót względem dowolnej osi można (częściowo) zrealizować przez rozkład na obroty
cząstkowe wokół osi X, Y i Z.

2.3 Jednokładność (skalowanie)


 
S
 x
0 0 0
 0 Sy 0 0
 
J = 
0 0 Sz 0
 
 
0 0 0 1

3 Transformacje w bibliotece GLM


Transformacje realizuje się za pomocą odpowiednich macierzy. Biblioteka GLM do-
starcza szereg funkcji generujących takie macierze:

#include <glm/gtx/transform.hpp>

glm::rotate(kąt_rad, oś_obrotu)

glm::scale(wektor)

glm::translate(wektor)

Każda z powyższych funkcji posiada wersję z macierzą jako argument – kolejne przekształ-
cenie „dokładane” jest (przez mnożenie) do przekazanej macierzy:

glm::rotate(matX, ...)

glm::scale(matX, ...)

glm::translate(matX, ...)

matX -> mat2, mat3 lub mat4

Przeliczenie kąta ze stopni na radiany może zostać wykonane w następujący sposób:

kąt_rad = glm::radians(stopnie)

3.1 Przykłady macierzy transformacji


glm::mat4 MatJ1 = glm::scale(glm::vec3(-0.5f));
glm::mat4 MatJ2 = glm::scale(glm::vec3(-1, 1, -1));
glm::mat4 MatR = glm::rotate(glm::radians(90.0f), glm::vec3(0, 0, 1));
glm::mat4 MatT = glm::translate(glm::vec3(0, 2, 0));

3
3.2 Składanie i realizacja transformacji
Składanie transformacji realizowane jest przez mnożenie macierzy, które odbywa się
z wykorzystaniem przeciążonego operatora *, np.:

glm::mat4 MatX = MatT * MatJ2;

Transformację wierzchołków wykonuje się mnożąc macierz transformacji przez wektor ze


współrzędnymi, np.:

glm::vec4 p1a = MatX * p1;

glm::vec4 p2a = MatJ2 * p2;

glm::vec4 p3a = MatT * p3;

3.3 Przykłady transformacji wierzchołków


// Punkty:
glm::vec4 p1(5, 2, 0, 1), p2(1, 5, 0, 1), p3(1, 2, 0, 1);

// Transformacje:
glm::mat4 MatJ2 = glm::scale(glm::vec3(-1));
glm::mat4 MatT = glm::translate(glm::vec3(0, 2, 0));

// Złożenie transformacji:
glm::mat4 MatX = MatT * MatJ2;

// Transformacja punktów:
glm::vec4 p1a = MatX * p1;
glm::vec4 p2a = MatX * p2;
glm::vec4 p3a = MatX * p3;

// Wyświetlenie:
cout << "P1a: x=" << p1a.x << "y=" << p1a.y << endl;
cout << "P2a: x=" << p2a.x << "y=" << p2a.y << endl;
cout << "P3a: x=" << p3a.x << "y=" << p3a.y << endl;

// Wynik:
P1a: x=5 y=0
P2a: x=-1 y=-3
P3a: x=-1 y=0

4
4 Transformacje przestrzeni w OpenGL
Transformacje przestrzeni to podstawowy mechanizm wykorzystywany w OpenGL do
budowania sceny. Aby ułożyć obiekty (prymitywy) w scenę, należy je odpowiednio „po-
układać”. Zagadnienie to zostało zobrazowane na rysunku 1.

Rysunek 1: Ułożenie obiektów (prymitywów) w scenie 3D

4.1 Macierze transformacji


Do wykonywania transformacji przestrzeni OpenGL wykorzystuje trzy macierze o wy-
miarach 4x4:

• macierz modelu (ang. model matrix) – reprezentuje transformacje obiektu, jego po-
łożenie w przestrzeni 3D i animację ruchu,
• macierz widoku (ang. view matrix) – odpowiada za położenie kamery,
• macierz rzutowania (ang. projection matrix) – odpowiada za rzutowanie sceny trój-
wymiarowej na płaszczyznę ekranu.

Wykonanie transformacji wierzchołka polega na pomnożeniu współrzędnych kolejno przez


wszystkie trzy macierze. W OpenGL w wersji poniżej 3.0 stosowany jest iloczyn macie-
rzy modelu i widoku, który funkcjonuje jako pojedyncza macierz widoku modelu (ang.
modelview matrix). Można ją rozumieć jako przekształcony układ współrzędnych do roz-
mieszczania obiektów. Obiekty zazwyczaj są rysowane w początku układu współrzędnych
(0, 0, 0), jak np. modele z biblioteki GLUT. Aby umieścić obiekt w wymaganym miejscu
sceny, należy przed jego narysowaniem skonstruować odpowiednią macierz przekształce-
nia. Wybór aktywnej macierzy odbywa się natomiast za pomocą funkcji:

glMatrixMode(GLenum mode);

Parametr mode może przyjmować następujące wartości:

• GL_MODELVIEW – iloczyn macierzy widoku i modelu, macierz przeznaczona do „usta-


wiania” elementów sceny z pomocą transformacji oraz ustawienia położenia kamery,
• GL_PROJECTION – macierz rzutowania,

5
• GL_TEXTURE – macierz tekstur,
• GL_COLOR – macierz kolorów.

W OpenGL do bezpośrednich operacji na macierzach wykorzystywane są macierze 4x4


definiowane w kolejności kolumn (ang. column-major order):
 
a
 0
a4 a8 a12 
a1 a5 a9 a13 
 
 
a2 a6 a10 a14 
 
 
a3 a7 a11 a15

Klasa mat4 z biblioteki GLM stosuje dokładnie taką samą konwencję. Pozwala to na
bezpośrednie wygenerowanie macierzy w postaci tabeli i przekazanie jej do OpenGL.
Bezpośrednie operacje na macierzach dotyczą aktywnej macierzy, wybranej przez ostatnie
wywołanie funkcji glMatrixMode():

• glLoadMatrixf(const GLfloat *m); – załadowanie tablicy m jako bieżącą macierz,


• glMultMatrixf(const GLfloat *m); – pomnożenie bieżącej macierzy przez m.

5 Realizacja przekształceń z użyciem biblioteki GLM


Konwersja macierzy typu mat4 na jednowymiarową tablicę, której zawartość jest uło-
żona w kolejności akceptowanej przez OpenGL, może zostać wykonana z zastosowaniem
funkcji value_ptr():

#include <glm/gtc/type_ptr.hpp>
glm::mat4 Mat;
glm::value_ptr(Mat);

5.1 Przykłady przekształceń za pomocą biblioteki GLM


// Aktywacja macierzy widoku modelu:
glMatrixMode(GL_MODELVIEW);

// Macierz translacji:
glm::mat4 MatM = glm::translate(glm::vec3(0, 0, -300));
glLoadMatrixf(glm::value_ptr(MatM));

// Brak transformacji - macierz jednostkowa:


glm::mat4 Identity = glm::mat4(1.0f);
glLoadMatrixf((glm::value_ptr(Identity));

6
// Wersja zwięzła:
glLoadMatrixf(glm::value_ptr(glm::mat4(1.0f)));

6 Położenie obserwatora
Pierwszy sposób polega na pozostawieniu obserwatora w punkcie (0, 0, 0) i odsunięciu
środka sceny na wymaganą odległość. Zagadnienie to zostało zobrazowane na rysunku 2.
W tym przypadku funkcja rysująca rozpoczyna się od translacji wzdłuż osi Z na odległość
rzutowania, np.:

glm::mat4 MatM = glm::translate(glm::vec3(0, 0, -100));

Rysunek 2: Położenie obserwatora – sposób 1

Drugi sposób polega na pozostawieniu środka sceny w punkcie (0, 0, 0) i ustaleniu


położenia obserwatora np. za pomocą funkcji lookAt():

glm::mat4 MatV = glm::lookAt(position, target, up_vector);

gdzie:

• position – pozycja kamery („oka”),


• target – punkt, na który patrzy kamera,
• up_vector – wektor „wyrastający” z głowy obserwatora.

Wszystkie parametry to wektory typu: glm::vec3. Zagadnienie to zostało zobrazowane


na rysunku 3.

7 Transformacje w OpenGL
Sekcja zawiera kilka przykładów przekształceń geometrycznych 3D w OpenGL. Więcej
przykładów transformacji znajduje się w prezentacjach z wykładu.

7
Rysunek 3: Położenie obserwatora – sposób 2

7.1 Przykład 1
Przykład 1 został zobrazowany na rysunku 4.

MatM = translate(MatM, vec3(10, 0, 10));


(1) glLoadMatrixf(value_ptr(MatM));
(1) glColor3f(1, 0, 0);
(2) glutSolidCube(3);
(3) MatM = translate(MatM, vec3(20, 0, 0));
(4) MatM = rotate(MatM, radians(90.0f), vec3(0, 1, 0));
(5) MatM translate MatM vec3(-15, 0, 0));
(5) glLoadMatrixf(value_ptr((MatM));
(5) glColor3f(0, 1, 0);
(6) glutSolidSphere(1, 12, 12);

Rysunek 4: Graficzne przestawienie przykładu 1

8
7.2 Przykład 2
Prosty model Układu Słonecznego, gdzie:

• α – kąt obrotu Ziemi (E) wokół Słońca (S),


• β – kąt obrotu Księżyca (M) wokół Ziemi (E).

Przykład 2 został zobrazowany na rysunku 5.

glColor3f(1, 1, 0);
(1) glutSolidSphere(5, 12, 12);
(2) MatM = rotate(MatM, alfa, vec3(0, 1, 0));
(3) MatM = translate(MatM, vec3(40, 0, 0));
(3) glLoadMatrixf(value_ptr(MatM));
(3) glColor3f(0, 0, 1);
(4) glutSolidSphere(3, 12, 12);
(5) MatM = rotate(MatM, beta, vec3(0, 1, 0));
(6) MatM = translate(MatM, vec3(10, 0, 0));
(6) glLoadMatrixf(value_ptr(MatM));
(6) glColor3f(0.5, 0.5, 0.5);
(7) glutSolidSphere(1, 12, 12);

Rysunek 5: Graficzne przestawienie przykładu 2

9
7.3 Przykład 3
Przykład 3 został zobrazowany na rysunku 6.

// Ustawienie rzutowania perspektywicznego.


glm::perspective<float>(glm::radians(50.0f), (float)w/h, 130, 470);

//Odsunięcie środka sceny od kamery:


glm::mat4 MatM = glm::translate(glm::vec3(0, 0, -300));

// Kąt patrzenia (góra/dół):


MatM = glm::rotate(MatM, glm::radians(lookA), glm::vec3(1, 0, 0));

// Animacja (lewo/prawo):
MatM = glm::rotate(MatM, glm::radians(angle), glm::vec3(0, 1, 0));

// Rotacja o~120 stopni wokół osi Y:


glm::mat4 MatRot120 = glm::rotate(glm::radians(120.0f), glm::vec3(0, 1, 0));

// Translacja +100 na osi X:


glm::mat4 MatTra100 = glm::translate(glm::vec3(100, 0, 0));

//Trzy obiekty krążące wokół punktu centralnego:


glm::mat4 m1 = MatM * MatTra100;
glLoadMatrixf(glm::value_ptr(m1));
glColor3f(0, 1, 0)); glutSolidCube(50); // Zielony sześcian

glm::mat4 m2 = MatM * MatRot120 * MatTra100;


glLoadMatrixf(glm::value_ptr(m2));
glColor3f(1, 1, 0); glutSolidTeapot(40); // Żółty czajnik

glm::mat4 m3 = MatM * MatRot120 * MatRot120 * MatTra100;


glLoadMatrixf(glm::value_ptr(m3));
glColor3f(0, 0, 1); glutSolidSphere(50, 10, 10); // Niebieska sfera

8 Zadania
1. Zaimplementuj klasę reprezentującą obserwatora, która umożliwi łatwe konfiguro-
wanie i zmianę pozycji kamery w scenie 3D.

10
Rysunek 6: Graficzne przestawienie przykładu 3

2. Zaimplementuj hierarchię klas dla obiektów gry analogiczną do tej zaproponowanej


w zadaniach z instrukcji nr 4.

3. Rozszerz funkcjonalność klasy reprezentującej sześcian o możliwość wykonywania


na tym obiekcie transformacji geometrycznych 3D przedstawionych w tej instrukcji.
Wpleć tę klasę w opracowaną hierarchię klas.

4. (Dla chętnych) Zaimplementuj klasę Player reprezentującą gracza. Umożliw ste-


rowanie graczem z użyciem klawiatury i/lub myszy. Wpleć tę klasę w opracowaną
hierarchię klas.

11

You might also like