SDK JS
    Preparing search index...

    Streams an OGC 3D-Tiles textured-mesh tileset (b3dm / glb, Draco geometry with KTX2/JPEG/PNG textures) and renders it georeferenced — a MapLibre CustomLayerInterface, added with map.addLayer. Only id and url are required (Tiles3DMeshLayerOptions): decode runs in a worker pool, and the dataset is seated on the basemap or 3D terrain from a ground measured off the decoded tiles. For a planet-scale tileset (Cesium OSM Buildings, Google Photorealistic) pass anchor.lng/anchor.lat for the area being viewed — its root box spans the globe, so there is no usable local frame to derive from it.

    Requires a WebGL2 context — on WebGL1 the layer goes inert and draws nothing — and renders under the mercator projection only: under a non-affine (globe) projection it hides itself. The visible tiles' data credits (Google's dynamic per-region attributions) are published into MapLibre's attribution control and reported through Tiles3DMeshLayerOptions.onAttributions.

    import { Tiles3DMeshLayer } from '@bitruvius/sdk-maplibre';

    map.addLayer(new Tiles3DMeshLayer({ id: 'city', url: 'https://…/tileset.json' }));

    Implements

    • CustomLayerInterface
    Index

    Constructors

    Properties

    id: string

    A unique layer id.

    renderingMode: "3d" = ...

    Either "2d" or "3d". Defaults to "2d".

    type: "custom" = ...

    The layer's type. Must be "custom".

    Methods

    • Revert to the default (no-sun) lighting — the clearSun half of SunLightable (used when the geo-sun system is disabled). Clearing lastSun also gates off the cast-shadow pass.

      Returns void

    • Representative ellipsoidal elevation (m) of the rendered data — for framing the camera at the data's height WITHOUT terrain (the data is placed absolutely). null when nothing is rendered yet.

      Returns number | null

    • The dataset attribution string this layer contributes, if any.

      Returns string | undefined

    • Unique data attributions of the currently-visible tiles (the required dynamic credits). Empty until tiles with asset.copyright are rendered. RAW service text — render with textContent, or escape it, if you put it in the DOM yourself.

      Returns string[]

    • The dataset's camera target [lng, lat] (degrees) — handy for driving your own flyTo.

      Returns [number, number] | null

      [lng, lat] in degrees, or null until the root center is known.

    • The dataset's geographic footprint as [west, south, east, north] in degrees.

      Returns LayerExtent | null

      [west, south, east, north] in degrees, or null until the root resolves.

      3D Tiles declares no extent the way I3S does, so this is derived from the root bounding volume: the OBB's eight corners are converted to geodetic and bounded. Corners, not centre plus radius — an OBB is oriented, so a radius would inflate a long thin tileset (a transport corridor, a coastline) into a square many times its real area, and the whole point of a footprint is deciding whether the thing is on screen.

      A planet-scale tileset (Google's, for instance) legitimately returns most of the globe here; that is the honest answer, and a caller sizing budgets should treat "always on screen" accordingly rather than reading it as an error.

    • Whether this layer is extracting hard edges. Seeds the settings panel's toggle.

      Returns boolean

    • MapLibre CustomLayerInterface hook — invoked when the layer is added with map.addLayer; initializes GL resources and begins streaming.

      Parameters

      Returns void

    • MapLibre CustomLayerInterface hook — invoked when the layer is removed with map.removeLayer; releases GL resources and stops streaming.

      Returns void

    • Pick the BIM feature under a canvas pixel. Renders the offscreen feature-id pass over the visible tiles, decodes the hit, then reads that feature's per-feature metadata (3D Tiles batch table / EXT_structural_metadata) from the resident tile — synchronous (metadata is CPU-resident).

      Parameters

      • x: number

        Canvas X in CSS pixels, top-left origin (e.g. a MapLibre click event's e.point.x).

      • y: number

        Canvas Y in CSS pixels, top-left origin (e.g. e.point.y).

      Returns
          | {
              featureOrdinal: number;
              properties: Record<string, FeatureValue>
              | null;
          }
          | null

      { featureOrdinal, properties } for the hit feature (properties is null when the tile carries no metadata), or null on a miss / before the first frame.

    • Resolve a canvas point to the 3D geographic position of the frontmost rendered mesh surface — the screen→scene primitive behind measurement and slice placement. GPU pick pass + window-depth readback, reconstructed through the inverse frame matrix (sub-decimetre at city-scale ranges).

      Parameters

      • x: number

        Canvas X in CSS pixels, top-left origin (e.g. a MapLibre click event's e.point.x).

      • y: number

        Canvas Y in CSS pixels, top-left origin.

      • snapRadiusPx: number = 0

        Snap radius in CSS pixels (default 0 = exact pixel): the nearest mesh hit within the radius wins, so a click slightly off an edge still lands on the mesh.

      Returns PickedPosition | null

      The picked position (lng/lat degrees, height metres above the rendered ground datum, plus the cross-layer-comparable depth01), or null on a miss / before the first frame.

    • Optional method called during a render frame to allow a layer to prepare resources or render into a texture.

      The layer cannot make any assumptions about the current GL state and must bind a framebuffer before rendering.

      Parameters

      Returns void

    • Nearest obstruction distance per height row through a forward corridor — ONE synthetic forward-looking orthographic pick pass over the walker's cross-section. The ObstructionProbeable contract; see it for why an overhead height probe cannot answer this. On a photogrammetry mesh this is what stops a walker at a building facade.

      Parameters

      Returns Float32Array<ArrayBufferLike> | null

      Distance in metres per row (index 0 = lowest), NaN where clear, null when this layer cannot answer.

    • Working-set load fraction (0–1): drawn tiles over drawn + still-pending.

      Returns number

    • Called during a render frame allowing the layer to draw into the GL context.

      The layer can assume blending and depth state is set to allow the layer to properly blend and clip other layers. The layer cannot make any other assumptions about the current GL state.

      If the layer needs to render to a texture, it should implement the prerender method to do this and only use the render method for drawing directly into the main framebuffer.

      The blend function is set to gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA). This expects colors to be provided in premultiplied alpha form where the r, g and b values are already multiplied by the a value. If you are unable to provide colors in premultiplied form you may want to change the blend function to gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA).

      Parameters

      Returns void

    • Sample the height of this layer's topmost rendered surface at each position — ONE synthetic top-down orthographic pick pass over the stations' bbox, then a per-station grid lookup (the "buildings" line on an elevation profile). Samples the currently-RESIDENT tiles; positions in unloaded areas return null.

      Parameters

      • points: readonly { lat: number; lng: number }[]

        lng/lat in degrees.

      • Optionalopts: SurfaceSampleOptions

        Optional: gridPx sets the overhead pass's long-axis resolution (default 1024; small values like 64 for cheap point probes), marginM the padding around the stations, and maxHeightM a CUT so the reading is the highest surface BELOW it rather than the topmost (see SurfaceSampleOptions.maxHeightM).

      Returns (number | null)[]

      Height in metres above the rendered ground datum per point, or null where this layer has no surface.

    • Toggle the DEBUG tile bounding-volume (OBB) wireframe overlay live (placement QA).

      Parameters

      • on: boolean

      Returns void

    • Resize the resident-memory budget live (the runtime equivalent of the budget ctor option).

      Parameters

      • opts: { maxBytes?: number }

        maxBytes = resident VRAM budget in bytes. Shrinking evicts far/out-of-view tiles on the next frame; growing lets the far LOD refill.

      Returns void

    • Replace this layer's clipping planes at runtime. Planes are geographic (ClippingPlanesOptions) and survive re-anchors; null (or an empty or disabled set) removes clipping and restores byte-identical rendering.

      Parameters

      Returns void

      layer.setClippingPlanes({ planes: [planeFromHeadingTilt({ lng, lat }, 90)] });
      layer.setClippingPlanes(null); // remove
    • Switch the vertical-datum placement live (rigid vertical shift; no re-stream).

      Parameters

      Returns void

    • Hard-edge overlay: the model's silhouettes and creases drawn over the surface.

      Parameters

      • edges: MeshEdgeOptions | null

        The overlay's look and extraction settings, or null to hide it.

      Returns void

      Edges are EXTRACTED per tile at decode — no 3D Tiles service ships them — so turning them on for a layer built without them re-streams the tileset. The style half (colour, opacity, width, overshoot) is uniforms and is free; only enabling, MeshEdgeOptions.creaseAngle and MeshEdgeOptions.maxEdgesPerTile force the re-stream.

      Worth it on discrete-feature datasets — Cesium OSM Buildings, individual building services — where each feature keeps its own outline (extraction welds by position AND feature id). On photogrammetry (Google, integrated meshes) there are no features to separate and every tessellation fold is a crease, so it is off by default and best left off there.

      layer.setEdges({ color: [0, 0, 0], width: 1.5, creaseAngle: 25 });
      layer.setEdges(null);
    • Set the screen-space-error target (px) live.

      Parameters

      • px: number

      Returns void

    • Fade the mesh over the basemap.

      Parameters

      • opacity: number

        Opacity in [0, 1] (clamped); 0 = transparent, 1 = opaque.

      Returns void

    • Toggle cast shadows at runtime (the setShadows half of SunLightable).

      Parameters

      Returns void

    • Adopt (or clear) the shared vector-drape atlas — satisfies the DrapeReceiver contract, so enableVectorDrape drives this layer directly. Stashed until the renderer exists.

      Parameters

      • shared: SharedDrape | null

      Returns void

    • Apply a 3D Tiles declarative style over per-feature metadata — show (an expression that's falsy → the feature is hidden) and/or color (a color()/rgb()/rgba() expression → recolor + opacity). Expressions use the 3D Tiles style language (${prop}, comparisons, ternary, …) over the tile's batch-table / structural-metadata properties. Compiled once; evaluated per feature only on change → the GPU pays one texture lookup at draw time (the same style system the I3S BSL filter uses).

      Parameters

      • style: { color?: string; show?: string } | null

        { show?, color? } 3D Tiles style-language expression strings, or null to clear the style (show everything, no recolor).

      Returns void

    • Light this layer from a SunState — satisfies @bitruvius/sdk-maplibre's SunLightable, so a GeoSunSystem / RendererSunController drives it directly. The ENU sun direction is used as-is (sub-degree difference vs the tileset anchor at city scale).

      Parameters

      Returns void

    • Show/hide without removing the layer (streaming continues).

      Parameters

      • visible: boolean

        true to show, false to hide.

      Returns void

    • Live streaming stats for a debug HUD / perf overlay.

      Returns MeshEngineStats | null

      The engine's MeshEngineStats (rendered / resident / loading / in-flight counts and bytes), or null until the engine is up.