Drawing a line with three.js dynamically
You can animate a line -- or increase the number of points rendered -- very easily using BufferGeometry
and the setDrawRange()
method. You do need to set a maximum number of points, however.
const MAX_POINTS = 500;
// geometry
const geometry = new THREE.BufferGeometry();
// attributes
const positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point
geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
// drawcalls
drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );
// material
const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
// line
line = new THREE.Line( geometry, material );
scene.add( line );
If you want to change the number of points rendered after the first render, do this:
line.geometry.setDrawRange( 0, newValue );
If you want to change the position data values after the first render, you set the needsUpdate
flag like so:
line.geometry.attributes.position.needsUpdate = true; // required after the first render
Here is a fiddle showing an animated line which you can adapt to your use case.
three.js r.147
how to draw a dynamic line in threejs with mouse down between two points using buffergeometry
Try MeshLine, Mesh replacement for THREE.Line
Instead of using GL_LINE, it uses a strip of triangles billboarded.
Dynamically Adding Vertices to a Line in Three.js
EDIT: Using BufferGeometry
and drawcalls
you can now implement equivalent functionality. See Drawing a line with three.js dynamically.
three.js r.71
Dynamically adding vertices to a line is not supported. As stated in the Wiki:
You can only update content of buffers, you cannot resize buffers (this is very costly, basically equivalent to creating new geometry).
You can emulate resizing by pre-allocating a larger buffer and then keeping unneeded vertices collapsed / hidden.
three.js r.55
Animate the drawing of a line in Three.js
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
Drawing a line between moving objects
In your animation loop you have to set line.geometry.verticesNeedUpdate = true
. Because every time after rendering it becomes false
. jsfiddle example
Dynamically adding faces to a three.js geometry
You want to add faces to an existing geometry.
Since buffers can't be resized, the best solution is to switch to BufferGeometry
, preallocate sufficiently-sized buffers, and set the drawRange. See this SO answer. This answer, too.
If you add vertices, you will need to recompute the bounding sphere for frustum culling to work correctly.
geometry.computeBoundingSphere();
Or, as you said, you can disable frustum culling:
mesh.frustumCulled = false;
three.js.r.91
How to smoothly animate drawing of a line
You can smoothly animate the drawing of a line -- even if the line consists of only a few points -- by using LineDashedMaterial
.
The trick is to render only one dash, and increment the length of the dash in the animation loop.
// geometry
var geometry = new THREE.BufferGeometry();
// attributes
numPoints = points.length; // points is an array of Vector3
var positions = new Float32Array( numPoints * 3 ); // 3 vertices per point
var colors = new Float32Array( numPoints * 3 ); // 3 channels per point
var lineDistances = new Float32Array( numPoints * 1 ); // 1 value per point
geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.setAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
geometry.setAttribute( 'lineDistance', new THREE.BufferAttribute( lineDistances, 1 ) );
// populate
var color = new THREE.Color();
for ( var i = 0, index = 0, l = numPoints; i < l; i ++, index += 3 ) {
positions[ index ] = points[ i ].x;
positions[ index + 1 ] = points[ i ].y;
positions[ index + 2 ] = points[ i ].z;
color.setHSL( i / l, 1.0, 0.5 );
colors[ index ] = color.r;
colors[ index + 1 ] = color.g;
colors[ index + 2 ] = color.b;
if ( i > 0 ) {
lineDistances[ i ] = lineDistances[ i - 1 ] + points[ i - 1 ].distanceTo( points[ i ] );
}
}
lineLength = lineDistances[ numPoints - 1 ];
// material
var material = new THREE.LineDashedMaterial( {
vertexColors: true,
dashSize: 1, // to be updated in the render loop
gapSize: 1e10 // a big number, so only one dash is rendered
} );
// line
line = new THREE.Line( geometry, material );
scene.add( line );
Then, in the animation loop:
fraction = ( fraction + 0.001 ) % 1; // fraction in [ 0, 1 ]
line.material.dashSize = fraction * lineLength;
Note: You can compute the line distances any way you want. For example, you could normalize the distances by the total length, so the distance to the last point is 1. You would then vary dashSize
from 0 to 1.
Compare this approach with this alternate method.
three.js r.143
Related Topics
Angular 4 Interceptor Retry Requests After Token Refresh
Javascript:Send JSON Object with Ajax
How to Pause a Youtube Player When Hiding the Iframe
Shiny Slider Input Step by Month
Open File Dialog Box in JavaScript
JavaScript Read File Without Using Input
Converting JSON Format to CSV to Upload Data Table in R to Produce D3 Bubble Chart
"Cannot Use Import Statement Outside a Module" Error When Importing React-Hook-Mousetrap in Next.Js
What Are Asynchronous Functions in JavaScript? What Is "Async" and "Await" in JavaScript
Allow Only Numbers to Be Typed in a Textbox
Invert Y Axis of L:Crs.Simple Map on Vue2-Leaflet
Rails 4 - Gmaps4Rails - Map Won't Render
Angular 4.3.3 Httpclient:How Get Value from the Header of a Response
Jquery Clone() Not Cloning Event Bindings, Even with On()