BVH intersections with mesh R3F

Hi there!
I’m struggling with a development… The idea is to “delimit” the areas where the user can put or not an object on a mesh, so I did this with a bounding box and check if the box3 intersects the mesh, then the user will be able to do that.

But I need to be more precise, because the bounding box is a box itself, but I need the BB to fit the model as much as possible, to delimit the exact zones.

For that, I have used three-mesh-bvh to generate multi bounding box… but when I check the intersections, there are some parts where hit is false, when it shouldn’t because there is an intersection…

I don’t know if I’m doing something wrong :frowning:

const checkCollision = (box: BoxBufferGeometryProps, mesh: BoxBufferGeometryProps) => {
    const transformMatrix = new THREE.Matrix4()
      .copy(mesh.matrixWorld)
      .invert()
      .multiply(box.matrixWorld);
    mesh.geometry.computeBoundsTree();

    const hit = mesh.geometry.boundsTree.intersectsBox(boxBB, transformMatrix);
    if (hit) {
      box.material.color.set('green');
      console.log('intersected!');
    } else {
      box.material.color.setHex(0xff0000);
      console.log('NOT intersected!');
    }
  };

I’m calling checkCollision() every time I move the box geometry.
when the box turns red, means that bvh found no intersection.


Screenshot 2023-04-20 at 17.19.38

doesn’t this work for you?

import { Bvh } from '@react-three/drei'

<Canvas>
  <Bvh>
    <Scene />
    ...
  </Bvh>

ps i don’t think re-calculating the boundstree on every interaction is how you normally use three-bvh. that is a very expensive function, usually only called once.

the drei component does the follow, maybe it helps if you want to do it manually without helpers:

export const Bvh = React.forwardRef(
  (
    {
      enabled = true,
      firstHitOnly = false,
      children,
      strategy = SAH,
      verbose = false,
      setBoundingBox = true,
      maxDepth = 40,
      maxLeafTris = 10,
      ...props
    },
    fref
  ) => {
    const ref = React.useRef(null)

    const raycaster = useThree((state) => state.raycaster)
    React.useImperativeHandle(fref, () => ref.current, [])

    React.useEffect(() => {
      if (enabled) {
        const options = { strategy, verbose, setBoundingBox, maxDepth, maxLeafTris }
        const group = ref.current
        // This can only safely work if the component is used once, but there is no alternative.
        // Hijacking the raycast method to do it for individual meshes is not an option as it would
        // cost too much memory ...
        raycaster.firstHitOnly = firstHitOnly
        group.traverse((child) => {
          // Only include meshes that do not yet have a boundsTree and whose raycast is standard issue
          if (isMesh(child) && !child.geometry.boundsTree && child.raycast === Mesh.prototype.raycast) {
            child.raycast = acceleratedRaycast
            child.geometry.computeBoundsTree = computeBoundsTree
            child.geometry.disposeBoundsTree = disposeBoundsTree
            child.geometry.computeBoundsTree(options)
          }
        })
        return () => {
          delete raycaster.firstHitOnly
          group.traverse((child) => {
            if (isMesh(child) && child.geometry.boundsTree) {
              child.geometry.disposeBoundsTree()
              child.raycast = Mesh.prototype.raycast
            }
          })
        }
      }
    })

    return (
      <group ref={ref} {...props}>
        {children}
      </group>
    )
  }
)

Update:

I was miscalculating the the position of the bounding box… Now it’s following the box but I would like to get true only if the whole box is intersecting the mesh… Like ‘containing’… bvh help here?

to know if bb intersects the mesh I’m using:
mesh.geometry.boundsTree.intersectsBox(boxBB, transformMatrix)

ex: the image shows that the BB crosses the mesh but not the entire box… so it should return false.
image

I’m not sure if mesh-bvh has the same functionality but in three you should be able to use containsBox instead of intersectsBox

Yep, I know three has containsBox property but as I mentioned, using boundingBox from three does not give me the accuracy I need…