almcd - 9 months ago 48

Javascript Question

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.

Answer Source

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