# MeshBVH

class in `three-mesh-bvh`, extends `GeometryBVH`

```js
import { MeshBVH } from 'three-mesh-bvh';
```

The MeshBVH generation process modifies the geometry's index bufferAttribute in place to save
memory. The BVH construction will use the geometry's boundingBox if it exists or set it if it
does not. The BVH will no longer work correctly if the index buffer is modified.

Only triangles within the geometry's draw range (or provided `range` option) are included in the
BVH. When a geometry has multiple groups, only triangles within the defined group ranges are
included. Triangles in gaps between groups are excluded.

Note that all query functions expect arguments in local space of the BVH and return results in
local space, as well. If world space results are needed they must be transformed into world space
using `object.matrixWorld`.

Example: Casting a thousand rays at a mesh every frame

```js
import { BufferAttribute, BufferGeometry, HemisphereLight, LineBasicMaterial, LineSegments, Points, PointsMaterial, Ray, Vector3 } from 'three';
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
import { MeshBVH } from 'three-mesh-bvh';

// scene, camera and renderer are initialized here

const URL = 'https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/models/fbx/stanford-bunny.fbx';
const RAYS = 1000;
const UP = new Vector3( 0, 1, 0 );

scene.add( new HemisphereLight( 0xffffff, 0x999999, 3 ) );
camera.position.set( 5, 3, 8 );

const { children: [ bunny ] } = await new FBXLoader().loadAsync( URL );
bunny.scale.setScalar( 1 );
bunny.geometry.scale( 0.0075, 0.0075, 0.0075 );
scene.add( bunny );

const bvh = new MeshBVH( bunny.geometry );

const origins = new Array( RAYS ).fill().map( () => new Vector3().randomDirection().multiplyScalar( 3.75 ) );
const rays = new BufferGeometry();
rays.setAttribute( 'position', new BufferAttribute( new Float32Array( RAYS * 6 ), 3 ) );
scene.add(
	new LineSegments( rays, new LineBasicMaterial( { color: 0xe91e63, transparent: true, opacity: 0.25 } ) ),
	new Points( rays, new PointsMaterial( { color: 0xe91e63, size: 0.04 } ) ),
);

const ray = new Ray();
renderer.setAnimationLoop( time => {

	const position = rays.attributes.position;
	for ( let i = 0; i < RAYS; i ++ ) {

		ray.origin.copy( origins[ i ] ).applyAxisAngle( UP, time * 0.0001 );
		ray.direction.copy( ray.origin ).negate().normalize();
		const hit = bvh.raycastFirst( ray );
		const end = hit ? hit.point : ray.origin;
		position.setXYZ( 2 * i, ray.origin.x, ray.origin.y, ray.origin.z );
		position.setXYZ( 2 * i + 1, end.x, end.y, end.z );

	}

	position.needsUpdate = true;
	renderer.render( scene, camera );

} );
```

## Constructor

```js
new MeshBVH( geometry: BufferGeometry, options?: Object )
```

- `geometry`, `BufferGeometry`
- `options`, `Object`, optional: Same options as `GeometryBVH`.

## Properties

### .resolveTriangleIndex: function

readonly

Helper function for use when `indirect` is set to true. This function takes a triangle
index in the BVH layout and returns the associated triangle index in the geometry index
buffer or position attribute.

## Methods

### serialize

```js
serialize( bvh: MeshBVH, options?: Object ): SerializedBVH
```

Generates a representation of the complete bounds tree and the geometry index buffer which
can be used to recreate a bounds tree using the `deserialize` function. The `serialize` and
`deserialize` functions can be used to generate a MeshBVH asynchronously in a background web
worker to prevent the main thread from stuttering. The BVH roots buffer stored in the
serialized representation are the same as the ones used by the original BVH so they should
not be modified. If `SharedArrayBuffers` are used then the same BVH memory can be used for
multiple BVH in multiple WebWorkers.

- `bvh`, `MeshBVH`: The BVH to serialize.
- `options`, `Object`, optional
  - `cloneBuffers`, `boolean`, optional, default `true`: If `true`, the index and BVH root buffers
  are cloned so the serialized data is independent of the live BVH.

### deserialize

```js
deserialize( data: SerializedBVH, geometry: BufferGeometry, options?: Object ): MeshBVH
```

Returns a new MeshBVH instance from the serialized data. `geometry` is the geometry used
to generate the original BVH `data` was derived from. The root buffers stored in `data`
are set directly on the new BVH so the memory is shared.

- `data`, `SerializedBVH`: Serialized BVH data.
- `geometry`, `BufferGeometry`: The geometry the BVH was originally built from.
- `options`, `Object`, optional
  - `setIndex`, `boolean`, optional, default `true`: If `true`, sets `geometry.index` from the
  serialized index buffer (creating one if none exists).

### .shiftTriangleOffsets

```js
.shiftTriangleOffsets( offset: number ): void
```

Adjusts all triangle offsets stored in the BVH by the given offset. This is useful when the
triangle data has been compacted or shifted in the geometry buffers (e.g. in `BatchedMesh`
when geometries are compacted using the 'optimize' function or constructing a 'merged' BVH).
This function only adjusts the BVH to point to different triangles in the geometry. The
geometry's index buffer and/or position attributes must be updated separately to match.

- `offset`, `number`

### .raycastObject3D

```js
.raycastObject3D( object: Object3D, raycaster: Raycaster, intersects?: Array<Intersection> ): Array<Intersection>
```

A convenience function for performing a raycast based on a mesh. Results are formed like
three.js raycast results in world frame.

- `object`, `Object3D`
- `raycaster`, `Raycaster`
- `intersects`, `Array<Intersection>`, optional, default `[]`

### .refit

```js
.refit( nodeIndices?: Set<number> | Array<number> | null )
```

Refit the node bounds to the current triangle positions. This is quicker than regenerating
a new BVH but will not be optimal after significant changes to the vertices. `nodeIndices`
is a set of node indices (provided by the `shapecast` function) that need to be refit
including all internal nodes.

- `nodeIndices`, `Set<number> | Array<number> | null`, optional, default `null`

### .raycast

```js
.raycast( ray: Ray, materialOrSide?: number | Material | Array<Material>, near?: number, far?: number ): Array<Intersection>
```

Returns all raycast triangle hits in unsorted order. It is expected that `ray` is in the
frame of the BVH already. Likewise the returned results are also provided in the local
frame of the BVH. The `side` identifier is used to determine the side to check when
raycasting or a material with the given side field can be passed. If an array of materials
is provided then it is expected that the geometry has groups and the appropriate material
side is used per group.

Note that unlike three.js' Raycaster results the points and distances in the intersections
returned from this function are relative to the local frame of the MeshBVH. When using the
`acceleratedRaycast` function as an override for `Mesh.raycast` they are transformed into
world space to be consistent with three's results.

- `ray`, `Ray`
- `materialOrSide`, `number | Material | Array<Material>`, optional, default `FrontSide`
- `near`, `number`, optional, default `0`
- `far`, `number`, optional, default `Infinity`

### .raycastFirst

```js
.raycastFirst( ray: Ray, materialOrSide?: number | Material | Array<Material>, near?: number, far?: number ): Intersection | null
```

Returns the first raycast hit in the model. This is typically much faster than returning
all hits. See `raycast` for information on the side and material options as well as the
frame of the returned intersections.

- `ray`, `Ray`
- `materialOrSide`, `number | Material | Array<Material>`, optional, default `FrontSide`
- `near`, `number`, optional, default `0`
- `far`, `number`, optional, default `Infinity`

### .intersectsGeometry

```js
.intersectsGeometry( otherGeometry: BufferGeometry, geometryToBvh: Matrix4 ): boolean
```

Returns whether or not the mesh intersects the given geometry.

The `geometryToBvh` parameter is the transform of the geometry in the BVH's local frame.

Performance improves considerably if the provided geometry also has a `boundsTree`.

- `otherGeometry`, `BufferGeometry`
- `geometryToBvh`, `Matrix4`: Transform of `otherGeometry` into the local space of
  this BVH.

### .shapecast

```js
.shapecast( callbacks: Object ): boolean
```

A generalized cast function that can be used to implement intersection logic for custom
shapes. This is used internally for `intersectsBox`, `intersectsSphere`, and more. The
function returns as soon as a triangle has been reported as intersected and returns `true`
if a triangle has been intersected.

- `callbacks`, `Object`
  - `intersectsBounds`, `IntersectsBoundsCallback`
  - `intersectsTriangle`, `IntersectsTriangleCallback`, optional
  - `intersectsRange`, `IntersectsRangeCallback`, optional
  - `boundsTraverseOrder`, `BoundsTraverseOrderCallback`, optional

### .bvhcast

```js
.bvhcast( otherBvh: MeshBVH, matrixToLocal: Matrix4, callbacks: Object ): boolean
```

A generalized cast function that traverses two BVH structures simultaneously to perform
intersection tests between them. This is used internally by `intersectsGeometry`. The
function returns `true` as soon as a triangle pair has been reported as intersected by
the callbacks.

`matrixToLocal` is a Matrix4 that transforms `otherBvh` into the local space of this BVH.
The other BVH's triangles are transformed by this matrix before intersection tests.

- `otherBvh`, `MeshBVH`
- `matrixToLocal`, `Matrix4`: Transforms `otherBvh` into the local space of this BVH.
- `callbacks`, `Object`
  - `intersectsRanges`, `IntersectsRangesCallback`, optional
  - `intersectsTriangles`, `IntersectsTrianglesCallback`, optional

### .intersectsBox

```js
.intersectsBox( box: Box3, boxToBvh: Matrix4 ): boolean
```

Returns whether or not the mesh intersects the given box.

The `boxToBvh` parameter is the transform of the box in the meshes frame.

- `box`, `Box3`
- `boxToBvh`, `Matrix4`: Transform of the box in the local space of this BVH.

### .intersectsSphere

```js
.intersectsSphere( sphere: Sphere ): boolean
```

Returns whether or not the mesh intersects the given sphere.

- `sphere`, `Sphere`

### .closestPointToGeometry

```js
.closestPointToGeometry( otherGeometry: BufferGeometry, geometryToBvh: Matrix4, target1?: HitPointInfo, target2?: HitPointInfo, minThreshold?: number, maxThreshold?: number ): HitPointInfo | null
```

Computes the closest distance from the geometry to the mesh and puts the closest point on
the mesh in `target1` (in the frame of the BVH) and the closest point on the other
geometry in `target2` (in the geometry frame). If `target1` is not provided a new Object
is created and returned from the function.

The `geometryToBvh` parameter is the transform of the geometry in the BVH's local frame.

If a point is found that is closer than `minThreshold` then the function will return that
result early. Any triangles or points outside of `maxThreshold` are ignored. If no point
is found within the min / max thresholds then `null` is returned and the target objects
are not modified.

The returned faceIndex in `target1` and `target2` can be used with the standalone function
`getTriangleHitPointInfo` to obtain more information like UV coordinates, triangle normal
and materialIndex.

_Note that this function can be very slow if `geometry` does not have a
`geometry.boundsTree` computed._

- `otherGeometry`, `BufferGeometry`
- `geometryToBvh`, `Matrix4`: Transform of `otherGeometry` into the local space of
  this BVH.
- `target1`, `HitPointInfo`, optional, default `{}`
- `target2`, `HitPointInfo`, optional, default `{}`
- `minThreshold`, `number`, optional, default `0`
- `maxThreshold`, `number`, optional, default `Infinity`

### .closestPointToPoint

```js
.closestPointToPoint( point: Vector3, target?: HitPointInfo, minThreshold?: number, maxThreshold?: number ): HitPointInfo | null
```

Computes the closest distance from the point to the mesh and gives additional information
in `target`. The target can be left undefined to default to a new object which is
ultimately returned by the function.

If a point is found that is closer than `minThreshold` then the function will return that
result early. Any triangles or points outside of `maxThreshold` are ignored. If no point
is found within the min / max thresholds then `null` is returned and the `target` object
is not modified.

The returned faceIndex can be used with the standalone function `getTriangleHitPointInfo`
to obtain more information like UV coordinates, triangle normal and materialIndex.

- `point`, `Vector3`
- `target`, `HitPointInfo`, optional, default `{}`
- `minThreshold`, `number`, optional, default `0`
- `maxThreshold`, `number`, optional, default `Infinity`

Example: Finding the closest point on a mesh

```js
import { Mesh, TorusKnotGeometry, MeshNormalMaterial, MeshBasicMaterial, SphereGeometry } from 'three';
import { MeshBVH } from 'three-mesh-bvh';

// scene, camera and renderer are initialized here

const geometry = new TorusKnotGeometry( 1, 0.3, 200, 30 );
const bvh = new MeshBVH( geometry );
scene.add( new Mesh( geometry, new MeshNormalMaterial() ) );

// a point circles the knot; the red marker is the closest surface point to it
const point = new Mesh( new SphereGeometry( 0.05 ), new MeshNormalMaterial() );
const closest = new Mesh( new SphereGeometry( 0.05 ), new MeshBasicMaterial( { color: 'red' } ) );
scene.add( point, closest );

// the query writes its result straight into the marker's position
const target = { point: closest.position };
renderer.setAnimationLoop( time => {

	point.position.set( 2 * Math.cos( time / 1000 ), Math.sin( time / 700 ), 2 * Math.sin( time / 1000 ) );
	bvh.closestPointToPoint( point.position, target );
	renderer.render( scene, camera );

} );
```
