01/08/2023

Moving Sinusoïdal Lines along 3D top view

Ouch :) This article was published 1 year ago - might be out of date, check out stuff or leave comment

Learn to animate nice curve lines in a few code lines with ThreeJS, and show them from above.

We 'll be using a three js boiler plate configured for Vite, on top of which we'll add a specific mesh line library. The prerequisites for this lesson are

  • node js, vite, npm
  • object javascript, basic three js

Choose a vite + threejs boiler plate

I tried a few code boilerplates. First try was from Francisco Jaramillo, guy from Montreal who has a few github projects , among which ThreeJs based Tetris including opensource code !! His Vite ThreejsTemplate is interesting because it demonstrates the object picking feature of the ThreeJs DragControl Event dispatcher. It is a working three js scene with many objects, a cube, a grid plane, a GUI to control some parameters of the scene, and the AnimationLoop. That's what I was looking for, and I could have kept this boilerplate to start my project but it is a bit too complex. better start from a lighter option, a light project from Italian Doinel Atanasiu, that features a simple animated plane in a single three js file, easy to modify for a small project

Component : Three MeshLine

ThreeMeshline is quite an old and non maintained -actually forked by pdmrs for maintenance - component for threeJS. It is an upgrade of the ThreeJsLine Object, with the notable feature of line width. In spite of a notable mention in the original Line object, linewidth argument will not render on most browsers.

The whole point here is to build lines with points. Starting from the src/three.js class from Doinel's example boilerplate,

  • import the WaveScene extension
  • add the following function :

WaveMeshline / using MeshLine

 waveMeshLine()
  {
    const points = [];
 
    var max=(2 * Math.PI) / 100
    for (let i=1 ; i<10; i++)
    for (let j = 0; j < Math.PI *11;j += max ) {
      points.push(new T.Vector3(    j *400, Math.cos(j+ this.count/5 +i)*300,1200-i*300));
    }
    const geometry = new Three.BufferGeometry().setFromPoints(points);
    const line = new MeshLine();
    line.setGeometry(geometry);
    const mesh = new Three.Mesh(line, this.waveLineMaterial1);

    mesh.position.set (-5000,0,0)

   this.scene.waveAddToScene( mesh , "WaveLine");


  }

WaveMeshLine / with Threejs Line

for the record I suggest the original Three Js Line object if you want to play around with a big amount of lines (check out performance issues with the animation technique, below). Again, this object will not render thick lines (in this example, 20) on most machines, as mentioned here :

Due to limitations of the OpenGL Core Profile with the WebGL renderer on most platforms linewidth will always be 1 regardless of the set value.

  waveMeshLine()
  {
    const material = new THREE.LineBasicMaterial({
      color: 0x99ffff, linewidth:20
    });


  for (let j=1;j<300;j++) {   const points = [];
    for (let i = 0; i < 1000; i++)
      points.push(new THREE.Vector3(    j *400, Math.cos(j+ this.count/5 +i)*300,1200-i*300));


    const geometry = new THREE.BufferGeometry().setFromPoints(points);

    const line = new THREE.Line(geometry, material);
    this.scene.addToScene(line, "WaveLine");
  }

Animating lines

in the render function, add the counter increment . Of course you will have taken care of initializing this count to zero in the class constructor (the count variable trick is taken from another basic three js sinus animation sample , point wave demo)

 this.count +=0.1;

the animation rendering in this case is very basic : notice we use the waveScene extension AddToScene method that names objects we add to the scene , so that we can at each tick delete with our waveScene extension waveRemoveMeshes by name and recreate them. Here's the code for the tick animate sequence based, as always with ThreeJs, on requestAnimationFrame.

  animateWaveLines()
  {
    this.scene.waveRemoveMeshes("WaveLine")
    this.waveMeshLine()
  }

Big drawback of that technique is that we delete and recreate objects . When we try to use more points by extending the limits of our loops, we get to a browser limit, don't know exactly yet who's reponsible for the error : Array buffer allocation failed.. So you can experiment but be ready to freeze your browser.

To top