gkjohnson / three-mesh-bvh

A BVH implementation to speed up raycasting and enable spatial queries against three.js meshes.
https://gkjohnson.github.io/three-mesh-bvh/example/bundle/raycast.html
MIT License
2.38k stars 247 forks source link

InstancedMesh example #661

Closed melicheradam closed 1 month ago

melicheradam commented 1 month ago

Is your feature request related to a problem? Please describe.

It is very unclear how to use this library with an InstancedMesh containing many instances of the same geometry.

Describe the solution you'd like

A clear and concise example how to use this, and even more how to use raycasting to get intersected objects. For example what im trying to do is, simply get the index of clicked object.

Describe alternatives you've considered

I have thoroughly checked the existing examples, yet nothing of use was found. One close example is the pointcloud, but even that one just copies the intersected position.

Additional context

Even when using the mesh.geometry.computeBoundsTree();, my bounds tree looks like this which seem incorrect and I honestly dont know what to do

image

Relevant part of code


 displayedData = data;

    //const sphereGeometry = new THREE.SphereGeometry(1, 32, 32); // Radius set to 1, adjust as needed
    const sphereGeometry = new THREE.IcosahedronGeometry( 0.5, 2 )
    const sphereMaterial = new THREE.MeshPhongMaterial();

    const instanceMesh = new THREE.InstancedMesh(sphereGeometry, sphereMaterial, displayedData.length);
    mesh = instanceMesh;
    //mesh.geometry.boundsTree = new MeshBVH( mesh.geometry );
    //mesh.castShadow = true;
    //mesh.receiveShadow = true;

    // Add each instance to the mesh
    const matrix = new THREE.Matrix4();
    displayedData.forEach((obj, i) => {
        matrix.setPosition( obj.x, obj.y, obj.z );
        instanceMesh.setMatrixAt( i, matrix );
        instanceMesh.setColorAt( i, new THREE.Color(obj.color) );
    });

    mesh.geometry.computeBoundsTree();
    helper = new MeshBVHHelper( mesh, 10 );
    scene.add(helper)

    // Create a points mesh and add it to the scene
    instanceMesh.name = "points"
    scene.add(instanceMesh);
gkjohnson commented 1 month ago

A clear and concise example how to use this, and even more how to use raycasting to get intersected objects. For example what im trying to do is, simply get the index of clicked object.

There's nothing different that has to be done for instanced mesh. You can access the intersected instance the same way you can with the native three.js raycast functionality:

const hit = raycaster.intersectObjects( scene.children )[ 0 ] || null;
if ( hit ) {

  // the instance id of 
  console.log( hit.instanceId );

}  

Here's a jsfiddle showing how:

https://jsfiddle.net/87e95yzx/7/

Is that what you're looking for?

Even when using the mesh.geometry.computeBoundsTree();, my bounds tree looks like this which seem incorrect...

The BVH is only generated for the single geometry and reused, and the helper is positioned at the origin of the passed in InstancedMesh. No BVH is generated for the set of instances at the moment. Perhaps it would be more clear to show the helper at the position of the first element in the InstancedMesh?