# Bonxai: a small header-only sparse voxel grid for C++

> Bonxai is a compact, header-only implementation of a sparse hierarchical voxel grid, strongly influenced by OpenVDB and considerably simpler than it, with a core of under a thousand lines that you can copy into a project. It is fast for updates and iteration, it costs more memory than Octomap on very sparse data, and it is not thread-safe for writes.

**facontidavide/Bonxai** — Fast, hierarchical, sparse Voxel Grid

- Repository: https://github.com/facontidavide/Bonxai
- Stars: 886 · Forks: 98
- Language: C++
- License: MPL-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/facontidavide-bonxai

## The problem: a grid too large to hold in memory

A voxel grid is the obvious way to represent a volume: a three-dimensional array of cells. It is also the obvious way to run out of memory, because the array is allocated in full whether or not you fill it. A room-sized volume at one centimetre resolution is a hundred million cells, and a building is a billion.

Sparse grids fix this by allocating only the parts of the space that contain something. The cost is that you now have a data structure with an internal hierarchy, and the question becomes which one to use.

Bonxai is a library that implements a compact hierarchical data structure that can store and manipulate volumetric data, discretized on a three-dimensional grid. Two properties are named as the defining ones. It is sparse, using only a fraction of the memory that a dense three-dimensional voxel grid would use. And it is unbounded, because you do not need to define the boundary of the three-dimensional space.

The unbounded part is worth quantifying, because the number is memorable. Thirty-two-bit indices are used, so with a voxel size of one centimetre the maximum range of the X, Y and Z coordinates is about 40,000 kilometres. The documentation puts that in context by noting that the diameter of the Earth is 12,000 kilometres.

The audience is a C++ developer working in robotics, mapping or simulation who needs a volume that is mostly empty, and who wants the structure to be small enough to read. The project says plainly that it is currently under development and that the author is building it mostly for fun and for educational purposes.

## The lineage: OpenVDB, and something much simpler

Bonxai is not an original idea, and the documentation is clear about its two ancestors.

It is strongly influenced by OpenVDB, and it can be considered an implementation of the original paper with a couple of non-trivial changes, namely K. Museth's VDB: High-Resolution Sparse Volumes with Dynamic Topology from ACM Transactions on Graphics in 2013, presented at SIGGRAPH 2013. There is also overlap with a second paper, Pedrosa, Pereira and Lau's A Sparse-Dense Approach for Efficient Grid Mapping from ICARSC 2018, whose implementation is much simpler even if conceptually similar.

That comparison with Octomap and Octrees is the one most readers will care about, because Octomap is the established tool in this space. The documentation says that if you are familiar with Octomap and octrees, you know those structures are also sparse and unbounded. Bonxai, it says, is much faster and, in some cases, even more memory-efficient than an octree.

The design goal behind that is stated in the FAQ. The number one reason for reimplementing OpenVDB is to have fun and to learn something new. The second is that the author wants the library to be small and easy to integrate into larger projects, and the core data structure is less than a thousand lines of code. The third is that it is not an exact rewrite, because a few important aspects of the algorithm were modified to make it slightly faster, at least for the specific use cases the author had in mind.

So the honest characterisation is: a teaching-grade, deliberately simplified implementation of a production idea, optimised by one author for one set of workloads.

## Using it: a header, a grid and an accessor

The integration story is part of the design. The core of Bonxai is a header-only library that you can simply copy into your project and include like this:

```cpp
#include "bonxai/bonxai.hpp"
```

No package manager, no build step for the dependency, no version to keep in step. The price is that the library is yours after you copy it, with all the consequences that has for security updates and bug fixes.

Creating a grid is a constructor call with the voxel resolution:

```cpp
double voxel_resolution = 0.05;
Bonxai::VoxelGrid<int> grid( voxel_resolution );
```

The cell type is a template parameter, and the documentation shows that you are not limited to scalars, with a grid of Eigen::Vector4d and a grid of a user defined struct with an int and a double both given as examples.

Writing goes through an accessor, which the documentation says to create once and reuse as much as possible:

```cpp
// Each cell will contain a `float` and it will have size 0.05
double voxel_resolution = 0.05;
Bonxai::VoxelGrid<float> grid( voxel_resolution );

// Create this accessor once, and reuse it as much as possible.
auto accessor = grid.createAccessor();
```

Positions are discretised with posToCoord, and reading a cell gives you a pointer that is null when the cell does not exist:

```cpp
Bonxai::CoordT coord = grid.posToCoord(x, y, z);
float* value_ptr = accessor.value( coord );
```

That null is meaningful rather than an oversight. A sparse grid distinguishes an absent cell from a cell holding zero, and code that treats the pointer as always valid is the most common way to misuse this kind of structure.

## The accessor cache, and why releasing memory does not break it

The accessor is the part of the API that needs explaining, because it is a cache and caches are where sparse grid libraries usually surprise people.

An accessor caches the last nodes it visited, so a run of nearby coordinates does not walk the hierarchy from the root every time. That cache is what makes the update path fast, and it is why the documentation insists you create one accessor and reuse it.

The interesting part is the interaction with memory management. The accessor remains valid for the entire lifetime of the grid, and VoxelGrid::clear() and VoxelGrid::releaseUnusedMemory() free nodes, but the accessors detect that and refresh their cache transparently. In other words, the cached pointers are not dangling pointers that you have to think about; the accessor notices that the nodes it held are gone and re-resolves them.

That design has a cost worth understanding rather than ignoring. The accessor holds a reference to the tree nodes it has visited, so a long-lived accessor keeps some of the structure alive, and an accessor that is created and discarded per operation throws away the caching benefit. The documentation's phrasing, create this accessor once and reuse it as much as possible, is an instruction about how to get the performance the library was written for.

For a library whose selling point is that it is much faster than an octree, this is the detail that determines whether you get that speed in practice.

## The benchmark, and the memory comparison that complicates it

The documentation includes a preliminary benchmark against Octomap, and the author is careful about it: take these numbers with a grain of salt, since they are preliminary and the benchmark is strongly influenced by the way the data is stored. They gave a fair idea of what you may expect, in terms of performance.

```
Bonxai_Create              1165 us
Octomap_Create            25522 us

Bonxai_Update               851 us
Octomap_Update             3824 us

Bonxai_IterateAllCells      124 us
Octomap_IterateAllCells     698 us
```

The three operations are defined: Create refers to creating a new VoxelGrid from scratch, Update means modifying the value of an already allocated VoxelGrid, and IterateAllCells gets the value and the coordinates of all the existing cells.

The pattern is consistent across the three, with the create operation showing the widest gap, and the caveat about storage is the important part, because it tells you the numbers describe one particular way of building the grid rather than the structure in general.

Memory is more nuanced, and the FAQ says so directly: it is complicated. If you need to store very sparse point clouds, Bonxai will probably use more memory, 20 to 40 percent more. If the point cloud is relatively dense, Bonxai might use less memory than Octomap, even less than half.

That is a real trade, and it runs opposite to the speed story in the sparse case. A user whose workload is a mostly empty map of a few hundred points gets the faster update path and pays for it in memory; a user with a dense cloud gets both.

## Not thread-safe for writes, and the Octomap parity work

One constraint is stated without hedging: Bonxai::VoxelGrid is not thread-safe for write operations.

If you want to access the grid in read-only mode, you can use multi-threading, but each thread should have its own accessor. That follows directly from the accessor design, since an accessor holds a mutable cache of tree nodes, and two threads sharing one accessor would race on that cache even if they were only reading, and one thread writing while another reads would corrupt the structure itself.

So the concurrency story is: one writer, or several readers each with their own accessor. That is a narrower model than a lock-free structure, and for a mapping or simulation loop where a sensor thread writes and a planner thread reads, it means either a mutex around the write or a copy.

The release history shows the project closing in on compatibility with the established tool. v0.8.0 in September 2026 was performance improvements, v0.6.1 in July 2026 was ProbabilisticMap correctness with octomap parity, and v0.6.0 in November 2024 was better memory management.

The roadmap shows what is done and what is not. Serialization to and from file is done. The full implementation of the Octomap algorithm, ray casting plus the probability map, is done. Integration with ROS 2 is done. Still open are RViz2 visualisation messages, and integration with FCL for collision detection, which carries a question mark in the project itself.

The repository layout matches that split, with bonxai_core/ for the data structure, bonxai_map/ for the mapping layer, bonxai_ros/ for the ROS 2 integration, a package.xml for the ROS packaging, examples/ with a tutorial, a map playground and a serialisation test, and a 3rdparty/ directory for the vendored dependencies.

## Licence, maturity and where Bonxai is the wrong tool

The licence is MPL-2.0, with the LICENSE file at the root of the repository. For a library you intend to copy into a project, that is a sensible choice: file level copyleft means a modified Bonxai file has to be published, but your own project code is not affected.

The maturity picture is the more important thing to weigh. The project says it is currently under development and that the author is building it mostly for fun and for educational purposes. The version number is 0.8.0, which is a pre-one version by convention and by intent, and the last push was on 2026-09-29.

Where Bonxai is the wrong tool is clear. If your data is very sparse, the memory comparison goes against you and Octomap is the better bet. If you need a production mapping stack with a probability map, ROS visualisation messages and collision detection, the roadmap says those pieces are still open, and the ROS 2 side stops at integration. If you need a format that other tools read, the interoperability is with Octomap semantics, which the project is still bringing into parity rather than having guaranteed.

What Bonxai genuinely offers is a data structure you can read in an afternoon, in a single header, with an accessor model that keeps the fast path fast and does not break when you free memory. For a robotics or graphics developer who wants to understand sparse grids by reading one rather than by linking a large library, that is a real and specific value, and the benchmark caveat in the documentation is a sign of a project that is honest rather than a project that is finished.

## Conclusion

Adopt Bonxai if you need a voxel grid you can drop into a C++ project as a header, if you update cells far more often than you iterate them, and if you are willing to own the code rather than depend on a large library. Do not adopt it if your point clouds are very sparse, because the documentation says it will use more memory than Octomap in that case, and do not share one grid between writing threads. Before you commit, read the memory comparison in the FAQ and measure it on your own data, because the benchmark in the documentation is described by its author as preliminary and sensitive to how the data is stored.

## FAQ

### How do I use Bonxai in a C++ project?

The core is header-only, so you copy it into your project and include it with #include "bonxai/bonxai.hpp", create a Bonxai::VoxelGrid<T> with a voxel resolution, and write through an accessor created with createAccessor(), which the documentation says to create once and reuse as much as possible.

### How does Bonxai compare with Octomap?

The documentation says Bonxai is much faster and, in some cases, even more memory-efficient than an octree, and the preliminary benchmark shows Bonxai faster for creating, updating and iterating cells. On memory the answer is that it is complicated: for very sparse point clouds Bonxai will probably use 20 to 40 percent more, while for a relatively dense cloud it might use less than half of Octomap's.

### Is Bonxai thread-safe?

No, not for write operations. For read-only access you can use multi-threading, but each thread should have its own accessor, because the accessor caches the last nodes it visited.

### What happens if I clear or release memory while an accessor exists?

Nothing breaks. An accessor remains valid for the entire lifetime of the grid, and VoxelGrid::clear() and VoxelGrid::releaseUnusedMemory() free nodes while the accessors detect it and refresh their cache transparently.

### What licence is Bonxai released under, and is it finished?

MPL-2.0, with the LICENSE file at the root of the repository. The project states it is currently under development and is built mostly for fun and for educational purposes, and the latest release is v0.8.0 from 2026-09-29.

## Sources

- [facontidavide/Bonxai on GitHub](https://github.com/facontidavide/Bonxai)
- [Issues](https://github.com/facontidavide/Bonxai/issues)
- [License: MPL-2.0](https://github.com/facontidavide/Bonxai/blob/main/LICENSE)
- [README](https://github.com/facontidavide/Bonxai/blob/main/README.md)
- [Releases](https://github.com/facontidavide/Bonxai/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/facontidavide-bonxai
