Landmarks 3D plugin
Use cases
- City-scale 3D visualization - Recognizable buildings (stadiums, cathedrals, towers) appear as detailed meshes instead of plain extrusions.
- Blend with the base map - Landmarks take the look of the base map’s 3D buildings and follow it as the map colours change, or wear a look of your own.
How it works
- A MapLibre custom layer fetches the landmark tiles covering the viewport and renders them with Three.js, lit to match the map style.
- The layer draws when the map draws and asks for a frame only when a tile arrives, so a still map stays idle. If you change a field on
landmarks.layeryourself, callmap.mapLibreMap.triggerRepaint(). - The layer sits below the POI layer, so POI labels and icons draw over the meshes and roads stay below.
- The plugin leaves the base map’s 3D buildings shown or hidden as they are. Basemap buildings that overlap a landmark carry
has_landmark, and the plugin filters them out so they don’t clip through the meshes. - After
setStyle, the plugin restores the layer, the filter and the look. - The plugin builds the tile URL from the global
TomTomConfig(apiKey,commonBaseURL). Behind a credentialed proxy, tile requests send cookies like every other SDK request.withCredentialsoverrides that. - Three.js decodes KTX2 textures with the Basis Universal transcoder. It ships with the plugin in a chunk loaded with the first landmark tile, so no request goes to a CDN.
- A strict Content Security Policy needs
data:inconnect-srcandblob:inworker-src. Landmarks3Dalways uses the bundled copy. To serve your own, build the layer yourself withnew ModelsLayer(layerSpecification, sourceSpecification)and settranscoderPathon theModelsSourceSpecification.
- A strict Content Security Policy needs
Installation
npm install @tomtom-org/maps-sdk maplibre-gl three @tomtom-org/maps-sdk-plugin-landmarks-3d- Follow the SDK Project Setup to create a
TomTomMap. Pitch the camera. From above, the meshes look flat. - Show the base map’s 3D buildings, so the landmarks stand in a 3D city. Most standard styles ship the
buildings3Dgroup hidden. Leave this step out for landmarks alone. - Create the plugin. Rendering starts once the map is ready, so there is nothing to await.
import { BaseMapModule } from '@tomtom-org/maps-sdk/map';import { Landmarks3D } from '@tomtom-org/maps-sdk-plugin-landmarks-3d';
await BaseMapModule.get(map, { groups: { buildings3D: { visible: true } } });const landmarks = new Landmarks3D(map);Usage examples
Set the look
The look of the landmarks is a set of knobs. Set the ones you want, and leave the others to the base map:
import { resetKnob, setKnob } from '@tomtom-org/maps-sdk/map';import { landmarks3DKnobCatalogue } from '@tomtom-org/maps-sdk-plugin-landmarks-3d';
landmarks.updateConfig({ color: '#c8b28a', opacity: 0.9 }); // the rest still follows the base mapsetKnob(landmarks, landmarks3DKnobCatalogue, 'verticalGradient', false); // a value held as dataresetKnob(landmarks, landmarks3DKnobCatalogue, 'color'); // back to the base map's colourlandmarks.resetConfig(); // every knob back to the base map- Each knob you leave unset follows the style’s 3D buildings, so landmarks blend in. They keep following them through
setStyleand whatever restyles them: the map colourscolors.artificialandcolors.land, as a borrowed look does, or a paint property you set on3D - Buildingyourself. - Every standard style but
streetSatellitehas 3D buildings to follow. OnstreetSatellite, and on a style of your own without them or with a value that isn’t a single one, the knob takes the 3D building look ofstreetLight. Setcolorwhere that doesn’t suit a dark style. Landmarks3Dfollows the same rules as a map module.applyConfig(config)replaces every knob andupdateConfig(config)the ones you name. For values held as data,setKnobandsetKnobscheck each one againstlandmarks3DKnobCataloguefirst.getKnobreturns the value in force: the one you set, otherwise the base map’s.getConfig()returns only the knobs you set.
Knobs
| Knob | Values | Unset |
|---|---|---|
visible | true or false | true |
color | a CSS colour | the colour of the base map’s 3D buildings |
opacity | 0 to 1 | the opacity of the base map’s 3D buildings |
verticalGradient | true or false: whether the walls darken towards the ground | as the base map’s 3D buildings |
minZoom, maxZoom | 0 to 22: the lowest and highest whole zoom levels the landmarks are drawn at | the zoom range of the base map’s 3D buildings |
Terrain
Landmarks stand on 3D terrain without any configuration. The plugin lowers each one onto the lowest ground under its footprint, so no wall floats above a slope. Landmarks follow the terrain as it loads or its exaggeration changes.
import { TerrainModule } from '@tomtom-org/maps-sdk/map';import { Landmarks3D } from '@tomtom-org/maps-sdk-plugin-landmarks-3d';
await TerrainModule.get(map, { elevation: { visible: true }, hillshade: { visible: true } });const landmarks = new Landmarks3D(map);Toggle visibility
landmarks.setVisible(false); // the same as landmarks.updateConfig({ visible: false })landmarks.isVisible(); // falseSeveral maps
Create one Landmarks3D per map. Each one loads the tiles of its own map’s view:
const landmarks = maps.map((map) => new Landmarks3D(map));- Each map takes a WebGL context, and a browser allows only so many per page (16 in Chrome). To show more landmarks than maps, move the maps you have instead of creating new ones.
- With more than one map, Three.js warns about
Multiple active KTX2 loaders. The landmarks still render.
To frame a tall landmark, aim the camera at its mid-height instead of its foot. Set centerClampedToGround: false on the map and give the camera an elevation in metres. MapLibre’s flyTo and easeTo leave the elevation where it was, so move with jumpTo:
const map = new TomTomMap({ mapLibre: { container: 'map', centerClampedToGround: false, center: [2.2945, 48.8584], elevation: 165, // halfway up the Eiffel Tower zoom: 15.4, pitch: 60, },});new Landmarks3D(map);
map.mapLibreMap.jumpTo({ center: [-122.3493, 47.6205], elevation: 92 }); // on to the Space NeedleThe demo below shows four landmarks of one kind, one per map:
Configuration
Pass the knobs to start with in the constructor, alongside withCredentials. That option sends cookies with each tile request, and follows the SDK’s proxy configuration unless you set it.
const landmarks = new Landmarks3D(map, { minZoom: 14, opacity: 1 });Landmark tiles exist at zoom 15 only. Below it, each view needs more of them: at zoom 13, 16 times as many, and more again on a pitched map. Keep minZoom close to 15, above all with several maps on a page.
API reference
For complete documentation see the Landmarks3D API Reference.
Related guides and examples
- Landmarks 3D plugin - Landmarks over a pitched city, with their look’s knobs and a built-up colour they follow
- 3D terrain map - Landmarks standing on the relief
- 3D landmarks of one kind - Four towers, cathedrals, stadiums or monuments, each on its own map
- Terrain - Hillshade and 3D elevation