Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
90 views
in Technique[技术] by (71.8m points)

javascript - Drawing a line with three.js dynamically

This is what I'd like to achieve (a modifiable polygon where the red circles are vertices) and I'd like to build the polygon dynamically.

enter image description here

When initiating the geometry as

var geometry = new THREE.Geometry();

geometry.vertices.push(point);
geometry.vertices.push(point);

var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({}));

it works well until the second click, it builds a straight line between 1 and 2 but does not add a third line when it's pushed to the array. WebGL seems to require buffered points.

When I predefine vertices like this I can draw two lines (third click)

var geometry = new THREE.Geometry();

for (var i = 0; i < 4; i++) {
    geometry.vertices.push(point);
}

var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({}));

but this is not a good solution as I don't know how many vertices does the user want to add and it's pointless to assign it a big number as I have to loop it multiple times.

Is there any way around it?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.

var MAX_POINTS = 500;

// geometry
var geometry = new THREE.BufferGeometry();

// attributes
var positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );

// draw range
drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );

// material
var material = new THREE.LineBasicMaterial( { color: 0xff0000 } );

// line
line = new THREE.Line( geometry,  material );
scene.add( line );

You set the position data using a pattern like this one:

var positions = line.geometry.attributes.position.array;

var x = y = z = index = 0;

for ( var i = 0, l = MAX_POINTS; i < l; i ++ ) {

    positions[ index ++ ] = x;
    positions[ index ++ ] = y;
    positions[ index ++ ] = z;

    x += ( Math.random() - 0.5 ) * 30;
    y += ( Math.random() - 0.5 ) * 30;
    z += ( Math.random() - 0.5 ) * 30;

}

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.


EDIT: See this answer for a technique that you may like better -- especially if the line consists of only a few points.

three.js r.84


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...