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/tiles3d-mesh

v0.3.1

Published

Composed off-main-thread decoder for OGC 3D-Tiles textured meshes: wires @bitruvius/gltf + draco + meshopt + ktx2 into a worker-pooled MeshTileDecoder

Downloads

378

Readme

@bitruvius/tiles3d-mesh

Textured 3D Tiles meshes, decoded off the main thread and handed back GPU-ready.

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

Give it tile bytes (b3dm, i3dm, cmpt or glb) and a georeference context. It unwraps the container, decodes Draco and meshopt geometry, transcodes KTX2 textures, decodes JPEG and PNG textures, and returns one PackedMeshTile rebased into the shared-scene ENU frame in metres.

All of that runs in a Web Worker pool by default, so a streaming city model does not spend the render thread's frame budget. Tile bytes transfer into the worker and every buffer of the packed tile transfers back out, both zero-copy.

Why it is its own package

The composition needs an owner, and neither of its neighbours can be it.

The parser must stay codec-free. @bitruvius/gltf consumes compression through seams whose interfaces live in @bitruvius/geo-core, so an uncompressed tileset decodes without downloading a single WebAssembly binary. Something still has to wire DracoDecoder, MeshoptGltfDecoder, Ktx2BasisTranscoder and an image decoder into a working decoder. Do it in the parser and every consumer inherits megabytes of wasm it may never use.

The renderer must not be it either. Put the wiring in the MapLibre layer and the only way to decode a 3D Tiles mesh is to adopt MapLibre. The composition lives here instead, so a custom renderer gets the same decoder the SDK uses.

Mesh and point content must not drag each other's codecs. The sibling package @bitruvius/tiles3d-points depends only on core, the parser and Draco. A LiDAR application therefore never pulls the KTX2 transcoder or the meshopt wasm, and a mesh application never pays for a point path it does not render. That is only true while the two compositions are separate packages.

The worker chunk has to be built by whoever owns the wiring. src/mesh-decode-worker.ts is published as its own chunk, and a worker cannot reliably resolve its sibling packages' wasm against its own base URL. So the Draco and KTX2 binaries are resolved on the main thread, forwarded with the first request to each worker, and cached there. That handshake touches the codecs, the parser and the pool at once, which is exactly the set of dependencies this package has and no other package should take on.

Two failure modes are handled here for the same reason. A pool that cannot spawn at all (a CSP without worker-src blob:, a missing chunk) is reported once, through onDegraded and one console warning, and every later decode runs on the calling thread: slower, but the layer renders instead of staying empty. And a cross-origin CDN page cannot call new Worker(cdnUrl), so the CDN build fetches the published worker chunk over CORS and spawns it from a same-origin Blob URL.

What is in it

| Export | What it does | | --- | --- | | createMeshDecoder(opts) | The factory. Worker pool on by default, sized hardwareConcurrency - 1 clamped to 1..8; workers: false selects the main-thread path, as does any environment with no Worker; poolSize, spawn and onDegraded tune the rest. Returns a MeshTileDecoder. | | WorkerGltfMeshDecoder | The pool itself, for when you need to supply explicit Draco or KTX2 wasm bytes or URLs rather than let them auto-resolve. | | browserImageDecoder | The JPEG/PNG decodeImage seam. createImageBitmap with no premultiply and no colour conversion, returning the ImageBitmap for a direct texImage2D upload instead of an OffscreenCanvas RGBA readback per tile. | | MeshDecodeRequest | The worker wire-protocol type. Useful when you host the worker yourself. |

import { createMeshDecoder } from '@bitruvius/tiles3d-mesh';

// Off-main-thread worker pool (default).
const decoder = createMeshDecoder();

// Cross-origin CDN: no module workers, so decode on the main thread.
const cdnDecoder = createMeshDecoder({ workers: false });

Pass the result to Tiles3DMeshEngine from @bitruvius/tiles3d, or as the decoder option of Tiles3DMeshLayer from @bitruvius/sdk-maplibre. Size the engine's decode concurrency to the decoder's concurrency, and call dispose() to tear the pool down. MeshTileDecoder and PackedMeshTile are contracts from @bitruvius/geo-core, not types this package invents, which is what lets a decoder built here drop into a renderer that never heard of it.

Who should depend on it

Almost nobody, directly. To stream 3D Tiles meshes into a map, install @bitruvius/sdk-maplibre, whose mesh layer constructs this decoder for you.

Take it directly when you are building your own renderer or pipeline on the Bitruvius contracts, when you want to tune worker concurrency against your own tile budget, or when you need to serve the codec wasm from a location you control.

Its runtime dependencies are @bitruvius/geo-core, @bitruvius/gltf, @bitruvius/draco, @bitruvius/meshopt and @bitruvius/ktx2.

Trademarks

Cesium and 3D Tiles are trademarks of Cesium GS, Inc. glTF and KTX 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.