Laboratoire 03

Transformations graphiques 2D

Les objets 2D sont définis dans un système cartésien de coordonnées 2D, par exemple, XOY, XOZ ou YOZ. Dans ce laboratoire, nous allons mettre en oeuvre différents types de transformations qui peuvent être appliqués à des objets définis dans le plan XOY: translation, rotation et mise à l'échelle. Ceux-ci sont définis dans un format de matrice, en coordonnées homogènes, comme vous l'avez déjà appris dans le cours. Les matrices de ces changements sont les suivants:

Translation

$$ \begin{bmatrix} {x}'\\ {y}'\\ 1 \end{bmatrix} = \begin{bmatrix} 1 & 0 & t_x\\ 0 & 1 & t_y\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} $$

Rotation

Rotation autour de l’origine

$$ \begin{bmatrix} {x}'\\ {y}'\\ 1 \end{bmatrix} = \begin{bmatrix} cos(u) & -sin(u) & 0\\ sin(u) & cos(u) & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} $$

La rotation relative à un certain point

La rotation relative à un certain point est résolu de cette façon:

  1. translater les deux points: le point au qui on applique la rotation et le point autour duquel la rotation est faite de sorte que le dernier est positionné à l'origine du système de coordonnées.
  2. La rotation normale (autour de l'origine)
  3. translater les résultats de sorte que le point autour duquel la rotation a été fait atteindre sa position initiale

Mise à l'échelle

Mise à l'échelle autour de l'origine

$$ \begin{bmatrix} {x}'\\ {y}'\\ 1 \end{bmatrix} = \begin{bmatrix} s_x & 0 & 0\\ 0 & s_y & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} $$

Si $sx = sy$ alors nous avons mise à l'échelle uniforme, sinon l'échelle non-uniforme.

Le mise à l'échelle autour un point arbitraire

Le mise à l'échelle par rapport à un point arbitraire peut être résolu similaire à la rotation par rapport à un certain point.

Utilisation de la bibliothèque GLM

Dans le laboratoire, on utilise la bibliothèque GLM est une bibliothèque implémentée avec des matrices en forme colonne, exactement le même format que OpenGL. La forme colonne diffère de la forme ligne par l'ordre de stockage des éléments de la matrice dans la mémoire. La matrice de translation est représentée de la manière suivante dans la mémoire:

glm::mat3 Translate(float tx, float ty)
{
	return glm::mat3( 
        	 1,  0, 0,     // colonne 1 en mémoire 
		 0,  1, 0,     // colonne 2 en mémoire
		tx, ty, 1);    // colonne 3 en mémoire
 
}

Pour cette raison, il est plus commode que la matrice être écrite manuellement dans cette forme:

glm::mat3 Translate(float tx, float ty)
{
	return glm::transpose(
		glm::mat3( 1, 0, tx, 
			   0, 1, ty, 
			   0, 0, 1)
	); 
}

Dans le cadre du laboratoire, le fichier Transform2D.h définit les fonctions de calcul des matrices de translation, de rotation et d’échelle. À ce stade, toutes les fonctions renvoient la matrice d'identité. Dans le laboratoire, vous devrez changer le code pour calculer les matrices.

Transformations composées

Pourquoi sont les matrices nécessaires? Pour représenter par une seule matrice de transformation une séquence de transformations élémentaires, au lieu d’appliquer une séquence de transformations élémentaires sur un objet.

Donc, si nous appliquons une rotation, une mise à l'échelle et une translation sur un objet, nous ne faisons pas la rotation de l'objet, l' échellage d’objet suivi par son translation, mais nous calculons une matrice qui représente la transformation composé (rotation, mise à l'échelle et la translation) et nous appliquons cette transformation composé sur l'objet qui doit être transformé.

Ainsi, si nous appliquons une rotation (la matrice de rotation $R$), suivie par un mise à l'échelle ($S$), suivie d'une translation ($T$) sur un point ($x$, $y$), le pointe tournée (${x}'$,${y}'$) est calculé comme suit:

$$ \begin{bmatrix} {x}'\\ {y}'\\ 1 \end{bmatrix} = \begin{bmatrix} 1 & 0 & t_x\\ 0 & 1 & t_y\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} sx & 0 & 0\\ 0 & sy & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} cos(u) & -sin(u) & 0\\ sin(u) & cos(u) & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} $$

Ainsi, la matrice de transformation composée $M$ est $M = T * S * R$.

Dans le laboratoire, dans le fichier Laborator3.cpp, il existe un certain nombre d'objets (carrés) pour lesquels Update (), avant de dessiner, définit les matrices de transformation. La commande de dessin est donnée par la fonction RenderMesh2D().

   modelMatrix = glm::mat3(1);
   modelMatrix *= Transform2D::Translate(150, 250);
   RenderMesh2D(meshes["square1"], shaders["VertexColor"], modelMatrix);

Pour l'exemple précédent, la matrice de translation créée translaté le carré actuel en (150 250). Pour les effets d'animation continue, les étapes de translation doivent changer au fil du temps.

Exemple:

tx += deltaTimeSeconds * 100;
ty += deltaTimeSeconds * 100;
model_matrix *= Transform2D::Translate(tx, ty);

Remarque: Si vous ne tenez pas compte de la durée d'exécution d'une image (deltaTimeSeconds), vous créerez des animations dépendantes de la plateforme.

Exemple: Si sur chaque image vous grandissez sur TX avec un pas constant (ex: TX + = 0.01), l'animation se comportera différemment sur un ordinateur qui va plus vite que celui qui va plus lentement. Sur un ordinateur fonctionnant à 50 FPS, l’objet se déplacera de 0,01 * 50 = 0,5 unité vers la droite dans une seconde. Au lieu de cela, sur un ordinateur plus lent fonctionnant à 10 FPS, l'objet se déplacera de 0,01 * 10 = 0,1 unités vers la droite en une seconde, l'animation sera donc 5 fois plus lente.

Pour cette raison, il est bon de garder à l’esprit la vitesse de chaque ordinateur (date à travers le deltaTimeSeconds, qui représente la durée de la trame précédente) et de modifier les étapes de conversion, les angles de rotation et les facteurs en fonction de cette variable.

La transformation fenêtre-porte

Les dessins représentés dans un application graphique (2D ou 3D) sont habituellement présentés dans un système de coordonnées différent de celui de la zone d'affichage.

Dans les exercices précédents de ce laboratoire, les coordonnées de l'objet étaient rapportées à la taille de la fenêtre définie par glViewport().

Exemple: Si ma fenêtre d'affichage a le coin inférieur gauche (0, 0), une largeur de 1280 et une hauteur de 720, tous les objets doivent être dessinés dans cette plage s'ils veulent être visibles. Cela me fait penser à toute la scène dans (0, 0) - (1280, 720). Si je souhaite supprimer cette limitation, je peux penser à la scène dans un espace logique (par exemple, je crée tous les objets dans l'espace (-1, -1) - (1, 1), puis je les dessine dans la grille d'affichage. , mais en appliquant ce que l’on appelle la porte tournante.

Dans ce qui suit, nous voyons ce que cette transformation implique et comment je peux penser à la scène sans être limité par la taille de la fenêtre.

Définition mathématique

$$ \frac{xp - xpmin}{xpmax - xpmin} = \frac{xf - xfmin}{xfmax - xfmin} $$ $$ \frac{yp - ypmin}{ypmax - ypmin} = \frac{yf - yfmin}{yfmax - yfmin} $$

La transformation est définie par deux rectangles, dans les deux systèmes de coordonnées, appelée fenêtre (de visualisation) et porte (d’affichage).

F: un point dans la fenêtre

P: le point qui F devient par appliquer le transformation de visualisation

La position relative de P dans l’affichage de droite doit être la même position relative de F dans la fenêtre.

$$ sx = \frac{xpmax - xpmin}{xfmax - xfmin} $$

$$ sy = \frac{ypmax - ypmin}{yfmax - yfmin} $$

  • sx, sy dépend de la taille des deux fenêtres
  • tx, ty dépendent des positions des deux fenêtres de l'original système de coordonnées sont définies.

$$ tx = xpmin - sx * xfmin $$ $$ ty = ypmin - sy * yfmin $$

Enfin, la transformation fenêtre-porte a les équations suivantes:

$$ xp = xf * sx + tx $$ $$ yp = yf * sy + ty $$

Nous considérons un même orientation des axes de les deux systèmes de coordonnées. Si elles ont des orientations différentes (comme dans la première image), une correction supplémentaire de la correction de la coordonnée y doit être appliquée.

Les effets de la transformation

  • Augmentation / diminution en fonction de la taille de la fenêtre et la porte
  • Déformation: si la fenêtre et la porte ne sont pas des rectangles semblables
  • Mise à l'échelle uniforme, $s=min(sx,sy)$, l'affichage centrée dans la porte: translation additionnel sur l'axe Ox ou Oy:

$$Tsx = (xpmax - xpmin - s*(xfmax - xfmin)) / 2$$ $$Tsy = (ypmax - ypmin - s*(yfmax - yfmin)) / 2$$

  • Couper les primitives positionées à l'extérieur de la fenetre de visualization

Matrice de transformation fenêtre-porte

Notez que la transformation de la fenêtre de porte implique la mise à l'échelle et la translation. Il a l'expression suivante, avec les formules de calcul pour sx, sy, tx, celles présentées précédemment:

$$ \begin{bmatrix} xp\\ yp\\ 1 \end{bmatrix} = \begin{bmatrix} sx & 0 & tx\\ 0 & sy & ty\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} xf\\ yf\\ 1 \end{bmatrix} $$

La transformation de vue est déjà implémentée dans la classe Laborator3_Vis2D:

//2D vizualization matrix
glm::mat3 Laborator3_Vis2D::VisualizationTransf2D(const LogicSpace & logicSpace, const ViewportSpace & viewSpace)
{
	float sx, sy, tx, ty;
	sx = viewSpace.width / logicSpace.width;
	sy = viewSpace.height / logicSpace.height;
	tx = viewSpace.x - sx * logicSpace.x;
	ty = viewSpace.y - sy * logicSpace.y;
 
	return glm::transpose(glm::mat3(
		sx, 0.0f, tx,
		0.0f, sy, ty,
		0.0f, 0.0f, 1.0f));
}

Dans le laboratoire, dans la classe Laborator3_Vis2D, un carré est créé dans l'espace logique (0,0) - (4,4). Notez que nous ne devons plus rapporter les coordonnées du carré à l'espace d'observation (comme dans les exercices précédents), mais à l'espace logique que nous avons défini.

logicSpace.x = 0;	// logic x
logicSpace.y = 0;	// logic y
logicSpace.width = 4;	// logic width
logicSpace.height = 4;	// logic height
 
glm::vec3 corner = glm::vec3(0.001, 0.001, 0);
length = 0.99f;
 
Mesh* square1 = Object2D::CreateSquare("square1", corner, length, glm::vec3(1, 0, 0));
AddMeshToList(square1);

Dans la fonction Update (), vous tracez cinq fois le même carré précédemment créé: quatre carrés aux quatre coins et un carré au milieu de l'espace logique. Définit 2 fenêtres contenant les mêmes objets. La première fenêtre est définie dans la moitié gauche de la fenêtre d’affichage et la seconde dans la moitié droite. Par défaut, la fenêtre Passerelle par défaut de la deuxième fenêtre, la fenêtre uniforme, est utilisée par défaut. Notez que dans la deuxième fenêtre, les carrés restent toujours des carrés, alors que dans la première fenêtre, ils sont vus comme des rectangles (c'est-à-dire qu'ils sont déformés) si l'espace logique et l'espace d'affichage ne sont pas représentés par de tels rectangles.

Utilisation

Où pouvez-vous utiliser cette fenêtre-porte de transformation? Par exemple, dans un jeu de course en 2D, il est souhaitable, en bas à droite de l'écran, de visualiser votre propre voiture sur une mini-carte. Ceci est fait en dessinant la scène deux fois.

Par exemple, si la scène entière (le chemin et toutes les voitures) est pensée dans l’espace logique (-10, -10) - (10,10) (qui a la taille de 20×20) et que l’espace d’affichage est (0,0) - (1280, 720 ), la première scène est la scène entière avec les paramètres de la fonction fenêtre-porte mentionnés ci-dessus:

LogicSpace logic_space = LogicSpace(-10, -10, 20, 20);
ViewportSpace view_space = ViewportSpace(0, 0, 1280, 720);
vis_matrix *= VisualizationTransf2D(logic_space, view_space);

Si, à un moment donné, votre voiture est dans l’espace (2,2) - (5,5), c’est-à-dire 3×3 et que je souhaite créer une mini-carte dans le coin inférieur droit de l’écran de résolution 280×220, je peux à nouveau dessiner la même scène, mais avec la transformation fenêtre-porte suivante:

LogicSpace logic_space = LogicSpace(2, 2, 3, 3);
ViewportSpace view_space = ViewportSpace(1000, 500, 280, 220);
vis_matrix *= VisualizationTransf2D(logic_space, view_space);

Laboratoire 3

Description du laboratoire

Dans ce laboratoire, vous devez être programmé dans deux classes:

  • Laborator3.cpp, pour familiariser avec les transformations de traduction, de rotation et de redimensionnement 2D
  • Laborator3_Vis2D.cpp, pour familiariser avec la transformation de la fenêtre de la porte

Dans la classe Main, vous pouvez choisir le laboratoire que vous utilisez:

World *world = new Laborator3();

ou

World *world = new Laborator3_Vis2D();

OpenGL est une API 3D. Le dessin d'objets 2D et l'application de transformations 2D sont simulés en effectuant l'abstraction des coordonnées z.

La transformation fenêtre-porte est également simulée pour ce cadre, mais vous apprendrez en cours de route qu’elle est en fait incluse dans la OpenGL et qu’elle ne devrait pas être explicitement définie.

Exercices

  1. Complétez le translation, la rotation et la mise à l'échelle à partir du /Laborator3/Transform2D.h
  2. Modifier les étapes de translation, de rotation et de mise à l'échelle des trois carrés pour créer une animation.
  3. Utilisez les touches W, A, S, D pour traduire la fenêtre logique Laborator3_Vis2D. Utilisez les touches Z et X pour effectuer un zoom avant ou arrière sur la fenêtre logique.
egc/laboratoare/fr/03.txt · Last modified: 2019/10/14 07:52 by alexandru.gradinaru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0