npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bitruvius/gltf

v0.3.1

Published

Bitruvius SDK glTF 2.0 / GLB parser + OGC 3D-Tiles container handlers (b3dm/i3dm/cmpt/pnts): pure TS, no WebGL/DOM/codecs. Normalizes tile content to a GPU-ready struct-of-arrays mesh/point representation; geometry decompression and texture transcode are

Readme

@bitruvius/gltf

glTF 2.0 / GLB and OGC 3D Tiles container parsing in pure TypeScript, with no WebGL, no DOM and no codecs.

Internal building block. This package exists so that @bitruvius/sdk-maplibre and the Bitruvius codecs can resolve their dependencies on npm. It has no standalone product story. Unless you are deliberately building against it, install the SDK instead.

What it does

Hand it tile bytes. It sniffs the 4-byte magic, unwraps the container (glTF, b3dm, i3dm, cmpt, pnts), reads glTF accessors into tightly packed typed arrays, flattens the node graph into world-placed primitives, flattens materials into a default-filled contract, and returns one indirection-free struct-of-arrays mesh or point cloud that a GPU path can upload as it stands.

Nothing in it touches a GPU, a canvas, or a WASM binary.

Why it is its own package

Three constraints forced the split, and each one is visible in the source.

The codecs must not be a dependency. Draco, meshopt and KTX2 are megabytes of WebAssembly, and most tiles need none of them. So compression is consumed through seams: DracoGeometryDecoder, MeshoptDecoder and Ktx2Transcoder. The seam interfaces are declared in @bitruvius/geo-core, not here, so a codec wrapper depends only on core and never on the parser. @bitruvius/draco, @bitruvius/meshopt and @bitruvius/ktx2 implement them and are injected at the call site. An uncompressed tileset therefore decodes without a single WASM download, each codec ships and versions on its own, and a tile that needs a seam you did not supply throws an error naming the missing package instead of mis-decoding quietly.

It has to run in a worker. @bitruvius/tiles3d-mesh and @bitruvius/tiles3d-points pool this parser off the main thread so a streaming city does not spend the map's frame budget. That rules out WebGL types, document, and anything else the main thread owns. Input is bytes, output is typed arrays, transferable as they are.

Mesh and point content share the hard parts and must not depend on each other. The container parsers, the feature/batch table reader, the accessor reader, the magic dispatch and the octahedral-normal decode are common to textured mesh, BIM and LiDAR. Put them in the mesh package and the point package inherits a renderer it never uses, and the reverse. A shared base below both, plus @bitruvius/sdk-maplibre, is the only arrangement in which none of them depends on another.

The output contract lives in core as well (NormalizedMesh, PackedMeshTile, PackedPointTile), so the renderers consume packed buffers and never see glTF at all.

What is in it

| Area | What it covers | | --- | --- | | Containers | parseGlb, parseB3dm, parseI3dm, parsePnts, splitCmpt, sniffMagic. Zero-copy: the parts are views into your buffer. | | glTF reading | readAccessor, resolveBuffer, decodeDataUri, flattenNodes, normalizeMaterial / normalizeMaterials. | | Normalization | buildNormalizedMesh for the uncompressed path (synchronous), buildNormalizedMeshAsync for KHR_draco_mesh_compression and EXT_meshopt_compression through the geometry seams. | | Textures | decodeTextures: a KTX2 transcode seam (KHR_texture_basisu) plus an injected JPEG/PNG image decoder, so the same code runs in a browser worker and in a test. | | Tile decoders | GltfMeshDecoder, CesiumPntsDecoder, Tiles3DPointDecoder, and their functional forms, taking tile bytes to ENU-rebased packed tiles. | | Instancing | 1.0 i3dm and 1.1 EXT_mesh_gpu_instancing converge on one per-instance matrix buffer, so the renderer has a single instanced path. | | Feature metadata | 1.0 batch tables with 3DTILES_batch_table_hierarchy, 1.1 EXT_structural_metadata property tables, and per-point property attributes, all normalized into the shared FeatureProperties so picking, filtering and styling behave the same whatever the tileset version. |

Both generations of 3D Tiles are covered on both content paths: 1.0 b3dm / i3dm / pnts, and 1.1 glTF meshes and glTF POINTS. They produce the same packed output, so nothing downstream branches on tileset version.

import { parseGlb, buildNormalizedMesh } from '@bitruvius/gltf';

const mesh = buildNormalizedMesh(parseGlb(bytes));

for (const prim of mesh.primitives) {
  prim.positions; // Float32Array, 3 per vertex
  prim.indices; // Uint16Array | Uint32Array | undefined
  prim.nodeMatrix; // composed node world transform, column-major
}

Compressed content takes the async form with the seams you supply: await buildNormalizedMeshAsync(parseGlb(bytes), { draco, meshopt }).

Who should depend on it

Almost nobody, directly. To stream 3D Tiles into a map, install @bitruvius/sdk-maplibre, which composes this parser with the codecs and a worker pool for you.

Reach for it directly only when you are building your own pipeline against the Bitruvius contracts and want tile content as typed arrays: a custom renderer, an offline conversion step, a server-side inspector. It is a parser, not a loader. Fetching, tile-tree traversal, level-of-detail and placement all live above it.

Its only runtime dependency is @bitruvius/geo-core.

Trademarks

Cesium and 3D Tiles are trademarks of Cesium GS, Inc. glTF, KTX and WebGL are trademarks of The Khronos Group Inc. OGC is a trademark of the Open Geospatial Consortium. Google and Draco are trademarks of Google LLC. MapLibre is a trademark of the MapLibre organization. All other marks are the property 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. Implementing a published specification is not a claim of certification: Bitruvius has not undergone OGC compliance testing for any standard.

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.