A high-performance C++/Cython implementation of Bounding Volume Hierarchy (BVH) for efficient ray-triangle intersection testing and spatial queries.
- Fast BVH construction for triangle meshes
- Efficient ray casting functionality
- Point-in-mesh testing
- Optimized C++ core with Python bindings
- Support for multiple Python versions (3.9+)
The package can be installed using pip:
pip install git+https://github.com/contextmachine/bvhFor other platforms, you'll need to build from source, which requires:
- A C++ compiler
- Cython
- NumPy
- Poetry (for development)
import numpy as np
from bvh import TriangleSoup
# Create a triangle mesh (n_triangles x 3 vertices x 3 coordinates)
triangles = np.array([
[[0, 0, 0], [1, 0, 0], [0, 1, 0]], # Triangle 1
[[1, 0, 0], [1, 1, 0], [0, 1, 0]], # Triangle 2
], dtype=np.float64)
# Initialize the BVH structure
soup = TriangleSoup(triangles)
# Build the BVH (required before any queries)
soup.build_bvh()
# Define rays for intersection testing
# Each ray is defined by origin and direction
rays = np.array([
[[0, 0, 1], [1, 1, -1]], # Ray 1: shooting down from above
], dtype=np.float64)
# Perform ray casting
hits, counts = soup.raycast_hits(rays)Example illustrating obtaining points inside the mesh from an array of points:
from bvh import TriangleSoup
mesh=TriangleSoup(...) # construct mesh from triangles
mesh.build_bvh()
bbx=np.array(mesh.bbox()) # Get mesh bbox
points_bbox=bbx*3 # Domain of points distribution
pts=np.random.uniform(points_bbox[0],points_bbox[1], size=(10000,3)) # generate random points
is_pt_in_bbox=np.zeros((pts.shape[0],),bool) # prepare array for an in_root_bbox test result.
mesh.in_root_bbox(pts,is_pt_in_bbox)
pts_in_bbox=pts[is_pt_in_bbox]
print(pts_in_bbox.shape) # (327, 3) May be different
is_pt_in_mesh=np.zeros((pts_in_bbox.shape[0],),dtype=bool)
mesh.points_inside(pts_in_bbox, is_pt_in_mesh)
pts_in_mesh=pts_in_bbox[is_pt_in_mesh]
print(pts_in_mesh.shape) # (68, 3) May be differentThe main class for BVH operations.
__init__(triangles): Initialize with a numpy array of trianglesbuild_bvh(): Build the BVH structurehas_bvh(): Check if BVH is builtraycast_counts(rays): Get intersection counts for raysraycast_hits(rays): Get intersection points and countspoints_inside(points): Test if points are inside the mesh
The project uses Poetry for dependency management and building. To set up a development environment:
# Clone the repository
git clone https://github.com/contextmachine/bvh.git
cd bvh
# Install dependencies
poetry install
# Build the project
poetry buildTests are written using C++ and the test suite can be built using Meson:
meson setup buildDir
cd buildDir
meson testLicensed under the Apache License, Version 2.0 - see LICENSE for details.
This BVH implementation represents a practical balance between simplicity and functionality, with several notable characteristics:
-
Clean and Efficient Structure
- Readable:The code is easy to follow. The data structures are clearly defined, and the recursive building function follows the familiar pattern of "if leaf, store object; else split and recurse."
- Array-based node layout using a single vector, improving memory locality
- Simple but effective centroid-based splitting strategy
- Memory-friendly implementation (2N-1 nodes for N objects)
-
Practical Design Choices
- Straightforward top-down recursive build process
- Splitting based on largest centroid extent - simpler than SAH but reasonably effective
- Clean separation between splitting logic and tree construction
- Focused scope: core BVH functionality without unnecessary complications
- Could use median-of-medians approach instead of full sorting
- Room for handling degenerate cases (overlapping centroids)
- Could benefit from SAH splitting for more optimal trees
- Opportunity for parallel build process in large scenes
- Small to medium sized geometric scenes. The current implementation can compute up to 2 million rays per second on a single core (Apple M1-Pro) (from python code). This may be slightly faster from c++ code depending on the application, but not by orders of magnitude.
- If you are looking for an implementation that you can easily adapt to your needs
- Projects requiring a clean, maintainable BVH implementation
- Educational contexts or reference implementations