Séance 4 · Travaux pratiques
TP 4 · Transformations et système solaire
Vous écrivez votre propre bibliothèque de matrices 2D, vérifiée par des tests automatiques, puis vous l'utilisez pour placer des objets en pixels, les composer, et animer un système solaire où chaque astre suit son parent.
Télécharger le code de départtp4-depart.zip · 10 Ko · à décompresser, puis ouvrir le dossier tp4/depart/ dans VS Code
Objectifs
- Écrire les matrices de translation, rotation, mise à l'échelle et projection, stockées par colonnes.
- Transmettre une matrice au vertex shader.
- Composer des transformations et constater l'effet de l'ordre.
- Construire une hiérarchie d'objets animés.
La bibliothèque m3
Ouvrez m3.js. Les fonctions identity, multiply, mul et transformPoint sont fournies ; lisez multiply attentivement. Les autres renvoient pour l'instant l'identité. Ouvrez tests.html avec Live Server : la plupart des tests échouent.
- 1.1
translation(tx, ty). - 1.2
rotation(angle). - 1.3
scaling(sx, sy).
Le tableau se lit colonne par colonne. La translation (tx, ty) se trouve donc aux indices 6 et 7, et non 2 et 5. Écrivez trois nombres par ligne de code, chaque ligne étant une colonne : c'est plus lisible.
Dans tests.html, tous les tests passent sauf les trois tests de projection.
Travailler en pixels
Ouvrez index.html. Le rectangle de main.js est décrit en pixels (200 × 120, centré sur l'origine) mais le shader l'interprète encore en espace de découpage : il recouvre tout le canvas.
- 2.1 Dans
m3.js, écrivezprojection(largeur, hauteur). Commencez sur papier : quelle matrice donnex′ = 2x/l − 1ety′ = −2y/h + 1? Relancez les tests : ils doivent tous passer. - 2.2 Dans le vertex shader, déclarez
uniform mat3 u_matrice;et calculezvec3 p = u_matrice * vec3(a_position, 1.0);puisgl_Position = vec4(p.xy, 0.0, 1.0); - 2.3 Récupérez l'emplacement de
u_matrice. - 2.4 Dans
dessiner(), calculezconst P = m3.projection(canvas.width, canvas.height);et envoyez-la avecgl.uniformMatrix3fv(locMatrice, false, P).
Seul un quart du rectangle est visible, dans le coin haut gauche du canvas : son centre est en (0, 0), le coin du canvas en pixels.
Composer avec les curseurs
- Calculez
M = P · T · R · Savecm3.mul, en utilisant les valeurs des curseurs (déjà lues danstx,ty,angle,s), et envoyez M au lieu de P.
Le rectangle apparaît au centre du canvas. Les curseurs le déplacent, le font tourner autour de son centre et le redimensionnent. Le coin jaune permet de suivre son orientation.
- Remplacez par
P · R · T · S. Que se passe-t-il quand on tourne ? Autour de quel point le rectangle tourne-t-il ? - Essayez
P · T · S · Ravec une échelle différente en x et en y (modifiez le code :m3.scaling(s, 1)). Pourquoi le rectangle se déforme-t-il en losange quand il tourne ? - Avec
anglepositif, dans quel sens tourne le rectangle à l'écran ? Expliquez.
Revenez ensuite à P · T · R · S.
Un satellite
On ajoute un petit rectangle, réutilisant la même géométrie, qui tourne autour du coin haut gauche du grand, deux fois plus vite que lui, à 50 pixels de ce coin. Il doit suivre le grand rectangle quand on le déplace, le tourne ou le redimensionne.
- Partez de M (la matrice du grand rectangle) :
const coin = m3.mul(M, m3.translation(-100, -60));est un repère dont l'origine est sur le coin. - Ajoutez une rotation de
2 * angle, une translation de 50 pixels, une échelle de 0,2. Envoyez cette matrice et redessinez.
À angle nul, le petit rectangle est à droite du coin jaune. En tournant le curseur d'angle, il tourne autour de ce coin, plus vite que le grand.
Quand on agrandit le grand rectangle, la distance coin-satellite augmente aussi. Pourquoi ? Comment l'éviter ?
Le système solaire
Ouvrez systeme.html et systeme.js. Un disque unité (rayon 1) est prêt, ainsi qu'une boucle d'animation et une variable temps en secondes. Le Soleil est dessiné : sa matrice mSoleil le place au centre ; l'échelle 50 ne sert qu'à dessiner le disque.
Séparez la matrice qui place un astre (transmise à ses enfants) de celle qui le dessine (avec son échelle). Si l'échelle 50 du Soleil était transmise à la Terre, l'orbite de la Terre ferait 50 × 180 pixels !
- 5.1 La Terre :
mTerre = mSoleil · R(ωt) · T(180, 0), avec ω = 2π / 10 (un tour en 10 secondes). Dessinez-la avecmTerre · S(16, 16). - 5.2 La Lune, enfant de la Terre : orbite de 38 px, un tour en 2 secondes, rayon 6 px.
- 5.3 Mars et ses deux lunes, Phobos et Deimos, avec vos propres valeurs.
La Lune tourne autour de la Terre qui tourne autour du Soleil. Le curseur de vitesse accélère ou fige tout le système.
Combien de multiplications de matrices faut-il pour la Lune ? Le GPU en fait-il plus pour la Lune que pour le Soleil ?
Bonus
- A. Orbites. La fonction
orbiteest fournie : elle redessine le bord du disque enLINE_LOOP. Affichez les orbites de la Terre et de la Lune. - B. Rotation propre. Ajoutez un repère visible sur la Terre (un petit disque décalé) qui montre sa rotation sur elle-même : 1 tour par seconde.
- C. Vaisseau. Dans une nouvelle page, un triangle pointant vers +x : les flèches gauche et droite le font tourner, la flèche haut le fait avancer dans sa direction
(cos θ, sin θ). Réutilisez la boucle du TP 3.