2
votes

We deal with large Three.js scenes with many individual objects. It is easy to end up with scene having 25k to 50k Object3D instances. Yes, this is a lot, but we currently don't see an easy way to lower this number. Clearing such a scene by removing all objects takes usually about two minutes. This is the case for both removing each element individually with scene.remove(element); and for collecting all elements first and calling scene.remove(element1, element2, ...);. We also tried replacing the complete scene instance, but to no avail: it was still slow.

We saw some differences between different graphics cards and suspect this has to do with using a lot of buffer geometries that presumably would need to be removed from the graphics card (which then would have some influence on performance).

Since the browser is blocking during object removal, the website becomes unusable for this period of time. Do you see any way of improving object removal performance or make it non-blocking (without setTimeout() for removing individual elements)?

This shows the problem in a simplified fashion (using 50k cubes, removed after first frame, but some of our objects are much more complex): http://jsfiddle.net/ua2mg5ty/

1
Yikes. Perhaps you should be using InstancedBufferGeometry. See, for example, this and this. - WestLangley
Thanks for the pointer! If I am not mistaken, using InstanceBufferGeometry implies that individual object instances would be similar. We display many big neurons that are all very different from each other. They are currently based on LineSegments using regular Geometry instances. I suppose I could use InstanceBufferGeometry to store only a single line segment and use an offset array to instance individual line segments at the correct position. Does this make sense? - tomka
Maybe. Or use BufferGeometry. Avoid regular geometry. Be careful to call dispose() when removing objects. - WestLangley
Thanks for the pointers, InstanceBufferGeometry turned out to work nicely for me. - tomka

1 Answers

4
votes

Try mesh merge and remove a single mesh.

http://jsfiddle.net/2t8j5caj/

Removal time: 0.13500000000021828ms, Render time: 3.6000000000012733ms

var mesh = new THREE.Mesh(singleGeometry, material);
for (var i = 0; i < nCubes; i++) {
  var box = new THREE.BoxGeometry(1, 1, 1);
  var cube = new THREE.Mesh(box);
  cube.position.x = (Math.random() - 0.5) * 5;
  cube.position.y = (Math.random() - 0.5) * 5;
  cube.position.z = (Math.random() - 0.5) * 5;
  cube.scale.set((Math.random() - 1 * cubeSize), (Math.random() - 1 * cubeSize), (Math.random() - 1 * cubeSize))
  cube.updateMatrix();

  singleGeometry.merge(cube.geometry, cube.matrix);
}
var mesh = new THREE.Mesh(singleGeometry, material);
scene.add(mesh);