feat(core): Add getZoomFromElevation and getElevationFromZoom utility functions#10015
feat(core): Add getZoomFromElevation and getElevationFromZoom utility functions#10015Copilot wants to merge 3 commits into
Conversation
|
Closes #9743 |
|
I think this code would be better placed in the |
|
I implemented the suggested new getZoomFromElevation function and was able to test it a bit with a simple 3D tiles scene. The function invoked with the default altitude(ratio) of 1.5 generates usable zoom levels for WebMercatorViewport which lead to more or less expected tile selections when navigating the scene. I noticed, however, that supplying the actual fovy (vertical field of view angle) which in my framework by default is only 45 degrees, has an adverse impact. In this case altitudeRatio is calculated from the fovy by the fovyToAltitude function: 0.5 / Math.tan(0.5 * fovy * DEGREES_TO_RADIANS);This comes out for 45 deg. fovy as about
I also calculate Another, perhaps unrelated, observation is that there can be |
|
Further testing revealed that using the actual pitch was important and helped with using the actual fovy. So this seems resolved. The NaN errors were due to pitches > 90,, eg. looking upwards. Looking upwards may not be common in deck.gl but will be in any first person view navigation. In the formula pitches > 90 lead to cos(pitch) < 0 which is not allowed for logarithms. Not sure what the proper solution would be but just taking the absolute value of the log argument seems to work well. This also takes care of the elevation < 0 case, eg. when dipping beneath the surface. There should be a proper solution as well. Elevation = 0 leads to infinity and elevation close to 0 leads to large numbers which may not be intended. Just clipping at 1 solves this and behaves well but is probably incorrect. |
|
Let me note that I ended up using 2 * actual fovy to address too aggressive culling for tile selection for WebMercatorviewport, and then also 2 * actual fovy to calculate zoom from elevation. I think it affects LOD switching a bit as well which seems a reasonable tradeoff. Going further, with the global Google Photorealistic 3D Tileset, I found that using the WebMercatorViewport as the only documented option was not appropriate. I am rendering it in a perspective projection, from geocentric space, not as a map. So in hindsight, it makes a lot of sense there were selection issues due to this conflict. #10066 and #10252 use FirstPersonViewport and GlobeViewport for 3d tiles layer, so it seems this is supposed to also work, somewhat ? I tried automatic switching between WebMercator and GlobeViewports at a certain zoom threshold (6 or so) and it more or less works for the global views but tile selection seem to get perhaps confused. It holds on to way too many tiles (hundreds) navigating and zooming around. Perhaps tile selection during subsequent traversals is additive/subtractive and needs to be reset when switching viewports like this ? |
This could get some love: https://visgl.github.io/math.gl/docs#history @ me in any active change / feature proposals |
|
Here is screen recording trying to show the increase in selected tiles. The #TILES number shown is just .selectedTiles.length. Apologies for the flashing: layersgl2-2026-05-13_16.12.05.mp4Hm, I also noticing that the calculated zoom changes quite a bit, so probably something else is going on. |
|
I love the direction youre taking the controller movement - would be blessed to work it into a deck.gl release as a follow up to landing #10298 https://maplibre.org/roadmap/maplibre-native/lod/ & maplibre/maplibre-native#2958 might help dig into a working system that clearly spent time mastering tile selection math. |
|
The renderer is x3dom (https://github.com/x3dom/x3dom) and the controller switches to 'fly mode' (a standard navigation mode in X3D, see https://www.web3d.org/documents/specifications/19775-1/V4.0/Part01/components/navigation.html#NavigationInfo). It will be difficult to transplant to deck.gl since the concepts are very different but the main implementation is here: https://github.com/x3dom/x3dom/blob/master/src/nodes/Navigation/modes/DefaultNavigation.js |
Users working with 3D tilesets outside of deck.gl need to construct a
WebMercatorViewportfrom a physical camera position (lat/lng/elevation in meters), but the API only acceptszoom— requiring manual derivation of the conversion formula.Change List
getZoomFromElevation(options)— converts a physical camera elevation (meters) to thezoomlevel forWebMercatorViewport. Supportsaltitude,fovy,pitch, andheightto match the viewport configuration.getElevationFromZoom(options)— inverse of the above; returns the camera elevation in meters for a given zoom level.@deck.gl/coreanddeck.gl.Formula:
zoom = getMeterZoom({latitude}) + log2(altitudeRatio × cos(pitch) × height / elevation)Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
https://api.github.com/repos/visgl/deck.gl/discussions/9743/home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js(http block)If you need me to access, download, or install something from one of these locations, you can either:
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.