5

I am using Three.js r83.

I am trying to dynamically add points to a geometry, but the scene never gets updated.

This works :

var tmaterial = new THREE.PointsMaterial({
    color: 0xff0000,
    size: 5,
    opacity: 1
});

var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);

for(var i = 0; i< 1000; i++) {
    x = (Math.random() * 200) - 100;
    y = (Math.random() * 200) - 100;
    z = (Math.random() * 200) - 100;
    tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.computeVertexNormals();

scene.add(pointCloud);

This doesn't work:

var tmaterial = new THREE.PointsMaterial({
    color: 0xff0000,
    size: 5,
    opacity: 1
});

var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
scene.add(pointCloud);

for(var i = 0; i< 1000; i++) {
    x = (Math.random() * 200) - 100;
    y = (Math.random() * 200) - 100;
    z = (Math.random() * 200) - 100;
    tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.elementsNeedUpdate = true;
tgeometry.computeVertexNormals();
renderer.render(scene, camera);

As you can see, the only difference is the fact that I add scene.add(pointCloud); before adding vertexes.

What do I miss?

You can find a fiddle Thanks to @hectate

To see what I means, just replace

init(); setPoints(); animate();

by

init(); animate(); setPoints();

7
  • What is your version of three.js? Check also documentation here on how to update things... Commented Dec 16, 2016 at 14:57
  • 2
    See stackoverflow.com/questions/36699389/… and stackoverflow.com/questions/31399856/…. Commented Dec 18, 2016 at 2:16
  • @WestLangley I am currently exploring the BufferGeometry, it seems like the number of points is fixed though. Commented Dec 18, 2016 at 2:59
  • 1
    The max number is. The rendered number is not. Study the 2nd link I posted. Commented Dec 18, 2016 at 3:04
  • 1
    From trial and error method, requesting animation frame before rendering this one, is like the worst thing you can do, just wrong, at your own risk there. and if true, why has no one noticed? Commented Aug 7, 2020 at 20:26

2 Answers 2

6

I am not sure why the THREE.Geometry object doesn't update Points after initial rendering, but I got it working with a THREE.BufferGeometry instead.

Thanks to @Hectate who got a working fiddle for me and @WestLangley who directed me to the hints, here is the working fiddle

BufferGeometry has a fixed number of Vertices, but you can decide how many of them you want to render. The trick is to make use of geometry.attributes.position.needsUpdate = true; and geometry.setDrawRange( 0, nbPointsYouWantToDisplay );

var MAX_POINTS = 1000000;
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array( MAX_POINTS * 3 ); 
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );

Then you can create your cloudpoints and add it to the scene:

//material and scene defined in question
pointCloud = new THREE.Points(geometry, material);
scene.add(pointCloud);

Now I want to add and render 500 new points every 10 milliseconds.

var nbPoints = 500;
var INTERVAL_DURATION = 10;

All I have to do is :

var interval = setInterval(function() {
  setPoints();
}, INTERVAL_DURATION)

function setPoints() {

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

  var x, y, z, index;

  var l  = currentPoints + nbPoints;
  if(l >= MAX_POINTS) {
    clearInterval(interval);
  }

  for ( var i = currentPoints; i < l; i ++ ) {
    x = ( Math.random() - 0.5 ) * 300;
    y = ( Math.random() - 0.5 ) * 300;
    z = ( Math.random() - 0.5 ) * 300;
    positions[ currentPointsIndex ++ ] = x;
    positions[ currentPointsIndex ++ ] = y;
    positions[ currentPointsIndex ++ ] = z;
  }
  currentPoints = l;
  pointCloud.geometry.attributes.position.needsUpdate = true;   
  pointCloud.geometry.setDrawRange( 0, currentPoints );  
  controls.update();
  renderer.render(scene, camera);

}
Sign up to request clarification or add additional context in comments.

1 Comment

three.js moved away from Geometry in favor of BufferGeometry as you found out. Of course that's easy for me to say in 2021 ( ;
3

Here's a fiddle with your first setup installed: https://jsfiddle.net/87wg5z27/236/

var scene, renderer, camera;
var cube;
var controls;

init();
animate();

function init()
{
    renderer = new THREE.WebGLRenderer( {antialias:true} );
    var width = window.innerWidth;
    var height = window.innerHeight;
    renderer.setSize (width, height);
    document.body.appendChild (renderer.domElement);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
    camera.position.y = 160;
    camera.position.z = 400;
    camera.lookAt (new THREE.Vector3(0,0,0));

    controls = new THREE.OrbitControls (camera, renderer.domElement);

    var tmaterial = new THREE.PointsMaterial({
      color: 0xff0000,
      size: 5,
      opacity: 1
   });

   var tgeometry = new THREE.Geometry();
   var pointCloud = new THREE.Points(tgeometry, tmaterial);

   for(var i = 0; i< 1000; i++) {
     x = (Math.random() * 200) - 100;
     y = (Math.random() * 200) - 100;
     z = (Math.random() * 200) - 100;
     tgeometry.vertices.push(new THREE.Vector3(x, y, z));
   }
   tgeometry.verticesNeedUpdate = true;
   tgeometry.computeVertexNormals();

   scene.add(pointCloud);

   window.addEventListener ('resize', onWindowResize, false);
}

function onWindowResize ()
{
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize (window.innerWidth, window.innerHeight);
}

function animate()
{
    controls.update();
    requestAnimationFrame ( animate );  
    renderer.render (scene, camera);
}

Here's one with your second: https://jsfiddle.net/87wg5z27/237/

var scene, renderer, camera;
var cube;
var controls;

init();
animate();

function init()
{
    renderer = new THREE.WebGLRenderer( {antialias:true} );
    var width = window.innerWidth;
    var height = window.innerHeight;
    renderer.setSize (width, height);
    document.body.appendChild (renderer.domElement);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
    camera.position.y = 160;
    camera.position.z = 400;
    camera.lookAt (new THREE.Vector3(0,0,0));

    controls = new THREE.OrbitControls (camera, renderer.domElement);

    var tmaterial = new THREE.PointsMaterial({
      color: 0xff0000,
      size: 5,
      opacity: 1
    });

    var tgeometry = new THREE.Geometry();
    var pointCloud = new THREE.Points(tgeometry, tmaterial);
    scene.add(pointCloud);

    for(var i = 0; i< 1000; i++) {
     x = (Math.random() * 200) - 100;
     y = (Math.random() * 200) - 100;
     z = (Math.random() * 200) - 100;
     tgeometry.vertices.push(new THREE.Vector3(x, y, z));
    }
    tgeometry.verticesNeedUpdate = true;
    tgeometry.elementsNeedUpdate = true;
    tgeometry.computeVertexNormals();
    renderer.render(scene, camera);

    window.addEventListener ('resize', onWindowResize, false);
}

function onWindowResize ()
{
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize (window.innerWidth, window.innerHeight);
}

function animate()
{
    controls.update();
    requestAnimationFrame ( animate );  
    renderer.render (scene, camera);
}

In both cases the point cloud shows for me perfectly fine (release 82). Perhaps there is something else missing where you're neglecting to render something? I notice that your first example doesn't show at what step you call render(). I hope this helps!

1 Comment

Hi @Hectate, Thank you very much for the fiddle, I should have created one - really thank you. I did another fiddle that shows case my problem - see updated question. jsfiddle.net/jjjaLv3e/2 I want to update the PointCloud after it has been rendered.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.