@bitruvius/bvc
v0.3.1
Published
BVC decoder: the Bitruvius container for lidar point clouds and Gaussian splats, decoded in the browser via wasm
Readme
@bitruvius/bvc
Lidar and Gaussian splats in one container: 16% smaller than LEPCC, 38% smaller than SPZ, and the only bit-exact mode in the field.
BVC compresses the two formats 3D actually ships in, lidar point clouds and Gaussian splats, into one container. This package is the browser decoder: SIMD-accelerated WebAssembly, both profiles, streaming quantized tiles straight into typed arrays your shaders can read.
Powered by Bitruvius BVC, a Bitruvius flagship codec.
Smaller on the wire, exact when it matters
Published results from bitruvius.com/bvc: identical input, identical tiling, each format measured against its strongest available implementation. Lower is better. These are our own measurements on the corpora named below, and results vary by dataset and settings.
Point clouds, bytes per point, 1.06M-pt Autzen tile:
| Format | Mode | Bytes/pt |
|---|---|---:|
| BVC, crown | lossy: single-pass 256-color palette | 5.78 |
| BVC, lossless | lossless: full color, exact data | 6.80 |
| LEPCC | lossy: quantized color, no gps_time field | 6.87 |
| Draco | lossless, same 1 cm grid | 7.02 |
| meshopt | lossless, same grid | 7.18 |
| LAZ | lossless archive standard | 8.87 |
Gaussian splats, bytes per splat, 786K-splat capture at full color detail:
| Format | Mode | Bytes/splat | |---|---|---:| | BVC, compact | lossy: SH compressed | 14.32 | | SOG (post-hoc) | lossy: k-means SH compression | 14.57 | | L-GSC | lossy: own quant grid plus zlib (compLevel 2) | 18.27 | | BVC, exact | lossless: every attribute bit-exact | 22.49 | | SPZ | lossy: quantizes on ingest | 23.09 |
Three things fall out of those tables.
Like for like, BVC is the smallest here. Comparing compressed against compressed, it is 5.78 against 6.87 bytes per point next to LEPCC, 16% less on the wire, and 14.32 against 23.09 bytes per splat next to SPZ, 38% less, or 1.6x. Both comparisons are lossy against lossy on the same input.
BVC is the only splat codec here with a bit-exact mode. Every other entry quantizes. If you need the capture back exactly as authored, that is the column that matters, and BVC's exact profile still lands under SPZ's quantized one on this capture.
Loss is a dial you declare, never a surprise. BVC offers true lossless for both point clouds and splats, and where loss is chosen it carries a declared worst-case error you can write into a workflow.
The bytes are the same everywhere. Intel, AMD, Apple Silicon, WebAssembly and two GPU stacks all produce and verify byte-identical files, enforced by cryptographic hash gates in continuous testing.
Use it
Open the header, then stream tiles.
import { createBvcDecoder } from '@bitruvius/bvc';
const decoder = await createBvcDecoder(); // backend picked by runtime capability
const model = await decoder.open(bytes); // cheap header parse
for await (const tile of decoder.decodeTiles(model, bytes)) {
// tile.x / tile.y / tile.z: Int32Array, the quantized position grid
if (model.meta.kind === 'pointcloud') {
const { scale, offset } = model.meta;
// world x of point i = tile.x[i] * scale[0] + offset[0]
}
}That is the whole surface. model.meta is discriminated by meta.kind, not by
model.profile, so switch on meta.kind: point clouds carry scale/offset,
splats carry fractionalBits/shDegree (meters = q / 2 ** fractionalBits).
Tiles carry the same discriminant on tile.kind.
Tiles arrive quantized on purpose, because that is the form the GPU wants. Dequantize in your shader and you never pay for a float expansion on the CPU.
createBvcDecoder() is async and returns a Decoder. Where Workers are
available it hands back the auto backend, which keeps small single-tile files
in-process and sends larger containers to BvcWorkerDecoder, a Worker pool that
transfers tile arrays instead of copying them, so heavy scenes decode off the
main thread. Transferred arrays are not reusable: do not hold a tile past the
next iteration. new BvcDecoder() pins the in-process wasm backend when you
need it, such as a sandboxed page that cannot spawn a Worker.
What ships
npm i @bitruvius/bvcThis package is the decoder. BVC is free to read: anyone who needs to open
BVC-encoded data can pull the decoder. Production encoding is a separate
commercial license and no encoder is shipped here or to the browser. If you
came looking for a way to write .bvc files, this is not it. Talk to Bitruvius.
The prebuilt wasm is committed to the package (wasm/) and needs a runtime with
WASM SIMD, which covers every current browser. Decode is golden-fixture tested
against files produced by the BVC encoder.
Also exported, for callers who already have a tiling engine: BvcGltfSplatDecoder
for BITRUVIUS_gaussian_splatting_bvc splat tiles in glTF, and
BvcI3sPointCloudDecoder for I3S point clouds run through the I3S to BVC
transcoder. Each has a worker-backed variant.
If you want BVC on a map rather than a decoder API, use
@bitruvius/sdk-maplibre,
which renders both profiles as MapLibre layers.
A GPU decoder for BVC exists on Vulkan and Metal, and in the browser on WebGPU. It is a separate deliverable and is not part of this npm package. Benchmarks for it are on the BVC page.
Learn more
- Live examples: point clouds and splats decoding in the browser, with source
- Documentation: guides and the full API reference
- Support: questions and issues
- BVC on bitruvius.com: benchmarks, format details and encoder licensing
Trademarks
Esri, I3S and LEPCC are trademarks of Environmental Systems Research Institute, Inc. Google and Draco are trademarks of Google LLC. Khronos, glTF, meshopt and Vulkan are trademarks of The Khronos Group Inc. Niantic and SPZ are trademarks of Niantic, Inc. Qualcomm is a trademark of Qualcomm Incorporated. LAZ and LASzip are trademarks of rapidlasso GmbH. Apple, Apple Silicon and Metal are trademarks of Apple Inc. Intel is a trademark of Intel Corporation. AMD is a trademark of Advanced Micro Devices, Inc. MapLibre is a trademark of the MapLibre organization. Other product and format names are trademarks of their respective owners.
These names are used solely to describe the data formats this software interoperates with. Bitruvius is not affiliated with, sponsored by, or endorsed by any of them, and no such relationship is implied.
License
Proprietary. The full terms ship as LICENSE inside this package, and are readable
before installing at cdn.bitruvius.com/legal/sdk-license-v1.txt.
© Bitruvius, Inc.
