SDK JS
    Preparing search index...

    Module @bitruvius/bvc

    @bitruvius/bvc — the BVC codec (decode), wrapping the prebuilt wasm decoder behind core's streaming Decoder contract.

    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 (the BITRUVIUS_gaussian_splatting_bvc extension) consumed by @bitruvius/tiles3d, use BvcGltfSplatDecoder / WorkerBvcGltfSplatDecoder; for I3S point clouds produced by the I3S→BVC transcoder, use BvcI3sPointCloudDecoder / WorkerBvcI3sPointCloudDecoder.

    import { createBvcDecoder } from '@bitruvius/bvc';

    const decoder = await createBvcDecoder(); // capability-gated backend
    const model = await decoder.open(bytes); // cheap header parse
    for await (const tile of decoder.decodeTiles(model, bytes)) {
    // tile = quantized SoA typed arrays; dequant happens in the shaders
    }

    Bitruvius

    @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.

    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.

    Classes

    BvcAutoDecoder
    BvcDecoder
    BvcGltfPointCloudDecoder
    BvcGltfSplatDecoder
    BvcI3sPointCloudDecoder
    BvcWorkerDecoder
    WorkerBvcGltfPointCloudDecoder
    WorkerBvcGltfSplatDecoder
    WorkerBvcI3sPointCloudDecoder

    Interfaces

    BvcDecoderOptions
    BvcGltfPointCloudDecoderOptions
    BvcGltfSplatDecoderOptions
    BvcI3sPointCloudDecoderOptions
    BvcWorkerDecoderOptions
    CreateBvcDecoderOptions
    DecodeGpuOptions
    SplatTileGpu
    ThreadsProbe
    WasmHostInit
    WorkerBvcGltfPointCloudDecoderOptions
    WorkerBvcGltfSplatDecoderOptions
    WorkerBvcI3sPointCloudDecoderOptions

    Type Aliases

    BvcAutoDecoderOptions
    ThreadsPolicy

    Variables

    bvc

    Functions

    bvcGltfPointToPrimitive
    createBvcDecoder
    threadPoolSize
    threadsSupported