Zurück zum Ranking

A BVH implementation to speed up raycasting and enable spatial queries against three.js meshes.

graphicsraycasttreeboundsthreejsthree-jsbounds-hierarchyperformancegeometrymeshdistanceintersection
Sterne-Wachstum
Sterne
3.4k
Forks
331
Wochenwachstum
Issues
78
1k2k3k
Mai 2018Jan. 2021Okt. 2023Juli 2026
Artefaktenpmnpm install three-mesh-bvh
README

three-mesh-bvh

npm version build github twitter sponsors

A Bounding Volume Hierarchy (BVH) implementation to speed up raycasting and enable spatial queries against three.js meshes. See the associated Wikipedia article for more information on bounding volume hierarchies and how they work.

screenshot

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

Examples

Raycasting

Skinned geometry

Point cloud intersection

Line intersection

Shape intersection

Geometry edge intersection

SDF generation

WebWorker generation

BVH options inspector

BatchedMesh Raycasting

Tools

Sculpting

Distance comparison

Triangle painting

Lasso selection

Clipped edges

Geometry voxelization

Games

Sphere physics collision

Player movement

Path Tracing

Simple GPU Path Tracing

Lambert GPU Path Tracing

CPU Path Tracing

Gem Refraction Path Tracing

Object Hierarchy BVH

Accelerated Scene Raycasting

Skinned Meshes

Frustum Culling

External Projects

three-gpu-pathtracer

three-bvh-csg

three-edge-projection

Use

Using pre-made functions

import * as THREE from 'three';
import {
	computeBoundsTree, disposeBoundsTree,
	computeBatchedBoundsTree, disposeBatchedBoundsTree, acceleratedRaycast,
} from 'three-mesh-bvh';

// Add the extension functions
THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;
THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
THREE.Mesh.prototype.raycast = acceleratedRaycast;

THREE.BatchedMesh.prototype.computeBoundsTree = computeBatchedBoundsTree;
THREE.BatchedMesh.prototype.disposeBoundsTree = disposeBatchedBoundsTree;
THREE.BatchedMesh.prototype.raycast = acceleratedRaycast;

// Generate geometry and associated BVH
const geom = new THREE.TorusKnotGeometry( 10, 3, 400, 100 );
const mesh = new THREE.Mesh( geom, material );
geom.computeBoundsTree();

// Or generate BatchedMesh and associated BVHs
const batchedMesh = new THREE.BatchedMesh( ... );
const geomId = batchedMesh.addGeometry( geom );
const instId = batchedMesh.addGeometry( geom );

// Generate bounds tree for sub geometry
batchedMesh.computeBoundsTree( geomId );

Or manually building the BVH

import * as THREE from 'three';
import { MeshBVH, acceleratedRaycast } from 'three-mesh-bvh';

// 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 ] );

Additional Geometry BVHs

In addition to MeshBVH for triangle meshes, the library provides specialized BVH implementations for other geometry types:

  • PointsBVH - For THREE.Points geometries
  • LineBVH - For THREE.Line geometries
  • LineLoopBVH - For THREE.LineLoop geometries
  • LineSegmentsBVH - For THREE.LineSegments geometries

These can be used with the extension functions by passing a type option into "computeBoundsTree" or constructing them explicitly:

import { PointsBVH } from 'three-mesh-bvh';

// For point clouds
THREE.Points.prototype.raycast = acceleratedRaycast;

const points = new THREE.Points( geometry, material );
geometry.computeBoundsTree( { type: PointsBVH } );

// Or create directly
geometry.boundsTree = new PointsBVH( geometry );

Each BVH type implements a core API including shapecast & raycastObject3D for its specific primitive type. See the point cloud intersection & line intersection examples for a working demonstration. Some features like webworker-generation and serialization are not supported at the moment.

Additional BVHs

A SkinnedMeshBVH for SkinnedMeshes and ObjectBVH for constructing scene-wide BVH to query a hierarchy of objects. These are recently added so the APIs may change over time.

Querying the BVH Directly

import * as THREE from 'three';
import { MeshBVH, acceleratedRaycast } from 'three-mesh-bvh';

let mesh, geometry;
const invMat = new THREE.Matrix4();

// instantiate the geometry

// ...

const bvh = new MeshBVH( geometry );
invMat.copy( mesh.matrixWorld ).invert();

// raycasting
// ensure the ray is in the local space of the geometry being cast against
raycaster.ray.applyMatrix4( invMat );
const hit = bvh.raycastFirst( raycaster.ray );

// results are returned in local spac, as well, so they must be transformed into
// world space if needed.
hit.point.applyMatrixWorld( mesh.matrixWorld );

// spherecasting
// ensure the sphere is in the local space of the geometry being cast against
sphere.applyMatrix4( invMat );
const intersects = bvh.intersectsSphere( sphere );

Serialization and Deserialization

const geometry = new KnotGeometry( 1, 0.5, 40, 10 );
const bvh = new MeshBVH( geometry );
const serialized = MeshBVH.serialize( bvh );

// ...

const deserializedBVH = MeshBVH.deserialize( serialized, geometry );
geometry.boundsTree = deserializedBVH;

Asynchronous Generation

NOTE WebWorker syntax is inconsistently supported across bundlers and sometimes not supported at all so the GenerateMeshBVHWorker class is exported separately via three-mesh-bvh/worker subpath. If needed the code from src/worker can be copied and modified to accommodate a particular build process.

import { GenerateMeshBVHWorker } from 'three-mesh-bvh/worker';

// ...

const geometry = new KnotGeometry( 1, 0.5, 40, 10 );
const worker = new GenerateMeshBVHWorker();
worker.generate( geometry ).then( bvh => {

    geometry.boundsTree = bvh;

} );

Parallel BVH generation is also supported using "ParallelMeshBVHWorker", which requires support for SharedArrayBuffer. If SharedArrayBuffer is not available it falls back to "GenerateMeshBVHWorker". It is recommended that geometry passed to this function have position and index with SharedArrayBuffer arrays, otherwise buffer copies must be made.

import { ParallelMeshBVHWorker } from 'three-mesh-bvh/worker';

// ...

const geometry = new KnotGeometry( 1, 0.5, 40, 10 );
const worker = new ParallelMeshBVHWorker();
worker.generate( geometry ).then( bvh => {

    geometry.boundsTree = bvh;

} );

BVH Queries in a Shader

See the shader implementation in the simple GPU Path Tracing example for an example on how to perform BVH ray queries in a shader. Or the GPU SDF Generation example for how to perform distance and closest point to point queries in a shader.

API

See API.md for full API documentation.

See WEBGPU_API.md for the WebGPU API documentation.

Gotchas

  • When querying the MeshBVH directly all shapes and geometry are expected to be specified in the local frame of the BVH. When using three.js' built in raycasting system all results are implicitly transformed into world coordinates.
  • 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 unless the "indirect" option is used.
  • The bounds hierarchy is not dynamic, so geometry that uses morph targets or skinning cannot be used. Though if vertex positions are modified directly the refit function can be used to adjust the bounds tree.
  • If the geometry is changed then a new bounds tree will need to be generated or refit.
  • InterleavedBufferAttributes are not supported with the geometry index buffer attribute.
  • A separate bounds tree root is generated for each geometry group, which could result in less than optimal raycast performance on geometry with lots of groups. Triangles excluded from these groups are not included in the BVH.
  • 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 so bounds tightly contain the geometry as much as possible.

Running Examples Locally

To run the examples locally:

  • Run npm start
  • Then visit localhost:5173/<demo-name>.html

Where <demo-name> is the name of the HTML file from example folder.

Used and Supported by

...and more!

Ähnliche Repositories
jgraph/drawio-desktop

Official electron build of draw.io

JavaScriptnpmApache License 2.0javascript-applicationselectron-app
diagrams.net
62.2k5.7k
aseprite/aseprite

Animated sprite editor & pixel art tool (Windows, macOS, Linux)

C++animationpixel-art
aseprite.org
38.2k8.4k
raysan5/raylib

A simple and easy-to-use library to enjoy videogames programming

Czlib Licenseraylibc
raylib.com
34k3.2k
iced-rs/iced

A cross-platform GUI library for Rust, inspired by Elm

Rustcrates.ioMIT Licenseguigraphics
iced.rs
31k1.6k
GraphiteEditor/Graphite

Community-built comprehensive 2D content creation appplication for graphic design, digital art, and interactive real-time motion graphics powered by a node-based procedural graphics engine

Rustcrates.ioApache License 2.0graphics-editorphoto-editor
graphite.art
26.6k1.2k
lvgl/lvgl

Embedded graphics library to create beautiful UIs for any MCU, MPU and display type.

CMIT Licenseembeddedgui
lvgl.io
24.2k4.3k
ssloy/tinyrenderer

A brief computer graphics / rendering course

C++Otheropenglc-plus-plus
haqr.eu/tinyrenderer/
23.9k2.3k
processing/p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. Looking for p5.js 2.0? http://beta.p5js.org

JavaScriptnpmGNU Lesser General Public License v2.1javascriptgraphics
p5js.org
23.8k3.8k
rough-stuff/rough

Create graphics with a hand-drawn, sketchy, appearance

HTMLMIT Licensedrawcanvas
roughjs.com
21.1k664
google/filament

Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WebGL2

C++Apache License 2.0pbrgraphics
google.github.io/filament/
20.3k2.2k
lettier/3d-game-shaders-for-beginners

🎮 A step-by-step guide to implementing SSAO, depth of field, lighting, normal mapping, and more for your 3D game.

C++shaders3d
lettier.github.io/3d-game-shaders-for-beginners/index.html
19.8k1.5k
mojs/mojs

The motion graphics toolbelt for the web

CoffeeScriptMIT Licensewebgraphics
mojs.github.io
18.7k889