Odpowiedzi:
Tak, możesz dodać wektor w przypadku tłumaczenia. Powód użycia macierzy sprowadza się do jednolitego sposobu obsługi różnych połączonych transformacji.
Na przykład obrót jest zwykle wykonywany przy użyciu macierzy (sprawdź komentarz @MickLH, aby poznać inne sposoby radzenia sobie z obrotami), więc aby poradzić sobie z wieloma transformacjami (obrót / tłumaczenie / skalowanie / rzutowanie ... itd.) W jednolity sposób musisz zakodować je w matrycy.
Mówiąc bardziej technicznie; transformacja odwzorowuje punkt / wektor na inny punkt / wektor.
p` = T(p);
gdzie p` jest punktem transformacji, a T (p) jest funkcją transformacji.
Ponieważ nie używamy macierzy, musimy to zrobić, aby połączyć wiele transformacji:
p1 = T (p);
p końcowy = M (p1);
Macierz może nie tylko łączyć wiele rodzajów transformacji w jedną macierz (np. Afiniczną, liniową, rzutową).
Zastosowanie macierzy daje nam możliwość łączenia łańcuchów transformacji, a następnie ich mnożenia. To oszczędza nam mnóstwo cykli zwykle przez GPU (dzięki @ChristianRau za wskazanie tego).
T końcowy = T * R * P; // tłumacz obróć projekt
p końcowy = T końcowy * p;
Warto również zauważyć, że procesory graficzne, a nawet niektóre procesory są zoptymalizowane do operacji wektorowych; Procesory wykorzystujące SIMD i GPU są projektowanymi równolegle procesorami sterowanymi danymi, więc użycie macierzy idealnie pasuje do przyspieszenia sprzętowego (w rzeczywistości GPU zostały zaprojektowane tak, aby pasowały do operacji macierz / wektor).
Jeśli wszystko, co kiedykolwiek zrobisz, to poruszaj się wzdłuż jednej osi i nigdy nie stosuj żadnej innej transformacji, to sugerujesz, że jest w porządku.
Prawdziwą mocą korzystania z macierzy jest to, że można łatwo połączyć szereg złożonych operacji razem i zastosować tę samą serię operacji do wielu obiektów.
Większość przypadków nie jest tak prosta i jeśli najpierw obrócisz obiekt i chcesz przekształcić wzdłuż jego osi lokalnych zamiast osi świata, przekonasz się, że nie możesz po prostu dodać 10 do jednej z liczb i sprawić, by działała poprawnie .
Aby zwięźle odpowiedzieć na pytanie „dlaczego”, to dlatego, że macierz 4x4 może jednocześnie opisywać operacje obracania, translacji i skalowania. Możliwość spójnego opisania któregokolwiek z nich upraszcza wiele rzeczy.
Różne rodzaje transformacji można prościej przedstawić za pomocą różnych operacji matematycznych. Jak zauważyłeś, tłumaczenie można wykonać po prostu przez dodanie. Jednolite skalowanie przez pomnożenie przez skalar. Ale odpowiednio spreparowana matryca 4x4 może zrobić wszystko. Używanie 4x4 konsekwentnie upraszcza kod i interfejsy. Płacisz trochę za zrozumienie tych 4x4, ale dzięki temu wiele rzeczy staje się łatwiejszych i szybszych.
powodem zastosowania macierzy 4x4 jest to, że operacja jest transformacją liniową . jest to przykład jednorodnych współrzędnych . To samo dzieje się w przypadku 2d (przy użyciu matrycy 3x3). Powodem użycia jednorodnych współrzędnych jest to, że wszystkie 3 geometryczne formacje tansformacji można wykonać za pomocą jednej operacji; w przeciwnym razie należałoby wykonać mnożenie macierzy 3x3 i dodanie macierzy 3x3 (do tłumaczenia). ten link z cegprakash jest przydatny.
Tłumaczenia nie mogą być reprezentowane przez matryce 3D
Prostym argumentem jest to, że tłumaczenie może przyjąć wektor pochodzenia:
0
0
0
od miejsca pochodzenia powiedz x = 1
:
1
0
0
Wymagałoby to jednak takiej matrycy, aby:
| a b c | |0| |1|
| d e f | * |0| = |0|
| g h i | |0| |0|
Ale to niemożliwe.
Kolejnym argumentem jest twierdzenie o dekompozycji liczby pojedynczej , które mówi, że każda macierz może być złożona z dwóch operacji obrotu i jednej operacji skalowania. Brak tłumaczeń.
Dlaczego można stosować matryce?
Wiele modelowanych obiektów (np. Podwozie samochodu) lub część modelowanych obiektów (np. Opona samochodowa, koło napędowe) to bryły: odległości między wierzchołkami nigdy się nie zmieniają.
Jedyne transformacje, które chcemy na nich wykonać, to rotacje i tłumaczenia.
Mnożenie macierzy może kodować zarówno rotacje, jak i tłumaczenia.
Macierze obrotu mają wyraźne wzory, np .: macierz obrotu 2D dla kąta a
ma postać:
cos(a) -sin(a)
sin(a) cos(a)
Istnieją analogiczne formuły dla 3D , ale zauważ, że obroty 3D przyjmują 3 parametry zamiast tylko 1 .
Tłumaczenia są mniej trywialne i zostaną omówione później. To jest powód, dla którego potrzebujemy matryc 4D.
Dlaczego fajnie jest używać matryc?
Ponieważ skład wielu macierzy można wstępnie obliczyć przez pomnożenie macierzy .
Na przykład, jeśli mamy przetłumaczyć tysiąc wektorów v
naszego podwozia samochodu za pomocą matrycy, T
a następnie obrócić za pomocą matrycy R
, zamiast robić:
v2 = T * v
i wtedy:
v3 = R * v2
dla każdego wektora możemy wstępnie obliczyć:
RT = R * T
a następnie wykonaj tylko jedno pomnożenie dla każdego wierzchołka:
v3 = RT * v
Jeszcze lepiej: jeśli chcemy następnie umieścić wierzchołki opony i koła napędowego względem samochodu, wystarczy pomnożyć poprzednią macierz RT
przez macierz względem samego samochodu.
To oczywiście prowadzi do utrzymania stosu macierzy:
Jak dodanie jednego wymiaru rozwiązuje problem
Rozważmy przypadek od 1D do 2D, który jest łatwiejszy do wizualizacji.
Matryca w 1D to tylko jedna liczba, a jak widzieliśmy w 3D, nie można wykonać tłumaczenia, tylko skalowanie ..
Ale jeśli dodamy dodatkowy wymiar jako:
| 1 dx | * |x| = | x + dx |
| 0 1 | |1| | 1 |
i wtedy zapominamy o nowym dodatkowym wymiarze, otrzymujemy:
x + dx
tak jak chcieliśmy.
Ta transformacja 2D jest tak ważna, że ma nazwę: transformacja ścinająca .
Fajnie jest wizualizować tę transformację:
Zwróć uwagę, jak każda pozioma linia (stała y
) jest po prostu tłumaczona.
Tak się złożyło, że wzięliśmy tę linię y = 1
za naszą nową linię 1D i przetłumaczyliśmy ją za pomocą macierzy 2D.
Rzeczy są analogiczne w 3D, z matrycami ścinającymi 4D w formie:
| 1 0 0 dx | | x | | x + dx |
| 0 1 0 dy | * | y | = | y + dy |
| 0 0 1 dz | | z | | z + dz |
| 0 0 0 1 | | 1 | | 1 |
A nasze stare obroty / skalowanie 3D mają teraz formę:
| a b c 0 |
| d e f 0 |
| g h i 0 |
| 0 0 0 1 |
Ten samouczek wideo Jamie King jest również wart obejrzenia.
Przestrzeń afiniczna
Przestrzeń afiniczna to przestrzeń generowana przez wszystkie nasze transformacje liniowe 3D (multiplikacje macierzy) wraz ze ścinaniem 4D (tłumaczenia 3D).
Jeśli pomnożymy macierz ścinania i transformację liniową 3D, zawsze otrzymamy coś z formy:
| a b c dx |
| d e f dy |
| g h i dz |
| 0 0 0 1 |
Jest to najbardziej ogólna możliwa transformacja afiniczna, która wykonuje obrót / skalowanie 3D i translację.
Jedną ważną właściwością jest to, że jeśli pomnożymy 2 macierze afiniczne:
| a b c dx | | a2 b2 c2 dx2 |
| d e f dy | * | d2 e2 f2 dy2 |
| g h i dz | | g2 h2 i2 dz2 |
| 0 0 0 1 | | 0 0 0 1 |
my zawsze dostać inny pokrewieństwa macierzy postaci:
| a3 b3 c3 (dx + dx2) |
| d3 e3 f3 (dy + dy2) |
| g3 h3 i3 (dz + dz2) |
| 0 0 0 1 |
Matematycy nazywają to zamknięcie własności i jest wymagane do zdefiniowania przestrzeni.
Dla nas oznacza to, że możemy nadal wykonywać multiplikacje macierzy w celu szczęśliwego obliczania ostatecznych transformacji, dlatego właśnie używamy używanych macierzy, bez uzyskiwania bardziej ogólnych transformacji liniowych 4D, które nie są afiniczne.
Projekcja Frustum
Ale czekaj, jest jeszcze jedna ważna transformacja, którą wykonujemy cały czas: glFrustum
która sprawia, że obiekt jest 2x bardziej widoczny, wydaje się 2x mniejszy.
Najpierw uzyskaj intuicję na temat glOrtho
vs glFrustum
pod adresem : https://stackoverflow.com/questions/2571402/explain-the-usage-of-glortho/36046924#36046924
glOrtho
można to zrobić tylko za pomocą tłumaczeń + skalowania, ale jak możemy zaimplementować glFrustum
macierze?
Przypuszczam, że:
z = -1
kwadrat o długości 2z = -2
Gdybyśmy tylko dopuścili bardziej ogólne 4-wektory typu:
(x, y, z, w)
z w != 0
, a ponadto identyfikujemy każdy (x, y, z, w)
z (x/w, y/w, z/w, 1)
, wtedy transformacja frustum z macierzą byłaby:
| 1 0 0 0 | | x | | x | | x / -z |
| 0 1 0 0 | * | y | = | y | identified to | y / -z |
| 0 0 1 0 | | z | | z | | -1 |
| 0 0 -1 0 | | w | | -z | | 0 |
Jeśli wyrzucimy z
i w
na końcu otrzymamy:
x_proj = x / -z
y_proj = y / -z
dokładnie tego chcieliśmy! Możemy to zweryfikować dla niektórych wartości, np .:
z == -1
dokładnie w samolocie, na który rzutujemy, x_proj == x
i y_proj == y
.z == -2
, to x_proj = x/2
: obiekty są o połowę mniejsze.Zwróć uwagę, że glFrustum
transformacja nie ma formy afinicznej: nie można jej zrealizować tylko za pomocą rotacji i tłumaczeń.
Matematyczna „sztuczka” polegająca na dodawaniu w
i dzieleniu przez nią nazywana jest współrzędnymi jednorodnymi
Zobacz także: powiązane pytanie dotyczące przepełnienia stosu: https://stackoverflow.com/questions/2465116/understanding-opengl-matrices
Obejrzyj ten film, aby zrozumieć pojęcia modelu, widoku i projekcji.
Matryce 4x4 służą nie tylko do tłumaczenia obiektu 3D. Ale także do różnych innych celów.
Zobacz to , aby zrozumieć, w jaki sposób wierzchołki na świecie są reprezentowane 4D matryce i jak są one przekształcane.