Animer des objets avec WebGL

Le code de l'exemple précédent est déjà configuré pour redessiner notre scène WebGL toutes les 15 millisecondes. Jusqu'à maintenant, il redessine simplement chaque fois la même manière. Il est temps de changer cela en faisant bouger nos carrés. 

Dans cet exemple, nous allons faire tourner et déplacer notre carré 2D dans les trois dimensions. Cela prouvera que même si nous créons un objet en 2D, il existera quand même en 3D.

Faire tourner le carré

Commençons par faire tourner le carré. La première chose dont nous avons besoin est une variable pour enregistrer la rotation courante du carré :

var squareRotation = 0.0;

Maintenant, nous devons modifier la fonction drawScene() pour appliquer la rotation courante du carré quand on le dessine. Après avoir déplacé le carré à sa position initiale, nous appliquons la rotation comme cela :  

mvPushMatrix();
mvRotate(squareRotation, [1, 0, 1]);

Cela enregistre la matrice model-view courante, et la fait ensuite tourner autour des axes X et Z en fonction de la valeur de squareRotation.

Après avoir dessiner, nous devons restaurer la matrice originale :

  mvPopMatrix();

Nous enregistons et restaurons la matrice originale pour éviter d'appliquer la rotation aux autres objets que nous dessinons. Aucun autre objet n'est dessiné dans cet exemple donc cela n'a pas d'utilité ici. 

Pour animer, nous avons besoin d'ajouter le code qui change la valeur de squareRotation en fonction du temps. Nous pouvons faire cela en créant une nouvelle variable pour enregistrer le temps auquel on a animé pour la dernière fois (appelons la lastSquareUpdateTime). Ajoutons ensuite le code suivant à la fin de la fonction drawScene().

  var currentTime = (new Date).getTime();
  if (lastSquareUpdateTime) {
  	var delta = currentTime - lastSquareUpdateTime;
  	
  	squareRotation += (30 * delta) / 1000.0;
  }
  
  lastSquareUpdateTime = currentTime;

Ce code utilise le temps écoulé depuis la dernière actualisation pour déterminer l'amplitude de la rotation.

Déplacer le carré

Nous pouvons aussi déplacer le carré en le translatant avant de le dessiner.

Enregistrons les coordonées sur les différents axes dans de nouvelles variables :

var squareXOffset = 0.0;
var squareYOffset = 0.0;
var squareZOffset = 0.0;

Et les décalages sur chaque axe dans ces variables : 

var xIncValue = 0.2;
var yIncValue = -0.4;
var zIncValue = 0.3;

Nous pouvons maintenant simplement ajouter ce code au précendent qui modifie la rotation :

    squareXOffset += xIncValue * ((30 * delta) / 1000.0);
    squareYOffset += yIncValue * ((30 * delta) / 1000.0);
    squareZOffset += zIncValue * ((30 * delta) / 1000.0);
    
    if (Math.abs(squareYOffset) > 2.5) {
      xIncValue = -xIncValue;
      yIncValue = -yIncValue;
      zIncValue = -zIncValue;
    }

Enfin, ajoutons ceci à la fonction drawScene() :

mvTranslate([squareXOffset, squareYOffset, squareZOffset]);

Cela fait que notre carré zoom et se déplace au hasard tout en tournant.

Si votre navigateur supporte WebGL, cliquez ici pour voir cet exemple en action.

Plus d'opérations sur les matrices

Cet exemple utilise quelques opérations sur les matrices en plus, dont deux routines pour empiler et dépiler des matrices sur une pile pour les préserver, et une qui tourne une matrice selon un nombre donné de degrés. Les voici : 

var mvMatrixStack = [];

function mvPushMatrix(m) {
  if (m) {
    mvMatrixStack.push(m.dup());
    mvMatrix = m.dup();
  } else {
    mvMatrixStack.push(mvMatrix.dup());
  }
}

function mvPopMatrix() {
  if (!mvMatrixStack.length) {
    throw("Can't pop from an empty matrix stack.");
  }
  
  mvMatrix = mvMatrixStack.pop();
  return mvMatrix;
}

function mvRotate(angle, v) {
  var inRadians = angle * Math.PI / 180.0;
  
  var m = Matrix.Rotation(inRadians, $V([v[0], v[1], v[2]])).ensure4x4();
  multMatrix(m);
}

Ces routines ont été empruntées d'un exemple écrit précédemment par Vlad Vukićević.

Étiquettes et contributeurs liés au document

Étiquettes : 
 Contributeurs à cette page : teoli, fscholz, LDelhez
 Dernière mise à jour par : teoli,