A BVH implementation to speed up raycasting against and enable intersection tests for three.js meshes.

Casting 500 rays against an 80,000 polygon model at 60fps!

Using pre-made functions

```
// Import via ES6 modules
import * as THREE from 'three';
import { computeBoundsTree, disposeBoundsTree, acceleratedRaycast } from 'three-mesh-bvh';
// Or UMD
const { computeBoundsTree, disposeBoundsTree, acceleratedRaycast } = window.MeshBVHLib;
// Add the extension functions
THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;
THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
THREE.Mesh.prototype.raycast = acceleratedRaycast;
// Generate geometry and associated BVH
const geom = new THREE.TorusKnotBufferGeometry(10, 3, 400, 100);
const mesh = new THREE.Mesh(geom, material);
geom.computeBoundsTree();
```

Or manually building the BVH

```
// Import via ES6 modules
import * as THREE from 'three';
import { MeshBVH, acceleratedRaycast } 'three-mesh-bvh';
// Or UMD
const { MeshBVH, acceleratedRaycast } = window.MeshBVHLib;
// Add the raycast function. Assumes the BVH is available on
// the `boundsTree` variable
THREE.Mesh.prototype.raycast = acceleratedRaycast;
// ...
// Generate the BVH and use the newly generated index
geom.boundsTree = new MeshBVH(geom);
```

And then raycasting

```
// Setting "firstHitOnly" to true means the Mesh.raycast function will use the
// bvh "raycastFirst" function to return a result more quickly.
const raycaster = new THREE.Raycaster();
raycaster.firstHitOnly = true;
raycaster.intersectObjects( [ mesh ] );
```

```
const geometry = new KnotBufferGeometry( 1, 0.5, 40, 10 );
const bvh = new MeshBVH( geometry );
const serialized = MeshBVH.serialize( bvh, geometry );
// ...
const deserializedBVH = MeshBVH.deserialize( serialized, geometry );
geometry.boundsTree = deserializedBVH;
```

Option for splitting each BVH node down the center of the longest axis of the bounds.

This is the fastest construction option but will yield a less optimal hierarchy.

Option for splitting each BVH node at the average point along the longest axis for all triangle centroids in the bounds.

Option to use a Surface Area Heuristic to split the bounds optimally.

This is the slowest construction option.

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.

```
static serialize( bvh : MeshBVH, geometry : BufferGeometry, copyIndexBuffer = true : Boolean ) : 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.

`bvh`

is the MeshBVH to be serialized and `geometry`

is the bufferGeometry used to generate and raycast against using the `bvh`

.

If `copyIndexBuffer`

is true then a copy of the `geometry.index.array`

is made which is slower but useful is the geometry index is intended to be modified.

```
static deserialize( data : SerializedBVH, geometry : BufferGeometry, setIndex = true : Boolean ) : MeshBVH
```

Returns a new MeshBVH instance from the serialized data. `geometry`

is the geometry used to generate the original bvh `data`

was derived from. If `setIndex`

is true then the buffer for the `geometry.index`

attribute is set from the serialized data attribute or created if an index does not exist.

*NOTE: In order for the bounds tree to be used for casts the geometry index attribute must be replaced by the data in the SeralizedMeshBVH object.*

*NOTE: The returned MeshBVH is a fully generated, buffer packed BVH instance to improve memory footprint and uses the same buffers passed in on the data.root property.*

```
constructor( geometry : BufferGeometry, options : Object )
```

Constructs the bounds tree for the given geometry and produces a new index attribute buffer. The available options are

```
{
// Which split strategy to use when constructing the BVH.
strategy: CENTER,
// The maximum depth to allow the tree to build to.
// Setting this to a smaller trades raycast speed for better construction
// time and less memory allocation.
maxDepth: 40,
// The number of triangles to aim for in a leaf node.
maxLeafTris: 10,
// Print out warnings encountered during tree construction.
verbose: true,
// If true the bounds tree is generated progressively as the tree is used allowing
// for a fast initialization time and memory allocation as needed but a higher memory
// footprint once the tree is completed. The initial raycasts are also slower until the
// tree is built up.
// If false then the bounds tree will be completely generated up front and packed into
// an array buffer for a lower final memory footprint and long initialization time.
lazyGeneration: true
}
```

*NOTE: The geometry's index attribute array is modified in order to build the bounds tree. If the geometry has no index then one is added.*

```
raycast( mesh : Mesh, raycaster : Raycaster, ray : Ray, intersects : Array) : Array<RaycastHit>
```

Adds all raycast triangle hits in unsorted order to the `intersects`

array. It is expected that `ray`

is in the frame of the mesh being raycast against and that the geometry on `mesh`

is the same as the one used to generate the bvh.

```
raycastFirst( mesh : Mesh, raycaster : Raycaster, ray : Ray) : RaycastHit
```

Returns the first raycast hit in the model. This is typically much faster than returning all hits.

```
intersectsSphere( mesh : Mesh, sphere : Sphere ) : Boolean
```

Returns whether or not the mesh instersects the given sphere.

```
intersectsBox( mesh : Mesh, 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 meshs frame.

```
intersectsGeometry( mesh : Mesh, geometry : 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 mesh's frame.

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

.

```
closestPointToPoint( mesh : Mesh, point : Vector3, target : Vector3 ) : Number
```

Returns the closest distance from the point to the mesh and puts the closest point on the mesh in `target`

.

```
closestPointToGeometry(
mesh : Mesh,
geometry : BufferGeometry,
geometryToBvh : Matrix4,
target1 : Vector3,
target2 : Vector3
) : Number
```

Returns the closest distance from the geometry to the mesh and puts the closest point on the mesh in `target1`

and the closest point on the other geometry in `target2`

in the frame of the BVH.

The `geometryToBvh`

parameter is the transform of the geometry in the mesh's frame.

```
roots : Array< ArrayBuffer >
```

```
index : TypedArray
```

Displays a view of the bounds tree up to the given depth of the tree.

*Note: The visualizer is expected to be a sibling of the mesh being visualized.*

```
depth : Number
```

The depth to traverse and visualize the tree to.

```
constructor( mesh: THREE.Mesh, depth = 10 : Number )
```

Instantiates the helper with a depth and mesh to visualize.

```
update() : void
```

Updates the display of the bounds tree in the case that the bounds tree has changed or the depth parameter has changed.

```
firstHitOnly = false : Boolean
```

The the `Raycaster`

member `firstHitOnly`

is set to true then the .acceleratedRaycast function will call the .raycastFirst function to retrieve hits which is generally faster.

```
computeBoundsTree( options : Object ) : void
```

A pre-made BufferGeometry extension function that builds a new BVH, assigns it to `boundsTree`

, and applies the new index buffer to the geometry. Comparable to `computeBoundingBox`

and `computeBoundingSphere`

.

```
THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;
```

```
disposeBoundsTree() : void
```

A BufferGeometry extension function that disposes of the BVH.

```
THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
```

```
acceleratedRaycast( ... )
```

An accelerated raycast function with the same signature as `THREE.Mesh.raycast`

. Uses the BVH for raycasting if it's available otherwise it falls back to the built-in approach.

If the raycaster object being used has a property `firstHitOnly`

set to `true`

, then the raycasting will terminate as soon as it finds the closest intersection to the ray's origin and return only that intersection. This is typically several times faster than searching for all intersections.

```
THREE.Mesh.prototype.raycast = acceleratedRaycast;
```

```
estimateMemoryInBytes( bvh : MeshBVH ) : Number
```

Roughly estimates the amount of memory in bytes a BVH is using.

```
getBVHExtremes( bvh : MeshBVH ) : Array< Object >
```

Measures the min and max extremes of the tree including node depth, leaf triangle count, and number of splits on different axes to show how well a tree is structured. Returns an array of extremes for each group root for the bvh. The objects are structured like so:

```
{
depth: { min: Number, max: Number },
tris: { min: Number, max: Number },
splits: [ Number, Number, Number ]
}
```

- This is intended to be used with complicated, high-poly meshes. With less complex meshes, the benefits are negligible.
- A bounds tree can be generated for either an indexed or non-indexed
`BufferGeometry`

, but an index will be produced and retained as a side effect of the construction. - The bounds hierarchy is
*not*dynamic, so geometry that uses morph targets cannot be used. - If the geometry is changed then a new bounds tree will need to be generated.
- Only BufferGeometry (not Geometry) is supported when building a bounds tree.
- InterleavedBufferAttributes are not supported on the geometry index or position attributes.
- A separate bounds tree is generated for each geometry group, which could result in poorer raycast performance on geometry with lots of groups.
- Due to errors related to floating point precision it is recommended that geometry be centered using
`BufferGeometry.center()`

before creating the BVH if the geometry is sufficiently large or off center. - Geometry with a lot of particularly long triangles on one axis can lead to a less than optimal bounds tree (see #121).

Get A Weekly Email With Trending Projects For These Topics

No Spam. Unsubscribe easily at any time.

javascript (66,040)Â

performance (559)Â

graphics (387)Â

threejs (200)Â

tree (168)Â

geometry (96)Â

mesh (73)Â

distance (31)Â

three-js (27)Â

acceleration (17)Â