SDK JS
    Preparing search index...

    Interface I3sMeshLayerOptions

    Configuration for I3sMeshLayer — and, unchanged, for its I3sIntegratedMeshLayer and I3s3dObjectLayer aliases. Only id and url are required; a public dataset renders with nothing else set.

    The fields that usually want a decision are datum (how the dataset is seated vertically), occludeTerrain (whether 3D terrain hides geometry behind it), and lodBias with budget (how much streaming and resident VRAM the view is allowed to cost). A secured ArcGIS service needs auth; the cross-origin CDN bundle needs workers: false.

    interface I3sMeshLayerOptions {
        attribution?: string;
        auth?: RequestAuthorizer;
        beforeId?: string;
        budget?: { maxBytes?: number };
        center?: [number, number];
        clippingPlanes?: ClippingPlanesOptions;
        datum?: VerticalDatum;
        datumRepair?: boolean;
        decoder?: I3sMeshDecoder;
        definitionExpression?: string;
        drape?: DrapeOption;
        edges?: MeshEdgeOptions;
        filterMode?: FilterMode;
        geoidN?: number;
        ground?: boolean;
        id: string;
        lodBias?: number;
        occludeTerrain?: boolean;
        onError?: (error: unknown) => void;
        onLoaded?: () => void;
        onProgress?: (fraction: number) => void;
        opacity?: number;
        poolSize?: number;
        requestInit?: RequestInit;
        selection?: SelectionStyleOptions;
        selectionField?: string;
        shadows?:
            | boolean
            | {
                bias?: number;
                cascadeCount?: number;
                mapSize?: number;
                maxDistance?: number;
                normalScale?: number;
                strength?: number;
            };
        spawn?: () => Worker;
        symbology?: I3sSymbology;
        terrainSeat?: TerrainSeat;
        underLabels?: boolean;
        url: string;
        visible?: boolean;
        workers?: boolean;
    }
    Index

    Properties

    attribution?: string

    Data attribution shown in MapLibre's attribution control (parity with the sibling layers).

    auth?: RequestAuthorizer

    Request authorizer for secured ArcGIS services (else public-first).

    beforeId?: string

    Place this layer immediately below the given style layer id on add (see underLabels). Takes precedence over underLabels.

    budget?: { maxBytes?: number }

    Resident VRAM budget (bytes). Default 2.4 GB. NOTE: the budget must accommodate the view at the chosen lodBias — a budget BELOW the view's need forces continuous eviction (thrash). For a memory-constrained target, raise lodBias (coarser, lighter) rather than just lowering this.

    center?: [number, number]

    Scene-anchor center [lng, lat]. Pin this for a PLANET-SCALE 3DObject (e.g. Esri's global buildings), whose root OBB center is degenerate (underground); otherwise such a root auto-anchors at the map's center at load. Localized datasets ignore this and anchor at their root center.

    clippingPlanes?: ClippingPlanesOptions

    Clipping planes (geographic; see ClippingPlanesOptions) applied to this layer's geometry. Fragments on the clipped side are discarded from the color, pick, and shadow-cast passes. Change at runtime via I3sMeshLayer.setClippingPlanes. Default none.

    Vertical datum for placement: 'basemap' drops the dataset on the map / 3D terrain, 'ellipsoid'/'orthometric' place it at its true absolute height. Default: inherited from the service's declared vertical CRS (vcsWkid — e.g. EGM96 5773 → 'orthometric') when a geoid is available, else 'basemap'. Switch live with I3sMeshLayer.setDatum.

    datumRepair?: boolean

    Repair a FALSE declared vertical datum on an IntegratedMesh (default true).

    Some services declare a global vertical CRS and then store heights in a LOCAL city datum — Vienna's mesh declares EGM96 (vcsWkid 5773, gravity_related_height) and stores Wiener Null, so its declared absolute placement buries the whole city 156.3 m under the terrain. No metadata distinguishes that from a service that is simply correct, so the layer MEASURES its own surface against the 3D terrain over ~225 near-field probes and, only when the disagreement is far larger than the local geoid undulation could explain, corrects it by the measured amount (one rigid shift, frozen for the layer's life, with one console warning).

    A dataset that agrees with the terrain is untouched and renders byte-identically (measured: Frankfurt +0.06 m, Clemson −0.53 m — both far under their thresholds). Inert unless the map has 3D terrain, and never runs when you pass datum or geoidN (you own the placement then) or on 3DObject / Building Scene Layer datasets. Set false to keep the declared height verbatim.

    decoder?: I3sMeshDecoder

    Custom mesh decoder (advanced) — overrides the worker / main-thread default.

    definitionExpression?: string

    Show only the features matching a SQL expression, the same shape as Esri's definitionExpression — e.g. "Type_Toit = 'plat' AND H_MAX <= 20".

    Applied as tiles stream, so nothing excluded is ever shown first. Change it later with I3sMeshLayer.setFilter.

    drape?: DrapeOption

    Drape MapLibre vector layers that sit ABOVE this layer in the style onto its geometry. Defaults to on, but only engages when the style actually has something drapeable above this layer (enabling stands up a hidden capture map). false never drapes; an options object configures it.

    Draw the model's hard edges — the silhouettes and creases of each building, the lines someone would draw sketching it.

    Opt-in, and it has to be set here. Edges are derived from the geometry as each node decodes (no service ships them), which is a full pass over every triangle. Omitting this costs exactly nothing: no extraction, no memory, no draw. I3sMeshLayer.setEdges then restyles them live — colour, width, overshoot — without re-decoding anything.

    Not the same as a wireframe: a wireframe shows every triangle, including the diagonal splitting a flat wall in two. This shows only the edges that are actually part of the model.

    filterMode?: FilterMode

    How definitionExpression hides what it excludes. Default 'hide'.

    geoidN?: number

    Optional — you should not normally need this.* The geoid undulation N (m) at the dataset, used to place absolutely-georeferenced data on mean-sea-level terrain. The SDK resolves it automatically (it fetches the EGM96 grid on demand and samples it at the dataset), so pass this only to override that — e.g. for a dataset referenced to a local vertical datum EGM96 does not model.

    An override shifts placement by the DIFFERENCE between your value and the EGM96 undulation at the dataset — so passing the conventional EGM96 value for your area is a no-op rather than a ~30 m jump.

    ground?: boolean

    Auto-ground (default true): measure the real ground from the first decoded tile and drop it onto the datum, so the dataset registers to the basemap under any tilt. Set false to skip the measure and anchor the (loose) root OBB center instead — only useful when the geometry's lowest point isn't the ground.

    id: string

    Layer id.

    lodBias?: number

    LOD quality bias (default 1, faithful to the service). >1 refines LESS — coarser + far lighter VRAM/streaming (the knob to fit a small budget on low-end GPUs); <1 sharper.

    occludeTerrain?: boolean

    Let 3D terrain OCCLUDE this layer's geometry (a hillside hides buildings behind it) instead of the geometry drawing over it.

    Defaults to true whenever the map has terrain. Without terrain there is nothing to occlude against, so it is inert. When off, the depth buffer is cleared before the layer draws, which makes its geometry composite over everything MapLibre already rendered — that is what made buildings visible straight THROUGH a hillside.

    An IntegratedMesh defaults to false instead, because that mesh IS the ground. It is coincident with the terrain rather than standing on it, so depth-testing the two against each other just lets whichever surface the DEM puts on top win in patches, and the basemap shows through the mesh. Leave it alone unless you know you want otherwise.

    Set false deliberately if you want the draw-over behaviour, e.g. a proposed-design model that must stay visible through the existing terrain.

    onError?: (error: unknown) => void

    Fired if the SceneServer fails to load.

    onLoaded?: () => void

    Fired once the working set has first fully streamed (parity with the sibling layers).

    onProgress?: (fraction: number) => void

    Fired with the working-set load fraction (0–1) as it streams.

    opacity?: number

    Initial opacity 0–1 (default 1).

    poolSize?: number

    Worker pool size (worker mode only).

    requestInit?: RequestInit

    Static auth/headers escape hatch.

    How a picked feature is drawn — a tinted fill inside, a glowing halo outside. See SelectionStyleOptions. Change it at runtime with I3sMeshLayer.setSelectionStyle.

    selectionField?: string

    Attribute whose value identifies a selected feature. Default: the service's OBJECTID field.

    Selection is keyed on an ATTRIBUTE rather than on the per-node feature ordinal, because the ordinal is meaningless outside the tile that produced it: the moment the camera moves and a different LOD streams in, the highlight would jump to an unrelated building.

    shadows?:
        | boolean
        | {
            bias?: number;
            cascadeCount?: number;
            mapSize?: number;
            maxDistance?: number;
            normalScale?: number;
            strength?: number;
        }

    Cast real sun shadows (depth-from-sun shadow map). Default false. Needs a sun via I3sMeshLayer.setSunState. Untextured 3DObject buildings also receive direct sun lighting; textured IntegratedMesh keeps its baked look but still receives shadows.

    spawn?: () => Worker

    Override worker creation (tests).

    symbology?: I3sSymbology

    Colour features by attribute from the start, equivalent to calling I3sMeshLayer.setSymbology once the layer is open.

    terrainSeat?: TerrainSeat

    For a SEA-LEVEL dataset draped on 3D terrain (datum:'basemap'), how each building seats on the slope under its footprint: 'min' (default — lowest corner, watertight, base sinks in and the terrain masks it), 'median' (centre on the ground), 'max' (highest corner), 'average' (mean). Switch live with I3sMeshLayer.setTerrainSeat. No-op for absolute datums (the geometry carries its own height).

    underLabels?: boolean

    Keep the basemap's labels (street names, POI icons) drawn ON TOP of this layer's 3D content, by placing the layer below the style's lowest symbol layer.

    Symbol layers are screen-space billboards drawn in style order, so this is purely a placement question. No-op on a style with no labels. Use beforeId instead to name an explicit layer to sit below.

    url: string

    SceneServer or layer URL (…/SceneServer or …/SceneServer/layers/{id}).

    visible?: boolean

    Initial visibility (default true).

    workers?: boolean

    Decode off the main thread in a worker pool (default true). Set false for the cross-origin CDN bundle, where the module worker can't load same-origin — the main-thread Draco decoder is used instead (its wasm still resolves via __BITRUVIUS_CONFIG__.wasmBaseUrl).