Animation à partir de courbes

Pour concevoir des animations plus complexes, il est possible de faire mouvoir des objets d’un scène en suivant un chemin défini par une courbe.

Les courbes

three.js fournit un ensemble de classes héritant de Curve. Ces classes représentent de courbes mathématiques à partir desquels il est possible de réaliser une interpolation. Ces courbes sont généralement définies par des points de contrôles.

Il existe des courbes 2D comme la CubicBezierCurve et des courbes 3D la CubicBezierCurve3. Toutes ces courbes possède la méthode getPoint qui permet connaître les coordonnées d’un point sur la courbe à partir de sa position le long de la courbe (la position étant donnée par un nombre entre 0 et 1).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html>
  <head>
    <meta charset=utf-8>
    <title>three.js app</title>
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <p>Quelques points le long d'une courbe de Bézier</p>
    <script src="https://threejs.org/build/three.min.js"></script>
    <script>
      // création d'un courbe de Bézier à partir d'un point de départ,
      // de deux points de contrôle et d'un point d'arrivée.
      var curve = new THREE.CubicBezierCurve3(
        new THREE.Vector3(-10,  0, 3),
        new THREE.Vector3( -5, 15, 2),
        new THREE.Vector3( 20, 15, 1),
        new THREE.Vector3( 10,  0, 0)
      );

      for (var i = 0; i < 11; ++i) {
        var p = curve.getPoint(i * 1/10);
        document.write("<p>(" + p.x + ", " +  p.y + ", " + p.z + ")</p>");
      }

    </script>
  </body>
</html>

Vous pouvez télécharger ce fichier directement.

Dans l’exemple ci-dessus, on récupère chaque point à la ligne 27 grâce à la méthode getPoint.

Représentation graphique d’une courbe

On peut tracer à l’écran une courbe comme une succession de lignes. Plus on sélectionne de points le long de la courbe, meilleur est l’échantillonnage et la représentation finale. Pour afficher une courbe, on peut créer un objet Line qui affiche en fait une succession de ligne à partir des vertices fournis par la géométrie.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html>
  <head>
    <meta charset=utf-8>
    <title>three.js app</title>
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <script src="https://threejs.org/build/three.min.js"></script>
    <script>
      // création du renderer
      var renderer = new THREE.WebGLRenderer();
      document.body.appendChild(renderer.domElement);
      renderer.setSize(window.innerWidth, window.innerHeight);

      // création de la caméra
      var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.5, 1000);

      // création de la scène
      var scene = new THREE.Scene();

      // couleur de fond noire
      scene.background = new THREE.Color(0, 0, 0);

      // création d'un courbe de Bézier à partir d'un point de départ,
      // de deux points de contrôle et d'un point d'arrivée.
      var curve = new THREE.CubicBezierCurve3(
        new THREE.Vector3(-10,  0, 3),
        new THREE.Vector3( -5, 15, 2),
        new THREE.Vector3( 20, 15, 1),
        new THREE.Vector3( 10,  0, 0)
      );

      var points = curve.getPoints(40);
      var geometry = new THREE.BufferGeometry().setFromPoints(points);
      var material = new THREE.LineBasicMaterial();
      var curveObject = new THREE.Line(geometry, material);
      scene.add(curveObject);

      camera.position.z = 30;
      camera.position.y = 5

      // rendu
      renderer.render(scene, camera);
    </script>
  </body>
</html>

Vous pouvez télécharger ce fichier directement.

Note

La méthode getPoints retourne un tableau contenant autant de points sur la courbe que demandé. Cette méthode permet de réaliser rapidement un échantillonnage pour construire une géométrie.

Animation le long d’une courbe

Une courbe peut également représenter un chemin suivi par un objet. Pour cela, on peut tirer profit du fait que la méthode requestAnimationFrame passe en paramètre de la fonction de callback un timestamp correspond au moment de l’appel. Il est donc possible d’utiliser cette information pour en déduire une position le long de la courbe et mettre à jour la position de l’objet en conséquence :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<!DOCTYPE html>
<html>
  <head>
    <meta charset=utf-8>
    <title>three.js app</title>
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <script src="https://threejs.org/build/three.min.js"></script>
    <script>
      // création du renderer
      var renderer = new THREE.WebGLRenderer();
      document.body.appendChild(renderer.domElement);
      renderer.setSize(window.innerWidth, window.innerHeight);

      // création de la caméra
      var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.5, 1000);

      // création de la scène
      var scene = new THREE.Scene();

      // couleur de fond noire
      scene.background = new THREE.Color(0, 0, 0);

      // création d'un courbe de Bézier à partir d'un point de départ,
      // de deux points de contrôle et d'un point d'arrivée.
      var curve = new THREE.CubicBezierCurve3(
        new THREE.Vector3(-10,  0, 3),
        new THREE.Vector3( -5, 15, 2),
        new THREE.Vector3( 20, 15, 1),
        new THREE.Vector3( 10,  0, 0)
      );

      var points = curve.getPoints(40);
      var geometry = new THREE.BufferGeometry().setFromPoints(points);
      var material = new THREE.LineBasicMaterial();
      var curveObject = new THREE.Line(geometry, material);
      scene.add(curveObject);

      var sphere = new THREE.Mesh(new THREE.SphereGeometry());
      scene.add(sphere);

      camera.position.z = 30;
      camera.position.y = 5

      var vitesse = 5;

      var start = null;
      function animate(t) {
        if (start == null) {
          start = t;
        }
        var delai = t - start;

        curve.getPoint((delai * vitesse * .0001) % 1, sphere.position);

        requestAnimationFrame(animate);
        renderer.render(scene, camera);
      }
      requestAnimationFrame(animate);

    </script>
  </body>
</html>

Vous pouvez télécharger ce fichier directement.

Dans l’exemple ci-dessous, la fonction animate reçoit en paramètre le timestamp du rendu. Elle renseigne la variable start la première fois, puis elle calcule la différence pour connaître le temps écoulé depuis le début de la scène. On peut ensuite en déduire ligne 69, la position de l’objet le long du chemin. Notez que la méthode getPoint accepte en second paramètre un vecteur qu’elle met directement à jour.

Note

Vous pouvez également utiliser la méthode getPointAt. Cette méthode tient compte de la courbure entre deux points et crée un mouvement uniforme tandis que getPoint crée des effets d’accélération et de décélération.

Note

Vous pouvez tester un autre exemple à cette adresse.

Exercice

Modification de l’animation le long d’une courbe

Modifiez l’exemple ci-dessus afin que l’animation ne boucle pas. Lorsque la sphère arrive au bout de la courbe, elle doit simplement repartir en sens inverse.