Espaces et transformations

L’espace du monde (World Space)

Une scène est un espace qui contient des objets. Cet espace est celui que nous voulons visualiser en créant une image à partir d’une caméra virtuelle.

L’espace de la scène est appelé espace du monde (world space).

Lorsqu’on charge les sommets d’un modèle 3D, le but est de les transformer pour les placer dans l’espace du monde.

L’espace des sommets (Object Space)

L’espace des sommets, parfois appelé (object space) est l’espace original où les sommets d’un objets sont définis. Dit autrement, cet espace n’est pas le résultat de transformations – les données sont brutes.

Un artiste qui créer la géométrie pour un personnage, par exemple, travaille dans cet espace. Les sommets sont placés par rapport à l’origine \((0,0)\).

Soit un personnage \(obj_1\) qui est un triangle. \[ \begin{align*} EspaceSommets(obj_1) = &\begin{bmatrix} 0.0 & 0.5 \\ -0.5 & -0.5 \\ 0.5 & -0.5 \\ \end{bmatrix} \end{align*} \]

Les sommets du personnages seront ensuite transformés pour placer le personnage dans une scène quelconque.

Sommets directement dans l’espace du monde

Il faut passer d’espace de sommets à espace du monde. Essayons une première technique où on map directement d’un espace à l’autre. Dit autrement, les sommets seront placés aux mêmes coordonnées dans l’espace du monde que dans l’espace des sommets.

Cette transformation est représentée par la matrice identité \(I\).

\[ \begin{align*} I\times EspaceSommets(obj_1) &= \begin{bmatrix} 1.0 & 0.0 & 0.0 \\ 0.0 & 1.0 & 0.0 \\ 0.0 & 0.0 & 1.0 \\ \end{bmatrix} \times \begin{bmatrix} 0.0 & 0.5 \\ -0.5 & -0.5 \\ 0.5 & -0.5 \\ \end{bmatrix}\\[10pt] &=\begin{bmatrix} 0.0 & 0.5 \\ -0.5 & -0.5 \\ 0.5 & -0.5 \\ \end{bmatrix} \end{align*} \]

Soit deux objets à placer dans une scène. Chaque joueur contrôlera un personnage, mais le personnage a le même modèle : le triangle.

\[ \begin{align*} EspaceMonde(obj_1||obj_2) &= I \times EspaceSommets(obj_1)\\ &= I \times EspaceSommets(obj_2)\\ &=\begin{bmatrix} 0.0 & 0.5 \\ -0.5 & -0.5 \\ 0.5 & -0.5 \\ \end{bmatrix} \end{align*} \]

Évidemment, la transformation identité n’est pas un mapping qui permettra à deux personnages de se déplacer dans une scène.

Matrice model

La matrice Model est la transformation de l’espace de sommets vers l’espace du monde. Elle est identifiée avec l’étiquette \(M\).

Dans l’exemple précédent, \(M = I\) pour la transformation des deux objets.

Soit maintenant deux objets avec des sommets différents dans leur object space.

\[ \begin{align*} EspaceSommets(obj_1)=\begin{bmatrix} 0.0 & 0.5 \\ -0.5 & -0.5 \\ 0.5 & -0.5 \\ \end{bmatrix}\\[10pt] EspaceSommets(obj_2)=\begin{bmatrix} 0.5 & 1.0 \\ 0.0 & 0.0 \\ 1.0 & 0.0 \\ \end{bmatrix} \end{align*} \]

Notez où les triangles sont par rapport à l’origine de l’espace.

Voici des exemples avec des \(M\) qui représentent des rotations, scaling, et translations.

Rotation

\[M = R \quad R \in \mathbb{R}^{m \times n}\]

Scaling

\[M = S \quad S \in \mathbb{R}^{m \times n}\]

Lorsqu’on ne scale pas tous les axes par le même facteur (lorsque qu’on ne fait pas une homothétie), les angles ne sont pas préservés.

Cisaillement (Shearing)

Il est évident que le cisaillement ne préserve pas les angles. Par contre, les lignes demeures parralèles et l’origine ne se déplace pas. C’est une transformation linéaire.

Translation

La translation n’est pas une transformation linéaire. Elle est affine, où elle déplace l’origine. Notez que l’origine du repère pour l’objet n’est plus à l’origine de la scène.

\[M = T,\quad T \in \mathbb{R}^{m \times n}\]

La translation n’est pas une transformation linéaire, car elle ne préserve pas l’origine. Elle est une transformation affine, qui est une catégorie de transformations plus générale. La rotation, le scaling, et le cisaillement sont des transformations linéaires, donc aussi des transformations affines.

La translation d’un vecteur \(\mathbb{R}^n\) peut être exprimée comme une transformation linéaire à l’aide de coordonnées homogènes. Ceci augmente les vecteurs à une dimension \(\mathbb{R}^{n+1}\).

Par exemple, pour un sommet \((x,y)\) 2D et un vecteur de translation \((t_x, t_y)\) :

\[ \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} = \begin{bmatrix} x + t_x \\ y + t_y \\ 1 \end{bmatrix} \]

Chaînes de transformations

\(M\) peut être le résultat de plusieurs transformations. Par exemple, \(M = R_{tot} = R_1R_0\). Ceci peut être interprété comme appliquer une rotation \(R_1\) sur les résultats de la rotation \(R_0\) pour obtenir une rotation totale \(R_{tot}\). Les transformations sont appliquées de droite à gauche.

Si \(M = T_0R_0\) :

Les transformations sont faîtes selon le repère du monde. La rotation est par rapport à l’origine de la scène, et non le l’origine du repère après la translation.

La multiplication matricelle est non-commutative, sauf dans les cas triviales. \[R_0T_0 \ne T_0R_0\]

Pour tourner effectivement autour du repère suivant la translation (et non autour de celui du monde), il faut appliquer la rotation avant la translation.

Matrice \(TRS\)

L’ordre des transformations la plus intuitive est scaling, après rotation, après translation. Chaque objet a une matrice \(TRS\) qui exprime comment étirer, orienter, et placer l’objet dans l’espace du monde. Cette matrice peut être calculée et ensuite envoyée au vertex shader.

Dans l’exemple précédent, \(T\) représente une translation de \((1,1)\), \(R\) représente une rotation de \(45^{\circ}\), et \(S = I\).

Transformations hierarchiques et espace local

Soit un carré \(Obj_{parent}\) et un triangle \(Obj_{enfant}\).

Le \(TRS\) de chaque est \(I\). Le résultats est le suivant :

Changeons le \(TRS\) du carré pour inclure une translation de \((-1, 0)\) :

Les deux objets sont placés et orientés indépendamment de l’autre.

Par curiosité, supposons qu’on transforme les sommets résultants du \(TRS_{enfant}\) par \(TRS_{parent}\). \[ \begin{align*} M_{enfant} &= TRS_{parent} \times TRS_{enfant}\\ &= TRS_{parent} \times I\\ & = TRS_{parent} \end{align*} \]

L’enfant est, dans la scène, à \((-1, 0)\), mais à \((0,0)\) par rapport au repère parent.

Essayons avec un \(TRS_{enfant}\) qui inclut une translation de \((0,1)\).

\[ \begin{align*} M_{enfant} &= TRS_{parent} \times TRS_{enfant}\\ &= TRS_{parent} \times T_{enfant}\\ \end{align*} \]

L’enfant est, dans la scène, à \((-1, 1)\), mais à \((0,1)\) par rapport au repère parent.

Maintenant encore la même \(TRS_{enfant}\), mais avec \(TRS_{parent}\) qui inclut la translation \((-1, 0)\) et une rotation de \(45^{\circ}\).

L’enfant est, dans la scène, à \((\sim0.3, \sim0.7)\), mais encore à \((0,1)\) par rapport au repère parent. Il a une rotation de \(45^{\circ}\) par rapport au repère de la scène, mais encore une rotation de \(0^{\circ}\) par rapport au repère parent.

Finalement, avec le même \(TRS_{parent}\) et \(TRS_{enfant}\), mais ajoutons une rotations de \(45^{\circ}\) au \(TRS_{enfant}\).

Nous voyons que \(TRS_{enfant}\) donne la position, orientation et scale selon le repère du parent, et non selon le monde. L’espace où le repère est celui d’un objet parent est nommé l’espace local. La position \((0,1)\) dans l’espace local veut dire être à \((0,1)\) de l’origine de son parent, et non sa position absolue dans la scène.

\[M_{enfant} = M_{parent} \times TRS_{enfant}\]

Si un objet n’a pas de parent, son espace locale est la même que l’espace de la scène. \(M_{parent} = I\) \[M = I \times M_{enfant}\]

Le parent peut avoir son propre parent. Supposons \(obj_{main}\) est connecté à \(obj_{bras}\) qui est connecté à \(obj_{corps}\).

\[ \begin{align*} M_{corps} &= TRS_{corps}\\[10pt] M_{bras} &= M_{corps} \times TRS_{bras}\\ &= TRS_{corps} \times TRS_{bras}\\[10pt] M_{main} &= M_{bras} \times TRS_{main}\\ &= (M_{corps} \times TRS_{bras}) \times TRS_{main}\\ &= (TRS_{corps} \times TRS_{bras}) \times TRS_{main} \end{align*} \]