DIM · 4×4w · point=1, vector=0COMPOSE · non-commutativeEXT OF · R.3, R.17
Dodatek F / Głębiej: Transformacje

Macierze i współrzędne jednorodne

Rozdział 2 rozróżnił punkt od wektora słowami. Rozdział 17 mnożył macierze transformacji, nie mówiąc, co jest w środku. Ten dodatek łączy oba — jedna, elegancka konstrukcja matematyczna robi wszystko naraz.

TL;DR
Pass: w

4×4, nie 3×3: czwarta współrzędna

Rozdział 2 powiedział: translacja przesuwa punkty, ale nie wektory. Żeby jedna macierz obsłużyła obie reguły przez zwykłe mnożenie, rozszerzamy każdy punkt i wektor o czwartą współrzędną w. Punkty dostają w=1, wektory w=0. Kolumna translacji w macierzy mnoży się przez w — dla punktu (w=1) translacja się liczy, dla wektora (w=0) translacja mnoży się przez zero i znika.

4x4.matrix.structureblocks
rotacja / skala (3×3) tx ty tz 0 0 0 1 obraca/skaluje punkty i wektory przesuwa tylko punkty (w=1)
Kolumna translacji (amber) mnoży się przez w — zero dla wektora wyłącza ją automatycznie.
Pass: Kolejność

Składanie: dlaczego kolejność mnożenia ma znaczenie

Mnożenie macierzy nie jest przemienne. „Obróć wokół początku układu, potem przesuń” daje inny wynik niż „przesuń, potem obróć wokół początku układu” — bo w drugim przypadku rotacja zakręca całym już przesuniętym punktem po łuku wokół oryginalnego środka, nie wokół nowej pozycji.

Order.mattersR∘T ≠ T∘R
ROTACJA → TRANSLACJA TRANSLACJA → ROTACJA wynik: (230,160) wynik: (649,234)
Ten sam obrót o 45° i to samo przesunięcie — inna kolejność, inny finalny punkt.

To dosłownie ten sam mechanizm, który stał za wzorem z Rozdziału 17: M_world = M_parent · M_local. Zamiana kolejności czynników przesuwałaby dziecko względem złego układu odniesienia.

Pass: Normalne

Odwrotna transponowana: pułapka nierównomiernego skalowania

Sztuczka z Rozdziału 17 — transformuj promień odwrotną macierzą instancji — ma jeden wyjątek. Normalne (Rozdział 4) transformowane tą samą macierzą co pozycje wychodzą źle, gdy skalowanie nie jest równomierne: kula rozciągnięta w elipsoidę wzdłuż jednej osi ma normalne, które przestają być prostopadłe do nowej powierzchni.

N_world = normalize( (M⁻¹)ᵗ · N_local )odwrotna transponowana, nie sama M — dla samej rotacji (bez skalowania) to i tak wychodzi to samo co M
Non-uniform.scale.normalswrong vs correct
źle: transform. jak pozycja dobrze: odwrotna transponowana
Tylko jedna z dwóch strzałek jest naprawdę prostopadła do rozciągniętej powierzchni — ta licząca się przez (M⁻¹)ᵗ.
Z praktyki

To dlaczego DCC ostrzegają albo automatycznie „Apply Scale” przed pewnymi operacjami po nierównomiernym skalowaniu obiektu — silnik pod maską musi przeliczyć normalne odwrotną transponowaną, a niektóre narzędzia (starsze eksportery, proste shadery) tego nie robią, dając widocznie złe cieniowanie na rozciągniętych modelach.

Słowniczek
Współrzędne jednorodne
Reprezentacja punktu/wektora z dodatkową współrzędną w.
w (czwarta współrzędna)
1 dla punktów, 0 dla wektorów — kontroluje wpływ translacji.
Nieprzemienność mnożenia macierzy
M1·M2 ≠ M2·M1 w ogólnym przypadku.
Odwrotna transponowana
(M⁻¹)ᵗ — właściwa macierz do transformowania normalnych.