javascriptmergethree.jsgeometryoctree

three.js merge geometry and octree selection


I am using Three.js to show a number of custom geometry's in various positions and rotations. They are static and rarely change, but the user can add, delete or change the shape of each individual object.

This has worked well using the code snippet below:

var Mat=new THREE.MeshBasicMaterial( { color: 0xffff00, wireframe: false,  opacity: 0.5 , transparent:true} )
var Geo=new THREE.CubeGeometry( 20, 100, 20 )
var Mesh=new THREE.Mesh(Geo, Mat);

//Up or down rotation
m = new THREE.Matrix4().set(0.3,-0.3,0,0,0.3,0.3,0,0,0,0,1,0)
Mesh.applyMatrix(m);
Mesh.updateMatrix();

Mesh.position.x=50;
Mesh.position.y=50;
Mesh.position.z=50;
octree.add(Mesh);
Mesh.updateMatrix();

scene.add( Mesh );

The above works fine, although unsurprisingly it struggles with large number of objects. With reference to: https://gamedev.stackexchange.com/questions/81570/merging-geometry-mesh-without-losing-benefits

I have merged the objects and have had great success with speed increase, it runs well at 10,000+ objects. I am now trying to set up the selection again and here I am getting stuck.

The above link suggests that keeping the mesh in an array or octree will enable selection while keeping the speed benefits of the merged objects. I am already have an octree implemented so this should be simple to use again but the selection objects are now not in the same position as the merged scene object(s). The selection objects are found at the origin, it seems that the octree looses the position, and maybe the rotation, of its object(s). A snap shot of the troublesome code is below:

var TotalGeo = new THREE.Geometry();
//Add Objects
var Mat=new THREE.MeshBasicMaterial( { color: 0xffff00, wireframe: false,  opacity: 0.5 , transparent:true} )
var Geo=new THREE.CubeGeometry( 20, 100, 20 )
var Mesh=new THREE.Mesh(Geo, Mat);

//Up or down rotation
m = new THREE.Matrix4().set(0.3,-0.3,0,0,0.3,0.3,0,0,0,0,1,0)
Mesh.applyMatrix(m);
Mesh.updateMatrix();

Mesh.position.x=50;
Mesh.position.y=50;
Mesh.position.z=50;
octree.add(Mesh);
Mesh.updateMatrix();

//scene.add( Mesh );
TotalGeo.merge( Mesh.geometry, Mesh.matrix );

//Add merged geo 
var total = new THREE.Mesh(TotalGeo, Mat);
scene.add(total);

The manual rotation and position is needed for the custom geometry. Any ideas welcome! Thanks


Solution

  • When setting up your octree make sure undeferred is set to true. Like this -

    octree = new THREE.Octree( {
        undeferred: true,
        depthMax: Infinity,
        objectsThreshold: 8,
        overlapPct: 0.15
      } );
    

    That should do the trick!