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.
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.
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.
npm i @bitruvius/bvc
This 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.
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.
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.
@bitruvius/bvc— the BVC codec (decode), wrapping the prebuilt wasm decoder behind core's streamingDecodercontract.Remarks
BVC is Bitruvius' container for quantized gaussian-splat and point-cloud tiles. This package is decode-only — encoding is a separate licensed capability and is never shipped to the browser.
Reach for createBvcDecoder for a ready, capability-gated
Decoder(it auto-selects the worker-pool backend when available, else in-process), or construct BvcDecoder / BvcWorkerDecoder directly to pin a backend. For BVC-in-glTF gaussian-splat tiles (theBITRUVIUS_gaussian_splatting_bvcextension) consumed by@bitruvius/tiles3d, use BvcGltfSplatDecoder / WorkerBvcGltfSplatDecoder; for I3S point clouds produced by the I3S→BVC transcoder, use BvcI3sPointCloudDecoder / WorkerBvcI3sPointCloudDecoder.Example