fi-notes/src/content/docs/szmgr/SZP08_modelovani_a_projekce.md

17 KiB

title description
Modelování a projekce A guide in my new Starlight docs site.

Note

Homogenní souřadnice, modelovací, pohledová a projekční matice, perspektivní a ortografická projekce. Základní afinní transformace.

PV189, PV112

Souřadnicové systémy

  • Right-hand rule Mnemotechnická pomůcka pro určení orientace os v kartézské soustavě souřadnic. Taky se používá pro určení směru vektorového součinu.

    Right-hand rule

    Tip

    Osa X je dána ukazováčkem, osa Y prostředníčkem, osa Z palcem. Pokud Y míří nahoru, pak ano, člověk si u toho může vykroutit ruku, ale alespoň si to zapamatuje.

  • Kartézská soustava souřadnic Right-handed systém definován třemi kolmými osami. Ve 2D jsou to x a y. Ve 3D jsou to x, y a z. Jsou na sebe v zájemně kolmé. Počátek je v bodě, kde se protínají všechny osy, označovaném jako 0.

  • Homogenní souřadnice Hack, kdy reprezentujeme souřadnici v 3D prostoru pomocí 4 čísel, abychom mohli zapsat translaci pomocí matice. Využívá se v projektivní geometrii, pro projekci 3D scén na 2D plochu.

    Převod z kartézských na homogenní souřadnice: (x, y, z) \to (x, y, z, 1).

    Převod z homogenních na kartézské souřadnice: (x, y, z, w) \to (\frac{x}{w}, \frac{y}{w}, \frac{z}{w}).

    Body, kde w = 0 jsou body v nekonečnu. Využívá se pro popis pohybu k nekonečnu, který se v kartézských souřadnicích nedá popsat.

MVP matice

Important

Pro implementaci v OpenGL viz Renderování s využitím GPU.

Warning

Při zápisu matic bacha na to, jestli jsou row-major nebo column-major. Třeba v OpenGL to znamená, že se všechny matice píší v transponované podobě, jelikož OpenGL je column-major a v takovém pořádí jsou i parametery mat2, mat3 a mat4 V GLSL.

  • Modelovací matice $M$ Převádí souřadnice z prostoru objektu (local space) do prostoru světa (world space). Využívá se pro rotaci (R), škálování (S) a translaci (T) objektu.

    M = T \cdot R \cdot S
    
  • Pohledová matice / view matrix $V$
    Převádí souřadnice z prostoru světa (world space) do prostoru před kamerou (camera space). Otáčí světem, aby kamera byla jeho středem.1

    V = \begin{bmatrix}
        \color{red}{R_x} & \color{red}{R_y} & \color{red}{R_z} & 0 \\
        \color{green}{U_x} & \color{green}{U_y} & \color{green}{U_z} & 0 \\
        \color{blue}{D_x} & \color{blue}{D_y} & \color{blue}{D_z} & 0 \\
        0 & 0 & 0  & 1
    \end{bmatrix}
    \cdot
    \begin{bmatrix}
        1 & 0 & 0 & -\color{purple}{P_x} \\
        0 & 1 & 0 & -\color{purple}{P_y} \\
        0 & 0 & 1 & -\color{purple}{P_z} \\
        0 & 0 & 0  & 1
    \end{bmatrix}
    

    kde:

    • \color{red}{R} je vektor, který ukazuje doprava od kamery.

    • \color{green}{U} je vektor, který ukazuje nahoru od kamery.

    • \color{blue}{D} je vektor, který ukazuje dopředu od kamery.

    • \color{purple}{P} je pozice kamery.

      Note

      Všimni si, že levá matice je transponovaná a poziční vektor v pravé matici je negovaný. Je to proto, že otáčíme a posouváme celým světem tak, aby kamera byla v počátku, musíme proto provést inverzní operace vůči těm, které chceme provést s kamerou. 1

  • Frustum Část 3D tělesa (nejčastěji pyramidy nebo jehlanu) mezi dvěma rovnoběžnými rovinami. Doslovný překlad je "komolý jehlan"

  • Projekční matice / projection matrix $P$ Převádí souřadnice z prostoru před kamerou (camera space) do clip space.

    Používá se zejména ortografická projekce (P_\text{ortho}) a perspektivní projekce (P_\text{persp}).

  • MVP matice Pro převod modelu z jeho lokálního prostoru do clip space použijeme:

    \vec{v}_\text{clip} = P \cdot V \cdot M \cdot \vec{v}_\text{local}
    

Projekce

Ortografická projekce

Používáme především k vykreslení 2D scén. Osu Z můžeme využít, abychom jeden sprite schovali za jiný. Nicméně objekty dál od kamery jsou stejně velké jako ty blízko kamery. 1

width=500

Je dána 6 parametry:

  • \text{left} - levá hranice (X),
  • \text{right} - pravá hranice (X),
  • \text{bottom} - spodní hranice (Y),
  • \text{top} - horní hranice (Y),
  • \text{near} - blízká hranice (Z),
  • \text{far} - daleká hranice (Z).

Společně definují boxík, kde je (\text{left}, \text{bottom}, -\text{near}) levý spodní roh a (\text{right}, \text{top}, -\text{far}) pravý horní roh. Úkolem matice P_\text{ortho} je nasoukat tento boxík do krychle (-1, -1, -1) \to (1, 1, 1) (a navíc flipnou Z, protože OpenGL mění handedness).

\begin{aligned}

P_\text{ortho} &= C \cdot S \cdot T \\

&=

\begin{bmatrix}
    1 & 0 & 0 & 0 \\
    0 & 1 & 0 & 0 \\
    0 & 0 & -1 & 0 \\
    0 & 0 & 0 & 1 \\
\end{bmatrix}
\cdot
\begin{bmatrix}
    \frac{2}{\text{right-left}} & 0 & 0 & 0 \\
    0 & \frac{2}{\text{top-bottom}} & 0 & 0 \\
    0 & 0 & \frac{2}{\text{far-near}} & 0 \\
    0 & 0 & 0 & 1 \\
\end{bmatrix}
\cdot
\begin{bmatrix}
    1 & 0 & 0 & -\frac{\text{right+left}}{2} \\
    0 & 1 & 0 & -\frac{\text{top+bottom}}{2} \\
    0 & 0 & 1 & -\frac{\text{far+near}}{2} \\
    0 & 0 & 0 & 1 \\
\end{bmatrix} \\
&=

\begin{bmatrix}
    \frac{2}{\text{right}-\text{left}} & 0 & 0 & -\frac{\text{right}+\text{left}}{\text{right}-\text{left}} \\
    0 & \frac{2}{\text{top}-\text{bottom}} & 0 & -\frac{\text{top}+\text{bottom}}{\text{top}-\text{bottom}} \\
    0 & 0 & -\frac{2}{\text{far}-\text{near}} & -\frac{\text{far}+\text{near}}{\text{far}-\text{near}} \\
    0 & 0 & 0 & 1 \\
\end{bmatrix}

\end{aligned}

kde:

  • C obrací osu Z, kvůli přechodu z right-handed do left-handed (týká se OpenGL 2),
  • S definuje velikost kvádru, který se vleze do clip space,
  • T posouvá počátek doprostřed kvádru.

Perspektivní projekce

Zmenšuje objekty, které jsou dále od kamery. 1

width=500

Je definována 4 parametry:

  • \text{FOV}_y - field of view (úhel zorného pole) v ose Y,
  • \text{aspect} - poměr šířky a výšky okna,
  • \text{near} - blízká hranice,
  • \text{far} - daleká hranice.

V matici P_\text{persp} se vyskytují následující mezihodnoty:

  • \text{top} = \text{near} \cdot \tan \left( \frac{\text{FOV}_y}{2} \right),

  • \text{bottom} = -\text{top},

  • \text{right} = \text{top} \cdot \text{aspect},

  • \text{left} = -\text{right}.

  • Translace frustumu Posouváme špičku frustumu do počátku souřadného systému. 3

    T =
    \begin{bmatrix}
        1 & 0 & 0 & -\frac{\text{left} + \text{right}}{2} \\
        0 & 1 & 0 & -\frac{\text{bottom} + \text{top}}{2} \\
        0 & 0 & 1 & 0 \\
        0 & 0 & 0 & 1 \\
    \end{bmatrix}
    

    Note

    Všimni si, že. Pokud používáme 4-parametrickou verzi, tak je to matice identity a tím pádem není potřeba.

  • Perspective divide Objekty blíže k rovině \text{near} budou větší než objekty dále. Rovina \text{near} reprezentuje plochu obrazovky, na kterou jsou všechny body promítány.

    Perspective divide 3

    width=500

    V obrázku výše je bod (x, y, z) promítnut na rovinu \text{near} jako (x', y', near). Vznikají tak dva trojúhelníky, které jsou si sobě podobné a proto mají stejné poměry stran. Platí tedy \frac{y'}{\text{near}} = \frac{y}{z}. Pak y' = \frac{y \cdot \text{near}}{z}. Chceme tedy, aby platilo:

    \begin{aligned}
        x' = \frac{x \cdot \text{near}}{z} \\
        y' = \frac{y \cdot \text{near}}{z}
    \end{aligned}
    

    Což můžeme vyjádřit v homogenních souřadnicích vyjadřít dělením w jako:

    D = \begin{bmatrix}
        \text{near} & 0 & 0 & 0 \\
        0 & \text{near} & 0 & 0 \\
        0 & 0 & 1 & 0 \\
        0 & 0 & \color{red}{-1} & \color{red}{0} \\
    \end{bmatrix}
    
  • Velikost okna Šířka a výška okna dána pomocí \text{left}, \text{right}, \text{bottom}, \text{top} se musí vlézt do intervalu (-1.0, 1.0), proto je potřeba provést škálování:

    S = \begin{bmatrix}
        \frac{2}{\text{right} - \text{left}} & 0 & 0 & 0 \\
        0 & \frac{2}{\text{top} - \text{bottom}} & 0 & 0 \\
        0 & 0 & 1 & 0 \\
        0 & 0 & 0 & 1 \\
    \end{bmatrix}
    
  • Přemapování hloubky Chceme zachovat tu schopnost souřadnice z nám říct, že něco je před něčím jiným. Potřebujeme proto přemapovat interval (-\text{near}, -\text{far}) na (-1.0, 1.0). Jelikož desetinná čísla mají tendenci vytvářet artefakty, chceme aby toto mapování bylo nelineární tak, aby bylo přesnější blíže \text{near}. Použijeme \frac{c_1}{-z} + c_2, kde c_1 a c_2 jsou konstanty zvoleny pomocí:

    Note

    Interval (-\text{near}, -\text{far}) obsahuje negace, neboť kamera se dívá do -Z osy, ale tyto hodnoty zadáváme jako kladná čísla.

    Note

    -z v rovnici výše je zodpovědné za přepnutí mezi right-handed a left-handed systémem souřadnic v OpenGL.

    Depth mapping 3

    width=500

    \begin{aligned}
        -1.0 &= \frac{c_1}{-(-\text{near})} + c_2 \\
        1.0 &= \frac{c_1}{-(-\text{far})} + c_2
    \end{aligned}
    

    Tedy:

    \begin{aligned}
        c_1 &= \frac{2 \cdot \text{far} \cdot \text{near}}{\text{near} - \text{far}} \\
        c_2 &= \frac{\text{far} + \text{near}}{\text{far} - \text{near}}
    \end{aligned}
    

    Pokud \frac{c_1}{-z} + c_2 přepíšeme jako \frac{(c_1 + c_2 \cdot (-z))}{-z} = \frac{(-c_2 \cdot z + c_1)}{-z}, můžeme opět použít homogenní souřadnice a dělení w a získáme:

    M_\text{depth} = \begin{bmatrix}
        1 & 0 & 0 & 0 \\
        0 & 1 & 0 & 0 \\
        0 & 0 & -c_2 & c_1 \\
        0 & 0 & -1 & 0 \\
    \end{bmatrix}
    = \begin{bmatrix}
        1 & 0 & 0 & 0 \\
        0 & 1 & 0 & 0 \\
        0 & 0 & -\frac{\text{far} + \text{near}}{\text{far} - \text{near}} & \frac{2 \cdot \text{far} \cdot \text{near}}{\text{near} - \text{far}} \\
        0 & 0 & -1 & 0 \\
    \end{bmatrix}
    

Výsledná matice je:

P_\text{persp} =  M_\text{depth} \cdot S \cdot D \cdot T =

\begin{bmatrix}
    \textcolor{green}{\frac{2 \cdot \text{near}}{\text{right} - \text{left}}}
        & 0
        & 0
        & \textcolor{purple}{-\text{near} \cdot \frac{\text{right} + \text{left}}{\text{right} - \text{left}}} \\

        0
        & \textcolor{blue}{\frac{2 \cdot \text{near}}{\text{top} - \text{bottom}}}
        & 0
        & \textcolor{#F56FA1}{-\text{near} \cdot \frac{\text{top} + \text{bottom}}{\text{top} - \text{bottom}}} \\
        % Nika: použij cyklamenovou farbu

        0
        & 0
        & -\frac{\text{far} + \text{near}}{\text{far} - \text{near}}
        & \frac{2 \cdot \text{far} \cdot \text{near}}{\text{near} - \text{far}} \\

    0 & 0 & -1 & 0 \\
\end{bmatrix}

Tahle matice funguje pro obecné frustum dané parametry \text{left}, \text{right}, \text{bottom}, \text{top}, \text{near}, \text{far}. Pokud dosadíme původní parametry za mezihodnoty:

\begin{aligned}

\textcolor{green}{\frac{2 \cdot \text{near}}{\text{right} - \text{left}}}
&= \frac{\textcolor{red}{2} \cdot \text{near}}{\textcolor{red}{2} \cdot \text{right}}
= \frac{\text{near}}{\text{top} \cdot \text{aspect}}
= \frac{\textcolor{red}{\text{near}}}{\textcolor{red}{\text{near}} \cdot \tan \left( \frac{\text{FOV}_y}{2} \right) \cdot \text{aspect}}
= \textcolor{green}{\frac{\cot \left( \frac{\text{FOV}_y}{2} \right)}{\text{aspect}}} \\

\textcolor{blue}{\frac{2 \cdot \text{near}}{\text{top} - \text{bottom}}}
&= \frac{\textcolor{red}{2} \cdot \text{near}}{\textcolor{red}{2} \cdot \text{top}}
= \frac{\textcolor{red}{\text{near}}}{\textcolor{red}{\text{near}} \cdot \tan \left( \frac{\text{FOV}_y}{2} \right)}
= \textcolor{blue}{\cot \left( \frac{\text{FOV}_y}{2} \right)} \\

\textcolor{purple}{-\text{near} \cdot \frac{\text{right} + \text{left}}{\text{right} - \text{left}}}
&= -\text{near} \cdot \frac{\color{red} \text{right} - \text{right}}{2 \cdot \text{right}}
= \textcolor{purple}{0} \\

\textcolor{#F56FA1}{-\text{near} \cdot \frac{\text{top} + \text{bottom}}{\text{top} - \text{bottom}}}
&= -\text{near} \cdot \frac{\color{red} \text{top} - \text{top}}{2 \cdot \text{top}}
= \textcolor{#F56FA1}{0}

\end{aligned}

dostaneme matici, na kterou se trochu lépe kouká: 4

P_\text{persp} = \begin{bmatrix}
    \textcolor{green}{\frac{\cot \left( \frac{\text{FOV}_y}{2} \right)}{\text{aspect}}}
        & 0
        & 0
        & \textcolor{purple}{0} \\

    0
        & \textcolor{blue}{\cot \left( \frac{\text{FOV}_y}{2} \right)}
        & 0
        & \textcolor{#F56FA1}{0} \\

    0
        & 0
        & -\frac{\text{far} + \text{near}}{\text{far} - \text{near}}
        & \frac{2 \cdot \text{far} \cdot \text{near}}{\text{near} - \text{far}} \\

    0 & 0 & -1 & 0 \\
\end{bmatrix}

Základní afinní transformace

Opakování z Lineární algebry II:

  • Afinní prostor $\mathcal{A}$
    Trojice (A, V, \oplus), kde A je množina bodů, V je vektorový prostor (zaměření) a \oplus je binární funkce \oplus : A \times V \to A.

  • Standardní afinní prostor $\mathcal{A}_n$
    Je afinní prostor (\mathbb{R}^n, \mathbb{R}^n, +).

  • Afinní kombinace bodů
    Výrazy tvaru t_0 \cdot a_0 + t_1 \cdot a_1 + ... + t_n \cdot a_n, kde t_i \in \mathbb{R}, a_i \in \mathcal{A} a \sum_{i=0}^n t_i = 1.

  • Afinní zobrazení
    Zobrazení f : \mathcal{A} \to \mathcal{A}, které zachovává afinní kombinace bodů.

    Složení nějakého lineárního zobrazení a translace.

  • Translace $T$
    Pro posun v 2D prostoru podél osy (x, y):

    T = \begin{bmatrix}
        1 & 0 & x \\
        0 & 1 & y \\
        0 & 0 & 1
    \end{bmatrix}
    

    Pro posun ve 3D prostoru podél osy (x, y, z):

    T = \begin{bmatrix}
        1 & 0 & 0 & x \\
        0 & 1 & 0 & y \\
        0 & 0 & 1 & z \\
        0 & 0 & 0 & 1
    \end{bmatrix}
    
  • Rotace $R$
    Pro rotaci v 2D prostoru o úhel \theta:

    R = \begin{bmatrix}
        \cos \theta & -\sin \theta & 0 \\
        \sin \theta & \cos \theta & 0 \\
        0 & 0 & 1 \\
    \end{bmatrix}
    

    Pro rotaci ve 3D prostoru o úhel \theta:

    • Kolem osy X:

      R = \begin{bmatrix}
          1 & 0 & 0 & 0 \\
          0 & \cos \theta & -\sin \theta & 0 \\
          0 & \sin \theta & \cos \theta & 0 \\
          0 & 0 & 0 & 1
      \end{bmatrix}
      
    • Kolem osy Y:

      R = \begin{bmatrix}
          \cos \theta & 0 & \sin \theta & 0 \\
          0 & 1 & 0 & 0 \\
          -\sin \theta & 0 & \cos \theta & 0 \\
          0 & 0 & 0 & 1
      \end{bmatrix}
      
    • Kolem osy Z:

      R = \begin{bmatrix}
          \cos \theta & -\sin \theta & 0 & 0 \\
          \sin \theta & \cos \theta & 0 & 0 \\
          0 & 0 & 1 & 0 \\
          0 & 0 & 0 & 1
      \end{bmatrix}
      
  • Škálování / scale $S$ Pro škálování v 2D prostoru:

    S = \begin{bmatrix}
        x & 0 & 0 \\
        0 & y & 0 \\
        0 & 0 & 1 \\
    \end{bmatrix}
    

    Pro škálování ve 3D prostoru:

    S = \begin{bmatrix}
        x & 0 & 0 & 0 \\
        0 & y & 0 & 0 \\
        0 & 0 & z & 0 \\
        0 & 0 & 0 & 1
    \end{bmatrix}
    
  • Zkosení / shear (asi taky S) Pro zkosení v 2D prostoru vektorem (x, y):

    S = \begin{bmatrix}
        1 & x & 0 \\
        y & 1 & 0 \\
        0 & 0 & 1 \\
    \end{bmatrix}
    

    Pro zkosení ve 3D prostoru podél plochy YZ:

    S = \begin{bmatrix}
        1 & Y & Z & 0 \\
        0 & 1 & 0 & 0 \\
        0 & 0 & 1 & 0 \\
        0 & 0 & 0 & 1
    \end{bmatrix}
    

    Podél plochy XZ:

    S = \begin{bmatrix}
        1 & 0 & 0 & 0 \\
        X & 1 & Z & 0 \\
        0 & 0 & 1 & 0 \\
        0 & 0 & 0 & 1
    \end{bmatrix}
    

    Podél plochy XY:

    S = \begin{bmatrix}
        1 & 0 & 0 & 0 \\
        0 & 1 & 0 & 0 \\
        X & Y & 1 & 0 \\
        0 & 0 & 0 & 1
    \end{bmatrix}
    

Další zdroje