wipfli / 3d-landmarks

Display 3D Landmarks in MapLibre GL JS
Apache License 2.0
1 stars 0 forks source link

Strategy to display 3d landmarks #1

Open wipfli opened 1 year ago

wipfli commented 1 year ago

Assume we have a set of 3D landmarks for a city. The landmarks are stored as glTF files and can be requested at HTTP endpoints of the form https://{base_url}/{landmark_name}.gltf. The basemap for the city has building footprints and building heights.

Below z15, only the building footprints are shown and the map pitch is 0.

At z15 and higher, the map pitches to 45 degrees and the buildings are shown as 2.5D extrusions.

If we have a 3D landmark model for a building, then we show it a z15 and higher and turn the 2.5D extrusion of the building footprint off. So building footprints need to know if they have a 3D model or not. This can be stored in a property called has-3d-landmark: yes/no.

wipfli commented 1 year ago

The 3D landmarks should be loaded only for things which are displayed. For this, we create a point layer in an MVT at z15. This source layer is called 3d-landmarks and the only property of a point is name.

In a MapLibre style layer, we use the 3d-landmarks data to create styleimagemissing events. These are events which are issued if a map style does not have access to an image. This is called run-time styling.

The MapLibre style layer could look like this:

{
  "id": "3d-landmarks",
  "type": "symbol",
  "source": "my-source",
  "source-layer": "3d-landmarks",
  "layout": {
    "icon-image": "please-load-3d-landmark-{name}"
  }
}

Say we look at the eifel tower with name eifel-tower, then since the icon image please-load-3d-landmark-eifel-tower is not available, this will create a styleimagemissingevent. We can catch that event, request https://{base_url}/eifel-tower.gltf and add it to the map with something like this:

https://maplibre.org/maplibre-gl-js-docs/example/3d-buildings/

wipfli commented 1 year ago

The only downside with this is that the rendering of the 3d landmark happens in a separate webgl layer or however it is called. As a consequence, the landmark is either always above or always below the 2.5D building extrusions.

What we need is a way to get obtrusion right between the 2.5D and 3D content.

wipfli commented 1 year ago

Maybe babylon could render the 2.5D buildings and the 3D buildings. Maybe MapLibre could render both.

wipfli commented 1 year ago

The simplest way to achieve a good looking result of the currently available technology is to render the 3D building with Babylon or three JS and also render some 2.5D buildings around the 3D building with Babylon.

If we assume a certain maximum pitch then we know at tile generation time how many buildings around the 3D building have to be removed and rendered with Babylon.

wipfli commented 1 year ago

This feels a bit like cheating, but I think it can work very well...

wipfli commented 1 year ago

Ah but actually then the problem just happens at another place where we want to have obstruction of 2.5 d and Babylon but it doesn't work.

wipfli commented 1 year ago

Maybe we can use deckgl:

image

https://deck.gl/docs/get-started/using-with-map

wipfli commented 1 year ago

deckgl seems to work nicely for this purpose.