Scott Thiessen
Scott Thiessen

Reputation: 875

Adding & removing vertices from THREE.LineSegment

I've got a THREE.LineSegments object, and I want to change the number of vertices dynamically. When I modify the geometry vertices array, though, any lines with vertices that were removed just stay put.

Is there a way to remove vertices after the geometry has been created?

e.g., Below I'm taking a LineSegments object with 3 segments, and trying to change it later to have only 2 segments. The last line segment remains.

var scene,
    renderer,
    camera;

var line;

initScene();
initLine();

setInterval(update, 500);


function initScene() {

  camera   = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000),
  scene    = new THREE.Scene();
  renderer = new THREE.WebGLRenderer();

  camera.position.z = 5;
  scene.add(camera);

  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

}

function initLine() {

  var verts = [
    randomV3(),
    randomV3(),
    randomV3(),
    randomV3()
  ];

  var geom = new THREE.Geometry();

  geom.vertices = [
    verts[0], verts[1],
    verts[1], verts[2],
    verts[2], verts[3]
  ];

  line = new THREE.LineSegments(geom, new THREE.LineBasicMaterial({
    color: 0xff00ff,
    linewidth: 3
  }));

  scene.add(line);
  renderer.render(scene, camera);

}

function update() {

  var verts = [
    randomV3(),
    randomV3(),
    randomV3()
  ];

  line.geometry.vertices = [
    verts[0], verts[1],
    verts[1], verts[2]
  ];
  line.geometry.verticesNeedUpdate = true;

  renderer.render(scene, camera);

}

function randomV3() {
  return new THREE.Vector3(
    (Math.random() * 4) - 2,
    (Math.random() * 4) - 2,
    0
  )
}
body {
  margin: 0;
  padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/103/three.min.js"></script>

Upvotes: 4

Views: 1400

Answers (1)

Mugen87
Mugen87

Reputation: 31026

One approach to solve this problem is to dispose the old geometry and then create a new one like so:

line.geometry.dispose();

line.geometry = new THREE.Geometry();

line.geometry.vertices = [
  verts[0], verts[1],
  verts[1], verts[2]
];

This approach is demonstrated in the following fiddle. However, consider to use THREE.BufferGeometry in order to have a more future-proof solution (THREE.Geometry will not be renderable at some point anymore). Here is a fiddle with the same code but with THREE.BufferGeometry.

Instead of disposing the geometry, you could also create a THREE.BufferGeometry with enough buffer space so it can represent the biggest line object in your application. This approach is necessary since you can't resize buffers, only update their contents. The details are explained in this guide:

https://threejs.org/docs/index.html#manual/en/introduction/How-to-update-things

BTW: Setting linewidth has no effect when rendering line primitives in three.js. The always have the width of 1 pixel.

three.js R103

Upvotes: 4

Related Questions