12
votes

I figured out how to draw a line in threejs, the problem is that I need to dynamically add vertices to the line. When I add vertices to the line dynamically the scene doesn't update.

I've tried geometry.verticesNeedUpdate = true, which doesn't seem to work.

3

3 Answers

15
votes

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

5
votes

I ran into this a couple of days ago too. As WestLangley said, you can't do true dynamic geometry out of the box, but alteredq has a couple of strategies for 'faking it' and achieving the desired effect at https://github.com/mrdoob/three.js/issues/342.

In regards to your comment on the last answer, don't just remove and re-add a new line from the scene each frame - you'll (most likely) incur a massive performance hit. You need to use either the first or second of alteredq's workaround strategies.

In my app I used option 1 like this:

  1. Create a THREE.Geometry object in advance and initialise it with as many vertices as you think you'll need (or otherwise a fairly high number of vertices). (You'll also need to hide them somehow before you want to display them - I set their positions to be off screen.)

  2. Create a THREE.Line object with that geometry and add to the scene.

  3. Now, when you want to add a new point to the line you'll have to index into the geometry object's vertices, find the last unused one in there, and update it - change the coordinates to the real ones, and set geometry.verticesNeedUpdate = true; (otherwise it thinks nothing changed). (See How to do updates on the wiki.)

I'm still ironing out the kinks on my approach, but that should at least let you get a line drawing on screen.

three.js r55

2
votes

As WestLangley's answer says, you can't do that. Here is the admittedly hacky workaround I have decided to use:

  • Allocate more vertices than I need by filling geometry.vertices with the starting point of my line
  • As new points come in that I want to add, shift the contents of the array to the left and write the new point in the last array entry of geometry.vertices

Code: To create a new line:

function createNewLine(startingPoint){
    var geometry = new THREE.Geometry();
    for (i=0; i<MAX_LINE_POINTS; i++){
    geometry.vertices.push(startingPoint.clone());
    }
    myLine = new THREE.Line(geometry, lineMaterial);
    myLine.geometry.dynamic = true;
    scene.add(myLine);
    render();
}

To add a point to the line:

function addPoint(myPoint) {
    myLine.geometry.vertices.push(myLine.geometry.vertices.shift()); //shift the array
    myLine.geometry.vertices[maxLinePoints-1] = myPoint; //add the point to the end of the array
    myLine.geometry.verticesNeedUpdate = true;
    render();
}

What you end up with then is a Line that has a bunch of points piled up on top of each other followed by the points you actually want to render. I submitted an issue on the three.js git repository for a simpler solution to this problem. https://github.com/mrdoob/three.js/issues/4716