2

I want to animate the drawing of a line on screen using Three.js. In this case the line I’m looking to draw is a Lorenz attractor, using this YouTube tutorial as a guide.

There’s a snippet of what I’ve created so far available at:

// CONFIGURE SCENE
// ------------------------------------

// Create Scene - acts as container
var scene = new THREE.Scene();

// Create camera - (field of view, aspect ratio, near and far planes)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); 

// Renderer - webgl
var renderer = new THREE.WebGLRenderer( { alpha: true,  antialias: true } );
renderer.setClearColor( 0x000000, 0 ); // set to show background of page

// Tell renderer to render to size of window
renderer.setSize( window.innerWidth, window.innerHeight );

// Add renderer to DOM
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);

// ADD GEOMETRY
// ------------------------------------
var x = -12.1;
var y = -22;
var z = 0;

var a = 10; // sigma
var b = 28; // beta
var c = 8/3; // rho

var dt, dx, dy, dz;
var points = [];

// A mesh is made up of geometry and material
// Geometry is like a scaffold. Made up of x,y,z coordinates called vertices 
// Material is the fill (faces) of the geometry

// Create Material (MeshBasic is not influenced by light)
var material = new THREE.LineBasicMaterial({
    color: 0x0000ff
});

var geometry = new THREE.Geometry();

// Create mesh, passing in geometry and material
var line = new THREE.Line(geometry, material);

// Calculate the 50000 Lorenz attractor vertices
for (var i = 0; i < 50000; i++) {
 dt = 0.01;
    dx = (a * (y - x)) * dt;
    dy = (x * (b - z) - y) * dt;
    dz = (x * y - c * z) * dt;
    
    x = x + dx;
    y = y + dy;
    z = z + dz;

    geometry.vertices.push(new THREE.Vector3(x, y, z));
}

// Add line to scene
scene.add(line);

// Move the camera out, else our camera will be at 0,0,0 and the attractor won't be visible by default
camera.position.z = 80;

// RENDER LOOP
// ------------------------------------
function render() {

 /**
 // Does not work - experimenting with animating the drawing of the attractor
 // ------------------------------------
 // Calculate the Lorenz attractor vertices
 dt = 0.01;
 dx = (a * (y - x)) * dt;
 dy = (x * (b - z) - y) * dt;
 dz = (x * y - c * z) * dt;
   
 x = x + dx;
 y = y + dy;
 z = z + dz;

 var vect = new THREE.Vector3(x, y, z); // Create three.js vector
 geometry.vertices.push(vect); // Add vertice to geometry
 // ------------------------------------
 **/

 renderer.render(scene, camera); // Render scene and camera

 // Rotate the attractor
 line.rotation.x += 0.001;
 line.rotation.y += 0.001;

 requestAnimationFrame(render); // Call animation loop recursively 
}
render(); // Initial call to loop
body {
  margin: 0;
  overflow: hidden;
  background-color: #ccc;
}
  canvas {
    width: 100%;
    height: 100%;
}
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.js"></script>
  <script src="https://s3-eu-west-1.amazonaws.com/code-pen/OrbitControls.js"></script>

As you can see, I'm able to successfully draw the Lorenz attractor, before adding it the scene.

However, I can't animate the drawing of the attractor, by pushing new vertices onto the geometry within the render loop. Doing so causes the line not to be visible on screen. You can see where I've experimented with this approach in the commented out section of JavaScript from line 73 onwards.

Some searching has brought up the idea of using Three.js’s BufferGeometry class. However, I’m unclear as to what exactly that class does or how to apply it in this instance.

Any guidance would be appreciated.

xxx
  • 1,153
  • 1
  • 11
  • 23
almcd
  • 1,069
  • 2
  • 16
  • 29
  • [this SO answer](http://stackoverflow.com/questions/31399856/drawing-a-line-with-three-js-dynamically/31411794#31411794) may help you with drawing a line – prisoner849 Nov 16 '16 at 11:22
  • @prisoner849 Thanks for the link. That SO answer was one of the things that lead me to Three.js's BufferGeometry class. But I'm at a loss as to how to apply that to my problem. – almcd Nov 16 '16 at 14:10
  • I see no problem to combine the SO answer with your jsbin code. [jsfiddle](http://jsfiddle.net/prisoner849/sfxo7m24/) example – prisoner849 Nov 16 '16 at 14:34
  • Thanks for the example @prisoner849 that's really helpful and makes it much clearer to me. BTW - would be happy to make this the accepted answer, if it was posted as an answer. – almcd Nov 17 '16 at 13:43

1 Answers1

4

Looking at this SO answer, you can combine this answer with your jsbin code. All that you have to do is to put your global variabels with attractor initials

var MAX_POINTS = 50000;

var x = -12.1;
var y = -22;
var z = 0;

var a = 10; // sigma
var b = 28; // beta
var c = 8/3; // rho

var dt, dx, dy, dz; 

and make a small change to the updatePositions() function, how you will set coordinates for an adding line segment

var index = 0;
...
dt = 0.01;
dx = (a * (y - x)) * dt;
dy = (x * (b - z) - y) * dt;
dz = (x * y - c * z) * dt;

x = x + dx;
y = y + dy;
z = z + dz;

jsfiddle example

Community
  • 1
  • 1
prisoner849
  • 16,894
  • 4
  • 34
  • 68