Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix level of detail at high pitch #4779

Draft
wants to merge 170 commits into
base: main
Choose a base branch
from

Conversation

NathanMOlson
Copy link
Contributor

@NathanMOlson NathanMOlson commented Sep 30, 2024

Reopening accidentally closed PR: #4750

This fixes #3983, fixes #4940 and improves #4703 by calculating the desired zoom level for each tile independently. Each tile zoom is calculated by scaling the center point zoom by the ratio of (3D) distance-to-tile to distance-to-center. For Mercator transform, the old behavior is preserved when there is no terrain and pitch < 60 degrees. For Globe transform, the new behavior applies in all cases.

Before:

before_terrain before

After:

after2_terrain after2

Here's my understanding of the previous implementation:
image
image

And here's a drawing of how it works now (in crude 3d):

image

Here's a description of how it works.

The center point is rendered at the requested zoom level.
the 3D distance from the camera to each candidate tile is calculated and the desired zoom for that tile is the requested zoom scaled by ratio of camera-to-center distance to camera-to-tile distance. If the candidate tile is lower resolution than desired, the tile is split.
Note that rather than use the true 3D distance to each tile (accounting for terrain), it is assumed that all tiles are at the same elevation as the center point. This prevents "resolution explosion" when the camera is very close to a hill, and keeps the resolution variation from map center smooth.

kubapelc and others added 30 commits March 15, 2024 13:32
…ibre#3783)

* Port changes from main globe branch - basics

Fix minor issues so that it compiles.

* Fix PI redefinitions

* Fix stencil shader

* Port adaptation of raster layer for globe from main globe branch

* Add globe.html example from pheonor's repo

Minor changes (remove terrain, set initial zoom 0, change title and description)

* Better map projection parameter doc comment, warn when using unknown projection

* Mercator projectionData handles negative zoom correctly

* Comment clarification

* Fix spelling of "granularity"

* Add missing docs

* Convert ProjectionBase to an interface

* Do not leak GL object in globe projection error measurement, add a destroy method to projection

* Fix chrome performance warning, refactor error measurement

Warning fixed by changing ring buffer size to 1, making ring buffer pointless, so I removed it.

* Fix granularity capitalization

* Fix capitalization

* Fix typo

* Fix stencil mask triangle index order (this was causing failing render tests)

* Cleanup vertex shader projection interface

* Move projection creation function into its own file

* Remove getProjectionName

* Added comment for deduplicateWrapped

* Remove unused vertex-buffer-related code from image source

* Add globe raster layer render test

* More render tests - test transition to mercator

* Remove pointless test, add test descriptions

* Render test for rendering poles on globe

* SubdivisionGranularitySetting constructor takes an object

* Remove "defines" parameter from useProgram

* Refactor useProgram and Program constructor

* Properly format translatePosMatrix comment

* Refactor globe-specific code outside projection classes, remove stencil-specific granularity settings

* Refactor granularity settings to be more readable

* Minor refactor of ProjectionErrorMeasurement

* Refactor draw_raster.ts

* Move globe utility functions to utils.ts, use easeCubicInOut instead of smoothStep

* Simplify imports in globe.ts

* globe.ts refactor

* Move ProjectionErrorMeasurement to a separate file

* Refactor ProjectionErrorMeasurement

Change parseRGBA8float to a private static function, use isWebGL2 function instead of instanceof

* Refactor draw_raster.ts

* Refactor globe projection error measurement to not use Painter

* Painter.clearStencil creates custom ProjectionData instead of calling getProjectionData(null, null)

* Remove "deduplicateWrapped" functionality from source_cache.ts

* Globe projection no longer requires a map instance

* Painter doesn't pass `this` to `updateGPUdependent`

* isRenderingDirty is now a function

* Rename ProjectionBase to Projection

* Replace globeView property with setGlobeViewAllowed

* Add mercator and globe projection unit tests

* Remove tests that test for exact clipping planes

* Update build test with new bundle size

* isRenderingDirty is now a function
* Port changes from main globe branch - basics

Fix minor issues so that it compiles.

* Fix PI redefinitions

* Fix stencil shader

* Port adaptation of raster layer for globe from main globe branch

* Add globe.html example from pheonor's repo

Minor changes (remove terrain, set initial zoom 0, change title and description)

* Better map projection parameter doc comment, warn when using unknown projection

* Mercator projectionData handles negative zoom correctly

* Comment clarification

* Fix spelling of "granularity"

* Add missing docs

* Convert ProjectionBase to an interface

* Do not leak GL object in globe projection error measurement, add a destroy method to projection

* Fix chrome performance warning, refactor error measurement

Warning fixed by changing ring buffer size to 1, making ring buffer pointless, so I removed it.

* Fix granularity capitalization

* Fix capitalization

* Fix typo

* Fix stencil mask triangle index order (this was causing failing render tests)

* Cleanup vertex shader projection interface

* Move projection creation function into its own file

* Remove getProjectionName

* Added comment for deduplicateWrapped

* Remove unused vertex-buffer-related code from image source

* Add globe raster layer render test

* More render tests - test transition to mercator

* Remove pointless test, add test descriptions

* Render test for rendering poles on globe

* SubdivisionGranularitySetting constructor takes an object

* Remove "defines" parameter from useProgram

* Refactor useProgram and Program constructor

* Properly format translatePosMatrix comment

* Refactor globe-specific code outside projection classes, remove stencil-specific granularity settings

* Refactor granularity settings to be more readable

* Minor refactor of ProjectionErrorMeasurement

* Refactor draw_raster.ts

* Move globe utility functions to utils.ts, use easeCubicInOut instead of smoothStep

* Simplify imports in globe.ts

* globe.ts refactor

* Move ProjectionErrorMeasurement to a separate file

* Refactor ProjectionErrorMeasurement

Change parseRGBA8float to a private static function, use isWebGL2 function instead of instanceof

* Refactor draw_raster.ts

* Refactor globe projection error measurement to not use Painter

* Painter.clearStencil creates custom ProjectionData instead of calling getProjectionData(null, null)

* Remove "deduplicateWrapped" functionality from source_cache.ts

* Globe projection no longer requires a map instance

* Painter doesn't pass `this` to `updateGPUdependent`

* isRenderingDirty is now a function

* Rename ProjectionBase to Projection

* Replace globeView property with setGlobeViewAllowed

* Add mercator and globe projection unit tests

* Remove tests that test for exact clipping planes

* Update build test with new bundle size

* isRenderingDirty is now a function

* Fill, fill-extrusion, line layers, subdivision: Import changes from kubapelc/globe-vector branch

* Fix unit tests

* Subdivision: ensure consistent triangle winding order, fix unit tests

* Fix terrain

* Fix fill extrusion not working with terrain

* Fix typos

* Fix line gradient bug

* Subdivision: fix line ring handling

* Subdivision: fix unit test expecting an invalid line segment

* Fix fill-extrusion ring handling

* Fill-extrusion refactor and fix failing test

* Update terrain fill extrusion test expected image

* Render tests for fill, line and fill-extrusion for globe

* Move fillArrays function into a separate file

* Add vector globe example

* Remove changes for line and fill-extrusion layers to make the PR smaller

* Add unit tests for fillArrays()

* fillArrays unit test has better segment size limits

* Update build test build size

* Fix html example description

* Fix missing docs for granularity settings

* Rename globe fill render test tile source layer to "vector_tiles"

* Fix classifyRings comment format

* Move subdivisionGranularitySettingsNoSubdivision constant to a static readonly field, shorten the name

* Use `import type` for SubdivisionGranularitySetting where possible

* Fix typo

* Revert fill_attributes back to default exports

* Improve comment for scanline subdivision

* Subdivision: break up scanline subdivision function into more functions

* Move SubdivisionGranularitySetting into its own file

* Unit tests: use mock of MercatorProjection instead of the full class

* Add SegmentVector unit tests

* Subdivision: unit tests for poles, ring triangulation, fix bug in ring triangulation

* Subdivision: more pole unit tests

* Subdivision: fix wireframe generation, add unit test for wireframe

* Rename subdivisionGranularitySettings.ts to subdivision_granularity_settings.ts

* Move granularity settings registration to subdivision

* Update build size

* Rename `fillArrays` to `fillLargeMeshArrays`

* Move virtual buffers to a test util file

* Better warning for segments.ts vertex overflow

* Better comment for projection subdivision granularity

* Clarify mesh comparison in fill_large_mesh_arrays.test.ts

* Move mesh creating functions into a separate file, add tests for mesh comparison and grid creation

* Refactor and add better doc comment for `fillLargeMeshArrays`

* Refactor fill_large_mesh_arrays by removing duplicated code

* Move debug functions to mesh_utils.ts

* Unit tests: use StructArrays instead of VirtualVertexBuffer, etc.

* Subdivision: refactor

* Subdivision: rename subdivideFill to subdividePolygon, remove wireframe function

* Subdivision: throw when a vertex is outside int16 range

* Subdivision: refactor generatePoleQuad into a proper function

* Subdivision: add subdivision benchmark

* Subdivision: split scanline subdivision into smaller functions

* Remove wireframe generation function

* Subdivision: better doc comments for scanline subdivision

* Fix 'as any' in segment.ts

* Reuse condition in fill_large_arrays

* Deduplicate code in fill_large_arrays

* Subdivision: remove redundant function in tests

* Subdivision: improve scanline subdivision comments

* Subdivision: benchmark is not async

* Rename SegmentVector's invalidateLast to forceNewSegmentOnTextPrepare

* More tests for segment.ts

* Fix typo in forceNewSegmentOnNextPrepare

* Subdivision: more tests for fillLargeMeshArrays

* Subdivision: better comment in fillLargeMeshArrays
* Fix merge

* Import line layer changes from kubapelc/globe-vector

* Lines: shorten line_bucket.test.ts subdivision settings

* Lines: minor refactor

* Lines: update build size

* Lines: minor refactor
* Import changes for fill-extrusion from main vector globe branch

* Fill extrusion: refactor

* Fill extrusion: indent shader ifdefs

* Fill extrusion: add example

* Fill extrusion: update build size

* Move globe specific projection methods to projection interface

* Fix failing unit test

* Use vec3.clone() instead of manually copying vector components
* Import background layer changes from main vector globe branch

* Import hillshade layer changes from main vector globe branch

* Subdivision: explicit types

* Fix single-pixel seams in the oceans

* Add render test for background pattern on globe

* Refactor drawBackground

* Refactor drawHillshade

* Update build size

* Update globe background-pattern render test with results from CI

* Hillshade: refactor prepareHillshade

* Add a render test for fill layer seams fix
* Import changes for circle and heatmap layers from the main vector globe branch

* Minor refactors

* Update build size

* Use "/ 8.0" in shader instead of "* 0.125"

* Update shader comments

* Use a thin type instead of full Transform in projection

* Only import types in projection.ts

* getPixelScale and getCircleRadiusCorrection only need map center as argument

* Only import types where possible in projection classes

* Smaller refactors

* Fix failing unit test

* Add heatmap render test

* More explicit types in projection interface

* Globe plane equation is a vec4

* Fix wrong args in projection functions
* Import changes from main vector globe branch

* Fix import

* Remove unused code

* Remove unused imports

* Update build size test

* Remove unused function

* Add render test results for Debian

* Add another Debian render test variant

* Add more render test variants

* Hide collision boxes on the backfacing side of the globe

* Fix pitch-aligned texts getting hidden when their anchor is beyond horizon

* Update build size

* Fix merge

* Better comment in draw_collision_debug

* Update build size

The 10 kb size increase seems to come from the main branch

* Minor refactor

* Use explicit types, even for unused parameters

* Refactor screenspace path projection

* Refactor imports for projection.ts and collision_index.ts

* Fix import in collision_index.ts
* Add example images

* Add "-" into example name

* Remove basic globe example
* HiSilicon fix: enable face culling whereever possible

(cherry picked from commit fe439a5)

* Improve circle layer performance by discarding empty pixels

(cherry picked from commit 266897d)

* HiSilicon fix: software clipping of polygon outlines

(cherry picked from commit 98167ba)

* HiSilicon fix: software clipping for line layer

(cherry picked from commit d521e95)

* HiSilicon fix: circle software clipping

(cherry picked from commit f2ed744)

* HiSilicon fix: enable backface culling for symbols

(cherry picked from commit 54e3632)

* Update build test

* Fix terrain using a mirrored projection matrix

* Fix typos

* Fix terrain coord textures being flipped vertically

* Update build size

* Fix rendering of images with face culling, fix image rendering near pole regions

* Add render test for images on a globe

* Update comment in circle.vertex.glsl
@HarelM
Copy link
Collaborator

HarelM commented Oct 28, 2024

I think this looks good now, besides a few minor comments.
If we can also nail removing the coveringTiles method from the transform interface to a method that receives IReadonlyTransform it will be great!
It might be an interesting case for the suggested CalculateTileZoomFunction to see if it can facilitate the difference between globe an mercator? This is just a thought to see if the provided interface can cover this scenario, or if more parameters are needed. IDK, not mandatory, just a thought experiment I guess...

@NathanMOlson NathanMOlson marked this pull request as draft October 28, 2024 23:48
@NathanMOlson
Copy link
Contributor Author

It might be an interesting case for the suggested CalculateTileZoomFunction to see if it can facilitate the difference between globe an mercator?

Not as currently implemented. Some of the inputs to CalculateTileZoomFunction are calculated differently depending on the projection.

@@ -293,6 +292,7 @@ export class GlobeTransform implements ITransform {
this._globeness = globeProjectionEnabled ? 1 : 0; // When transform is cloned for use in symbols, `_updateAnimation` function which usually sets this value never gets called.
this._projectionInstance = globeProjection;
this._mercatorTransform = new MercatorTransform();
this._coveringTilesDetailsProvider = new GlobeCoveringTilesDetailsProvider();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be injected instead of instantiated in the constructor?

distanceToCenter3D: number,
cameraVerticalFOV: number) => number;

export interface CoveringTilesDetailsProvider {
Copy link
Collaborator

@HarelM HarelM Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this interface be in a different file?

const distanceSmallest = Math.min(distanceCurrent, distanceLeft, distanceRight);
if (distanceSmallest === distanceRight) {
return 1;
export class GlobeCoveringTilesDetailsProvider implements CoveringTilesDetailsProvider {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be in a different file?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is this the main class now in this file?
If so, consider changing the file name.

distanceSq: number;
tileDistanceToCamera: number;
};
export class MercatorCoveringTilesDetailsProvider implements CoveringTilesDetailsProvider {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as previous one, I think this file needs a rename...?

* @returns Array of OverscaledTileID. All OverscaledTileID instances are newly created.
*/
coveringTiles(options: CoveringTilesOptions): Array<OverscaledTileID>;
getCameraFrustum(): Frustum;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some tsdocs comments to better explain what these methods are for.

@HarelM
Copy link
Collaborator

HarelM commented Oct 31, 2024

This looks good! Seems like there's some issue with the render tests.
I've added minor comments, but otherwise, this can be merged I believe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants