Skip to content

Commit 86ed382

Browse files
NathanMOlsonkubapelcHarelMPheonor
authored
Camera Roll (maplibre#4780)
* Globe - basic infrastructure, raster layer adaptation for globe (maplibre#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 * Globe - fill layer (maplibre#3882) * 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 build due to bad merge. * Globe - line layer (maplibre#3961) * 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 * Globe - fill extrusion layer (maplibre#3968) * 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 * Kubapelc/globe pr hillshade (maplibre#3979) * 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 * Globe - circle and heatmap layers (maplibre#4015) * 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 * Improve readibility of build test and fix it. * Globe - symbols & symbol bugfixes (maplibre#4067) * 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 * Globe - example images (maplibre#4140) * Add example images * Add "-" into example name * Remove basic globe example * Globe - clipping fix (maplibre#4146) * 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 * Fix bad merge * Fix lint * Fix location of old vertex count * replace expected file for terrain changes * Fix rename in main merge branch * Fix build test * Move projection to style class (maplibre#4267) * Move projection to style class * Fix lint * Fix unit tests * Increase build size * Update docs, fix test * Fix lint * Add test to cover projection change * Added more tests * Add an Atmosphere layer for Globe (maplibre#3888) (maplibre#4020) * Port of PoC atmosphere layer. * Fix resize for draw_atmosphere * Add some options. * Allow to change sun date and time * Fix import warning * Render atmosphere only when a Globe projection is selected * Add some comments * Add some comments * Change key * Update changelog * Fix merge with globe branch * Fix documentation and default background color. * Use black clear color only when atmosphere is on * Use atmosphere uniform for globe position, raidus in camera frame and inv projection matrix. * Remove unused project method * Update maplibre-gl-style-spec to 20.3.0 and use sky atmosphere parameter * Fix globe tests and use light position as Sun position. * Avoid type name collisions. * Add atmosphere test for globe projection. * Update expectedBytes for build test. * Fix PR comments. * Update Style test. * Remove unused method on projection * Add Sky Test. * Fix style test and add sky unit test. * Move getSunPos method * Fix mercator updateProjection * Remove isGlobe method and fix merge. * Fix globe atmosphere tests with new projection style. * Clean-up some projection and light. Fix setSky and add tests. * Remove sky test during update. * Clean-up * missing fix from merge * Fix lint * Terrain fix (maplibre#4343) * Fix missing image for globe example * Update atmosphere (maplibre#4345) * Merge Sky and Atmosphere code. * Update changelog * Fix generate-struct-arrays * Globe - transform+projection changes (maplibre#4341) * Delete unused file * Rename projection.name to projection.projectionName Since this interface will be implemented by the transfrom class soon * Symbols: displayed collision circles now exactly match their computed positions * Globe: use mercator projection for symbol placement when globe rendering is disabled * Group all getters/setters in the transform class * Transform: move transform-related stuff from the projection interface to transform class (WIP) * Transform: finish moving parts of projection into mercator_transform.ts * Transform: remove posMatrix usage from line symbol placement (WIP) * Transform: temporarily remove globe stuff (WIP, compilable) * Transform: fix line symbols * Symbols: fix wrong function names * Fix line point projections * Fix line rendering Some things are still broken * Fix line symbols sometimes being incorrectly oriented * Fix some failing unit tests * Fix single glyph orientation * Add another image to render test No idea why it is shifted by a few pixels but I assume that the new expected image is also correct * Add another expected image to textFit-grid-long test It was only failing on my machine, works fine in github CI windows tests * Fix some failing unit tests * Simplify getProjectionData interface and terrain matrix passing * Change comment at calculatePosMatrix * Fix symbols not rendering, remove unused shader parameters * Bring back globe src files * globe.test.ts is now globe_transform.test.ts * Move stuff from globe.ts to globe_transform.ts * Fix showTileBoundaries not working Fix the three render tests related to showTileBoundaries timing out. * Remove irrelevant test * Fix failing unit test * Transform: move more stuff from globe to globe_transform * Transform: better comments * Transfrom: isRenderingDirty cleanup * Transform: no more errors in globe_transform.ts * Transform: remove `get point()` from transform class * Transform: globe_transform.ts is compilable * Re-enable globe projection * Fix source_cache.ts sometimes crashing * Fix globe.ts - globe_transform.ts circular dependency * Fix and refactor getProjectionData interface Now it is actually compilable, with many bugs * Transform: fix failing unit tests * Transform: fix symbols not rendering on globe * Transform: minor fixes * Transform: update globe symbol render tests * Transform: unify how symbol/projection.ts exports stuff * Transform: improve comments * Remove unused function in painter * Transform: cleanup unneeded abstract functions * Transform: replace abstract getHorizon function with more generic isPointOnMapSurface function * Fix useGlobeRendering not being set properly * Transform: proper implementation of isPointOnMapSurface and screen pixel unprojection for globe * Transform: adapt more functions for globe * Transform: fix locationPoint implementation * Controls: globe panning experiments * Controls: reasonable globe panning * Controls: centering zoom for globe experiment * Transform: fix globe unit tests * Transform: fix remaining unit tests * Move mercator_transform.test to src/geo/projection * Transform: globe bugfixes and more unit tests * Transform: bugfix globe setLocationAtPoint * Transform: isolate accesses to globe projection to avoid unintentional transform's state changes * Transform: move related tests so they are near each other * Transform: improve globe unprojection accuracy * Transform: fix globe bugs * Transform: move globe unit tests * Transform: another globe setLocationAtPoint implementation * Transform: fix globe zoom adjustment not working * Transform: fix setLocationAtPoint * Transform: setLocationAtPoint and zoom WIP * Transform: adjust unit test to accept positive longitudes * Transform: improve globe math precision (fp64) * Transform: precision improvement, better camera position * Transform: another test WIP * Transform: fix setLocationAtPoint condition * Transform: more reasonable zoom for globe Still has bugs though * Transform: globe zoom works well when cursor is outside the globe * Transform: globe more consistent zoom logic * Transform: experimental pole edge clamp for globe * Transform: fix maxLatitudeForZoomLevel math * Transform: globe constrain experiment * Transform: minor improvements * Transform: globe panning 2.0 * Transform: globe panning 2.1 Adjust more constants! * Transform: some math for globe zoom * Transform: globe: working zoom controls without glitches * Transform: globe zoom: fix some more glitching * Transform: globe zoom: reduce panning when zoom pixel is far from the planet * Transform: zoom globe: simplify, better behaviour around poles * Transform: globe zoom: exact zooming * Transform: globe zoom: better comments * Transform: temporarily disable camera easeTo and flyTo * Transform: calling project/unproject on a globe should fail, rename project/unproject to be more descriptive * Transform: fitBounds: initial implementation for globe_transform Not working * Transform: fitBounds: zoom is now correct * Transform: fitBounds: padding works for north/south * Transform: fitBounds: just build on top of mercator code * Transform: fitBounds: the original way * Transform: fitBounds: back to mercator-buildon + done * Transform: tighter bounds for zoom heuristic transition * Transform: easeTo: probably works * Transform: attempt to handle camera options apparent zoom for globe * Transform: easeTo fixes WIP * Transform: easeTo: mostly working implementation (still WIP) * Transform: easeTo: small fixes * Transform: easeTo: intertia works for panning * Transform: globe zoom: add globe radius based slowing factor * Transform: globe zoom adjustments * Transform: jumpTo adapted for globe * Transform: camera flyTo works for globe * Make (un)projectToWorldCoordinates into standalone functions * Fix inertia sometimes rotating in the wrong direction * Fix transform center sometimes not getting wrapped, leading to visual artifacts * Transform: easeTo: slerp experiment * Transform: easeTo: revert slerp, add note on why it is not used * Transform: improve center animation for easeTo and flyTo * Minor refactor & remove some outdated TODOs * More refactor and TODOs * Transform: globe remembers its globeness state after clone, fixes improper collision box when globe gets soft-disabled * Terrain matrix refactor WIP * Terrain fixes * Transform: better comments, rename angularCoordinatesToVector to angularCoordinatesToSurfaceVector, some functions for globe WIP * Transform: getBounds for globe works * Transform: remove some comments * Fix merge * Remove globe.test.ts (it is now globe_transform.test.ts) * Rename Transform.updateProjection to newFrameUpdate * Revert globe.ts to pre-merge state * Revert mercator.ts to pre-merge state * New mechanism for creating specialized transforms, more merge fixes * Rename projectionMatrix to modelViewProjectionMatrix, refactor mercator_transform.ts a bit * More merge fixes, minor refactor of transforms * Add transform getters for atmosphere * Fix forgotten useGlobeControls uses * Fix cyclical dependency * Fix tests * Fix crashes * Fix manually triggered globe transition animation * Fix collision boxes not respecting mercator transition * Blend out atmosphere when transitioning to mercator * Fix globe transitions when mercator should be constrained * Reload all tiles upon projection change * Fix failing style tests * Fix terrain source cache tests * Fix map zoom&center being applied in wrong order, causing zoom to be wrongly constrained under globe * Update globe pole render tests with correct zoom * Update globe unit test zooms * Fix more unit tests * Fix transform.apply not copying everything, fix globe controls not wrapping longitudes * Fix some globe tests * Fix globe setLocationAtPoint * Fix docs & lint * Increase globe setLocationAtPoint test desired precision * Some camera tests for globe * Fix easeTo test suite name and placing * Add rotated setLocationAtPoint test for globe, fix failing test * Fix globe easeTo & flyTo with bearing to follow spec, add tests * easeTo globe tests * All relevant camera tests for globe implemented * Update build size test * Fix symbols not respecting mercator * Update build size again * Terrain fix * Fix merge * Fix terrain shaders * Fix merge * Revert controls changes * Fix reverted files * Fix reverted camera tests * Revert forgotten file, fix lint * Update build size * Feedback comments for unit tests * Convert setters to functions: runtime code * Convert setters to functions: test code * Convert last setter to function * Fix some tests * Transform is now an interface * Rename Transform to ITransform * Remove abstract functions from transform base class * TransformHelper wip * Rename transform files * Finish transform rewrite * Fix mercator transform tests * Fix mercator_transform constructor * Fix symbol bucket test * Fix source cache tests * Fix transform clone bug & tests * Improve comments * More comments * Fix import * Move helper functions in tests to beginning of file * Fix collision index test accessing a private field * Remove unneeded null check * New utils tests + quadratic solve fix * Add remapSaturate tests * Add explicit types to line glyph placement * Refactor placeGlyphsAlongLine args into an object * Fix merge, cleanup draw_custom.test, fix missing perspective offset in globe transform * Fix draw_custom test * Update build test * Fix crashes * Fix transform_helper apply function not setting bearing correctly * Add test for TransformHelper * Fix TransformHelper.apply * Fix flipped text placement * Add new expected image to render test * Fix marker tests * Update build size * Move functions from mercator_transform.ts to mercator_utils.ts * Refactor un/projectToWorldCoordinates function args * Make zoomScale and scaleZoom standalone functions * Fix unprojectFromWorldCoordinates arg type * Move globe functions to separate file * Fix private member access in source_cache.test.ts * Fix deck.gl missing dot * Fix missing globe_utils.ts * Better `angleToRotateBetweenVectors2D` doccomment * Remove unneeded `protected` * Cleanup transform interface and remove duplicate comments * Split mercator_utils tests into a separate file * Fix tests * Split globe locationPoint tests a bit * Add more mercator tests * More globe tests * Fix globe getBounds and add tests for it * Remove unneeded function, update build size * projectTileCoordinates for globe now covered by test * Add globe_utils tests * Split up globe tests more * Fix missing doccomment * Rename transform's projection/unprojection functions * Better ray intersection comment and type * Reduce indentation * Improve unproject math readability * Add point-plane distance util function * Move tileCoordinatesToMercatorCoordinates to mercator_utils * Better name for location to mercator coordinate functions * Move angleToRotateBetweenVectors2D to utils * Refactor _globeness usage * Remove _initialized from GlobeTransform * Remove translatePosition from transform interface * Add IReadonlyTransform interface * Update build size * Remove unneeded comment * Fix painter test * Fix lint * Update test/build/min.test.ts * Update changelog * Globe - camera controls (maplibre#4408) * Camera controls changes from dev branch * Move stuff from globe_control_utils to globe_utils * Better globe_utils comments * Fix markers not being updated when globe is toggled * Fix globe tests * Update build size * Better comments for camera helper functions * Move camera helper functions to beginning of file * Camera: more and better comments * Update build size * Fix globe transform error correction handling * Better comments for _last* fields in globe transform * Refactor newFrameUpdate * Better comments for CoveringTilesOptions type members. * Refactor globe camera tests to use more describe statements * Remove isTilePositionOccluded function from transform interface * Fix camera tests * Add more mercator_utils test * Add more globe_transform tests * Fix failing render tests * Make camera helper functions static * Remove `around` from flyTo options. * Update build size * CameraHelper: initial implementation, inertia handling * Move createVec* functions to util.ts * CameraHelper: panning and zooming * CameraHelpers: implement cameraForBounds * CameraHelpers: handle jumpTo * CameraHelper: easeTo * CameraHelper: flyTo * Projection event contains new projection name and is fired by changing style's projection * Fix lint * Fix test camera/map not having proper CameraHelper * Fix easeTo not emitting zoom events * Fix cameraForBoxAndBearing globe not returning anything, rename camera helter types * Fix globe easeTo ignoring offset * Fix one flyTo test not creating camera properly * Update build size * Add projection transition event tests * Add example on how to compensate for how globe size changes with latitude * Revert scrollzoom delete removal * Remove apparentZoom parameter * CameraHelper is set in camera constuctor * Use spy for projection event unit tests * Remove unnecessary done() in tests * Update build size * Remove more unneeded done() calls * Do not use map.once callback in projection events tests * Better zoom delta example title and description * Rename globe zoom delta and planet size function example * Add zoom planet size function example image * Reduce size of some globe example images using compresspng * Globe: bugfixes: raster layer & projection change (maplibre#4546) * Port bugfix changes * Update build size * Fix render tests * Add render test result for debian * Increase raster tile granularity some more * Adjust warped raster tile render test * Add missing tsdoc param * Use single checkerboard image for render test * Globe examples now use setProjection * Add new raster-pole render test image * Add another raster-warped expected image * Use "style.load" event on map instead of on style * Adapt new heatmap code for globe, update build size * Fix render tests Most tests had subpixel shifts * Globe - custom layers API and examples, globe dev guide (maplibre#4577) * Port custom layer changes and globe docs * Port transform changes * Fix custom layer unit test * Fix failing render tests * Update build size * Update globe custom layer example descritions, remove forgotten code * Remove unused util function * Incorporate globe docs feedback * Refactor and expose tile mesh generation * Refactor custom layers to get smaller args object and access map transform directly * Simplify more of the custom layer API * Clean up and adapt more examples * Fix mercator matrix precision * Fix 3D model on terrain example * Rename projectionDataForMercatorCoords to defaultProjectionData * Document ProjectionData type * Update build size * Update developer-guides/globe.md Co-authored-by: Harel M <[email protected]> * Decouple ProjectionData from rendering code Rename fields to camelCase, move it to a separate file * Rename ProjectionData members * Fix mercator transform unit tests * Add an example to createTileMesh * Rename CustomRenderMethodInput.shader to shaderData * Add shaderData examples * Document TileMesh and CreateTileMeshOptions types * Fix custom layers in render tests * Update render tests Fails other than raster-warped were caused by increasing pos matrix precision in mercator_transform to 64 bit floats * Add render test result from linux * Update build size * Update src/render/program/projection_program.ts Co-authored-by: Harel M <[email protected]> * Rename createTileMeshInternal to createTileMeshWithBuffers * Update build size * Improve doc comments --------- Co-authored-by: Harel M <[email protected]> * Globe - Covering tiles (maplibre#4615) * Import coveringTiles changes from dev branch * Remove duplicated tiles used in render tests * Remove unused function * Fix typo * Properly handle tile wraps and LOD across antimeridian * Discard previous changes and use custom wrap values instead * Update build size * Add render test for LOD at antimeridian * Convert visibility numbers to enum * Refactor globe covering tiles into a separate file * Add yet another raster-warped expected image * Add unit tests for globe covering tiles * Refactor globe coveringTiles math to assume worldSize=1 instead of tileSize=1 * Split globe coveringTiles into more functions * Explain radiusOfMaxLvlLodInTiles value * Explain why checking 4 tile corners is (mostly) enough to construct an AABB. * Move mercator coveringTiles into a separate file * Yet another raster-warped expected image * Remove ITileVisibilityProvider interface * Use explicit types * PR feedback * Rename coveringTiles stack types * fix typo * Remove sky disabling in examples as this is no longer needed. * Fix spelling * Fix spelling - unencode * Fix more spelling * Fix lint * Add basic roll capability * code hygiene * update sky shader to use roll angle * fix horizon /sky display when rolled * reduce repeat calls to potentially expensive functions * use slerp instread of euler angle interpolation for mercator easeTo(). Also reverses definition of roll. * safe roll pitch bearing near singularity * add option to use slerp or old linear interpolation of Euler angles * code hygiene * code hygiene * fix unit tests * add roll unit tests * change euler angle behavior at the end of easeTo() to use the representation specified by the caller. This only matters at the singularity (pitch = 0) * unit tests fro R2D and D2R * add euler angle unit tests * add roll to transform unit tests * add roll to transform helper test * code hygiene * add sky and fog render tests * code hygiene * this rotates labels as I intended it to when pitchWithMap = true, rotateWithMap= false, but I don't think that's what we want * Revert "this rotates labels as I intended it to when pitchWithMap = true, rotateWithMap= false, but I don't think that's what we want" This reverts commit 01845a9. * extend rotateWithMap to include the effects of camera roll * Add roll icon render tests * getPitchedLabelPlaneMatrix unit tests * add getPitchedLabelPlaneMatrix unit test * add getGlCoordMatrix unit tests * remove console.log * code hygiene * add roll text alignment render tests * fix lint * add text upright with roll render test * add combined rotation text upright render test * add text-pitch-scaling render test with roll * fix collision box when camera is rolled * add skew matrix tests at horizon. * faster getTileSkewMatrix * update changelog * updated expected build size * remove "useSlerp" flag from mercator transform, and use slerp in globe transform as well. * fix merge error * increase test coverage * switch from _underscore fields to getters * add render text for different text alignments with rolled horizon present. * change private angle names in transform to include prefix "InRadians", and add getters directly in radians. Remove ambiguous member "angle", which was negative bearingInRadians. * updated library size * use *InRadians where possible * combine duplicate interpolation code from mercator and globe * add roll to root style spec * change getTileSkewMatrix to return vectors instead of mat2 * fix lint * Add roll visualization to Navigation Control, and add mouse control of roll using Ctrl + right click. * Update style spec and remove "as any" in jumpTo() * rearrrange if-else * add roll and pitch control and visualization to navigation example * update build size * fix bad changelog merge * add mouseRollHandler and DragRotateHandler unit tests --------- Co-authored-by: Jakub Pelc <[email protected]> Co-authored-by: HarelM <[email protected]> Co-authored-by: Larrieu Vivian <[email protected]> Co-authored-by: Jakub Pelc <[email protected]>
1 parent 9c62b8b commit 86ed382

File tree

84 files changed

+2096
-189
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2096
-189
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## main
22

33
### ✨ Features and improvements
4+
- Add support for camera roll angle ([#4717](https://github.com/maplibre/maplibre-gl-js/issues/4717))
45
- _...Add new stuff here..._
56

67
### 🐞 Bug fixes

src/geo/projection/camera_helper.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import {LngLat, LngLatLike} from '../lng_lat';
44
import {CameraForBoundsOptions, PointLike} from '../../ui/camera';
55
import {PaddingOptions} from '../edge_insets';
66
import {LngLatBounds} from '../lng_lat_bounds';
7-
import {warnOnce} from '../../util/util';
7+
import {getRollPitchBearing, RollPitchBearing, warnOnce} from '../../util/util';
8+
import {quat} from 'gl-matrix';
89

910
export type MapControlsDeltas = {
1011
panDelta: Point;
1112
zoomDelta: number;
1213
bearingDelta: number;
1314
pitchDelta: number;
15+
rollDelta: number;
1416
around: Point;
1517
}
1618

@@ -23,6 +25,7 @@ export type CameraForBoxAndBearingHandlerResult = {
2325
export type EaseToHandlerOptions = {
2426
bearing: number;
2527
pitch: number;
28+
roll: number;
2629
padding: PaddingOptions;
2730
offsetAsPoint: Point;
2831
around?: LngLat;
@@ -41,6 +44,7 @@ export type EaseToHandlerResult = {
4144
export type FlyToHandlerOptions = {
4245
bearing: number;
4346
pitch: number;
47+
roll: number;
4448
padding: PaddingOptions;
4549
offsetAsPoint: Point;
4650
center?: LngLatLike;
@@ -78,7 +82,7 @@ export interface ICameraHelper {
7882
easingOffset: Point;
7983
};
8084

81-
handleMapControlsPitchBearingZoom(deltas: MapControlsDeltas, tr: ITransform): void;
85+
handleMapControlsRollPitchBearingZoom(deltas: MapControlsDeltas, tr: ITransform): void;
8286

8387
handleMapControlsPan(deltas: MapControlsDeltas, tr: ITransform, preZoomAroundLoc: LngLat): void;
8488

@@ -90,3 +94,29 @@ export interface ICameraHelper {
9094

9195
handleFlyTo(tr: ITransform, options: FlyToHandlerOptions): FlyToHandlerResult;
9296
}
97+
98+
/**
99+
* @internal
100+
* Set a transform's rotation to a value interpolated between startRotation and endRotation
101+
* @param startRotation - the starting rotation (rotation when k = 0)
102+
* @param endRotation - the end rotation (rotation when k = 1)
103+
* @param endEulerAngles - the end Euler angles. This is needed in case `endRotation` has an ambiguous Euler angle representation.
104+
* @param tr - the transform to be updated
105+
* @param k - the interpolation fraction, between 0 and 1.
106+
*/
107+
export function updateRotation(startRotation: quat, endRotation: quat, endEulerAngles: RollPitchBearing, tr: ITransform, k: number) {
108+
// At pitch ==0, the Euler angle representation is ambiguous. In this case, set the Euler angles
109+
// to the representation requested by the caller
110+
if (k < 1) {
111+
const rotation: quat = new Float64Array(4) as any;
112+
quat.slerp(rotation, startRotation, endRotation, k);
113+
const eulerAngles = getRollPitchBearing(rotation);
114+
tr.setRoll(eulerAngles.roll);
115+
tr.setPitch(eulerAngles.pitch);
116+
tr.setBearing(eulerAngles.bearing);
117+
} else {
118+
tr.setRoll(endEulerAngles.roll);
119+
tr.setPitch(endEulerAngles.pitch);
120+
tr.setBearing(endEulerAngles.bearing);
121+
}
122+
}

src/geo/projection/globe_camera_helper.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import Point from '@mapbox/point-geometry';
22
import {IReadonlyTransform, ITransform} from '../transform_interface';
3-
import {cameraBoundsWarning, CameraForBoxAndBearingHandlerResult, EaseToHandlerResult, EaseToHandlerOptions, FlyToHandlerResult, FlyToHandlerOptions, ICameraHelper, MapControlsDeltas} from './camera_helper';
3+
import {cameraBoundsWarning, CameraForBoxAndBearingHandlerResult, EaseToHandlerResult, EaseToHandlerOptions, FlyToHandlerResult, FlyToHandlerOptions, ICameraHelper, MapControlsDeltas, updateRotation} from './camera_helper';
44
import {GlobeProjection} from './globe';
55
import {LngLat, LngLatLike} from '../lng_lat';
66
import {MercatorCameraHelper} from './mercator_camera_helper';
77
import {angularCoordinatesToSurfaceVector, computeGlobePanCenter, getGlobeRadiusPixels, getZoomAdjustment, globeDistanceOfLocationsPixels, interpolateLngLatForGlobe} from './globe_utils';
8-
import {clamp, createVec3f64, differenceOfAnglesDegrees, remapSaturate, warnOnce} from '../../util/util';
9-
import {mat4, vec3} from 'gl-matrix';
8+
import {clamp, createVec3f64, differenceOfAnglesDegrees, remapSaturate, rollPitchBearingToQuat, warnOnce} from '../../util/util';
9+
import {mat4, quat, vec3} from 'gl-matrix';
1010
import {MAX_VALID_LATITUDE, normalizeCenter, scaleZoom, zoomScale} from '../transform_helper';
1111
import {CameraForBoundsOptions} from '../../ui/camera';
1212
import {LngLatBounds} from '../lng_lat_bounds';
@@ -48,9 +48,9 @@ export class GlobeCameraHelper implements ICameraHelper {
4848
};
4949
}
5050

51-
handleMapControlsPitchBearingZoom(deltas: MapControlsDeltas, tr: ITransform): void {
51+
handleMapControlsRollPitchBearingZoom(deltas: MapControlsDeltas, tr: ITransform): void {
5252
if (!this.useGlobeControls) {
53-
this._mercatorCameraHelper.handleMapControlsPitchBearingZoom(deltas, tr);
53+
this._mercatorCameraHelper.handleMapControlsRollPitchBearingZoom(deltas, tr);
5454
return;
5555
}
5656

@@ -59,6 +59,7 @@ export class GlobeCameraHelper implements ICameraHelper {
5959

6060
if (deltas.bearingDelta) tr.setBearing(tr.bearing + deltas.bearingDelta);
6161
if (deltas.pitchDelta) tr.setPitch(tr.pitch + deltas.pitchDelta);
62+
if (deltas.rollDelta) tr.setRoll(tr.roll + deltas.rollDelta);
6263
const oldZoomPreZoomDelta = tr.zoom;
6364
if (deltas.zoomDelta) tr.setZoom(tr.zoom + deltas.zoomDelta);
6465
const actualZoomDelta = tr.zoom - oldZoomPreZoomDelta;
@@ -191,6 +192,7 @@ export class GlobeCameraHelper implements ICameraHelper {
191192
clonedTr.setCenter(result.center);
192193
clonedTr.setBearing(result.bearing);
193194
clonedTr.setPitch(0);
195+
clonedTr.setRoll(0);
194196
clonedTr.setZoom(result.zoom);
195197
const matrix = clonedTr.modelViewProjectionMatrix;
196198

@@ -259,9 +261,12 @@ export class GlobeCameraHelper implements ICameraHelper {
259261
}
260262

261263
const startZoom = tr.zoom;
262-
const startBearing = tr.bearing;
263-
const startPitch = tr.pitch;
264264
const startCenter = tr.center;
265+
const startRotation = rollPitchBearingToQuat(tr.roll, tr.pitch, tr.bearing);
266+
const endRoll = options.roll === undefined ? tr.roll : options.roll;
267+
const endPitch = options.pitch === undefined ? tr.pitch : options.pitch;
268+
const endBearing = options.bearing === undefined ? tr.bearing : options.bearing;
269+
const endRotation = rollPitchBearingToQuat(endRoll, endPitch, endBearing);
265270

266271
const optionsZoom = typeof options.zoom !== 'undefined';
267272

@@ -312,11 +317,8 @@ export class GlobeCameraHelper implements ICameraHelper {
312317
isZooming = (endZoomWithShift !== startZoom);
313318

314319
const easeFunc = (k: number) => {
315-
if (startBearing !== options.bearing) {
316-
tr.setBearing(interpolates.number(startBearing, options.bearing, k));
317-
}
318-
if (startPitch !== options.pitch) {
319-
tr.setPitch(interpolates.number(startPitch, options.pitch, k));
320+
if (!quat.equals(startRotation, endRotation)) {
321+
updateRotation(startRotation, endRotation, {roll: endRoll, pitch: endPitch, bearing: endBearing}, tr, k);
320322
}
321323

322324
if (options.around) {

src/geo/projection/globe_transform.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,16 @@ describe('GlobeTransform', () => {
130130
globeTransform.setBearing(70);
131131
expectToBeCloseToArray(globeTransform.cameraPosition as Array<number>, [-0.7098603286961542, 2.002400604307631, 0.6154310261827212], precisionDigits);
132132

133+
globeTransform.setPitch(35);
134+
globeTransform.setBearing(70);
135+
globeTransform.setRoll(40);
136+
expectToBeCloseToArray(globeTransform.cameraPosition as Array<number>, [-0.7098603286961542, 2.002400604307631, 0.6154310261827212], precisionDigits);
137+
138+
globeTransform.setPitch(35);
139+
globeTransform.setBearing(70);
140+
globeTransform.setRoll(180);
141+
expectToBeCloseToArray(globeTransform.cameraPosition as Array<number>, [-0.7098603286961542, 2.002400604307631, 0.6154310261827212], precisionDigits);
142+
133143
globeTransform.setCenter(new LngLat(-10, 42));
134144
expectToBeCloseToArray(globeTransform.cameraPosition as Array<number>, [-3.8450970996236364, 2.9368285470351516, 4.311953269048194], precisionDigits);
135145
});

src/geo/projection/globe_transform.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ export class GlobeTransform implements ITransform {
9393
setPitch(pitch: number): void {
9494
this._helper.setPitch(pitch);
9595
}
96+
setRoll(roll: number): void {
97+
this._helper.setRoll(roll);
98+
}
9699
setFov(fov: number): void {
97100
this._helper.setFov(fov);
98101
}
@@ -151,9 +154,6 @@ export class GlobeTransform implements ITransform {
151154
get height(): number {
152155
return this._helper.height;
153156
}
154-
get angle(): number {
155-
return this._helper.angle;
156-
}
157157
get lngRange(): [number, number] {
158158
return this._helper.lngRange;
159159
}
@@ -181,12 +181,27 @@ export class GlobeTransform implements ITransform {
181181
get pitch(): number {
182182
return this._helper.pitch;
183183
}
184+
get pitchInRadians(): number {
185+
return this._helper.pitchInRadians;
186+
}
187+
get roll(): number {
188+
return this._helper.roll;
189+
}
190+
get rollInRadians(): number {
191+
return this._helper.rollInRadians;
192+
}
184193
get bearing(): number {
185194
return this._helper.bearing;
186195
}
196+
get bearingInRadians(): number {
197+
return this._helper.bearingInRadians;
198+
}
187199
get fov(): number {
188200
return this._helper.fov;
189201
}
202+
get fovInRadians(): number {
203+
return this._helper.fovInRadians;
204+
}
190205
get elevation(): number {
191206
return this._helper.elevation;
192207
}
@@ -472,13 +487,13 @@ export class GlobeTransform implements ITransform {
472487
// - "cam" is camera origin
473488
// - "C" is globe center
474489
// - "B" is the point on "top" of the globe - camera is looking at B - "B" is the intersection between the camera center ray and the globe
475-
// - this._pitch is the angle at B between points cam,B,A
490+
// - this._pitchInRadians is the angle at B between points cam,B,A
476491
// - this.cameraToCenterDistance is the distance from camera to "B"
477492
// - globe radius is (0.5 * this.worldSize)
478493
// - "T" is any point where a tangent line from "cam" touches the globe surface
479494
// - elevation is assumed to be zero - globe rendering must be separate from terrain rendering anyway
480495

481-
const pitch = this.pitch * Math.PI / 180.0;
496+
const pitch = this.pitchInRadians;
482497
// scale things so that the globe radius is 1
483498
const distanceCameraToB = this.cameraToCenterDistance / globeRadiusPixels;
484499
const radius = 1;
@@ -504,7 +519,7 @@ export class GlobeTransform implements ITransform {
504519
// Note the swizzled components
505520
const planeVector: vec3 = [0, vectorCtoCamX, vectorCtoCamY];
506521
// Apply transforms - lat, lng and angle (NOT pitch - already accounted for, as it affects the tangent plane)
507-
vec3.rotateZ(planeVector, planeVector, [0, 0, 0], this.angle);
522+
vec3.rotateZ(planeVector, planeVector, [0, 0, 0], -this.bearingInRadians);
508523
vec3.rotateX(planeVector, planeVector, [0, 0, 0], -1 * this.center.lat * Math.PI / 180.0);
509524
vec3.rotateY(planeVector, planeVector, [0, 0, 0], this.center.lng * Math.PI / 180.0);
510525
// Scale the plane vector up
@@ -609,7 +624,7 @@ export class GlobeTransform implements ITransform {
609624
const globeMatrixUncorrected = createMat4f64();
610625
this._nearZ = 0.5;
611626
this._farZ = this.cameraToCenterDistance + globeRadiusPixels * 2.0; // just set the far plane far enough - we will calculate our own z in the vertex shader anyway
612-
mat4.perspective(globeMatrix, this.fov * Math.PI / 180, this.width / this.height, this._nearZ, this._farZ);
627+
mat4.perspective(globeMatrix, this.fovInRadians, this.width / this.height, this._nearZ, this._farZ);
613628

614629
// Apply center of perspective offset
615630
const offset = this.centerOffset;
@@ -620,8 +635,9 @@ export class GlobeTransform implements ITransform {
620635
this._globeProjMatrixInverted = createMat4f64();
621636
mat4.invert(this._globeProjMatrixInverted, globeMatrix);
622637
mat4.translate(globeMatrix, globeMatrix, [0, 0, -this.cameraToCenterDistance]);
623-
mat4.rotateX(globeMatrix, globeMatrix, -this.pitch * Math.PI / 180);
624-
mat4.rotateZ(globeMatrix, globeMatrix, -this.angle);
638+
mat4.rotateZ(globeMatrix, globeMatrix, this.rollInRadians);
639+
mat4.rotateX(globeMatrix, globeMatrix, -this.pitchInRadians);
640+
mat4.rotateZ(globeMatrix, globeMatrix, this.bearingInRadians);
625641
mat4.translate(globeMatrix, globeMatrix, [0.0, 0, -globeRadiusPixels]);
626642
// Rotate the sphere to center it on viewed coordinates
627643

@@ -647,8 +663,9 @@ export class GlobeTransform implements ITransform {
647663
const zero = createVec3f64();
648664
this._cameraPosition = createVec3f64();
649665
this._cameraPosition[2] = this.cameraToCenterDistance / globeRadiusPixels;
650-
vec3.rotateX(this._cameraPosition, this._cameraPosition, zero, this.pitch * Math.PI / 180);
651-
vec3.rotateZ(this._cameraPosition, this._cameraPosition, zero, this.angle);
666+
vec3.rotateZ(this._cameraPosition, this._cameraPosition, zero, -this.rollInRadians);
667+
vec3.rotateX(this._cameraPosition, this._cameraPosition, zero, this.pitchInRadians);
668+
vec3.rotateZ(this._cameraPosition, this._cameraPosition, zero, -this.bearingInRadians);
652669
vec3.add(this._cameraPosition, this._cameraPosition, [0, 0, 1]);
653670
vec3.rotateX(this._cameraPosition, this._cameraPosition, zero, -this.center.lat * Math.PI / 180.0);
654671
vec3.rotateY(this._cameraPosition, this._cameraPosition, zero, this.center.lng * Math.PI / 180.0);

src/geo/projection/globe_utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,13 @@ export function getDegreesPerPixel(worldSize: number, lat: number): number {
137137
* @returns New center location to set to the map's transform to apply the specified panning.
138138
*/
139139
export function computeGlobePanCenter(panDelta: Point, tr: {
140-
readonly angle: number;
140+
readonly bearingInRadians: number;
141141
readonly worldSize: number;
142142
readonly center: LngLat;
143143
readonly zoom: number;
144144
}): LngLat {
145145
// Apply map bearing to the panning vector
146-
const rotatedPanDelta = panDelta.rotate(-tr.angle);
146+
const rotatedPanDelta = panDelta.rotate(tr.bearingInRadians);
147147
// Compute what the current zoom would be if the transform center would be moved to latitude 0.
148148
const normalizedGlobeZoom = tr.zoom + getZoomAdjustment(tr.center.lat, 0);
149149
// Note: we divide longitude speed by planet width at the given latitude. But we diminish this effect when the globe is zoomed out a lot.

src/geo/projection/mercator_camera_helper.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import Point from '@mapbox/point-geometry';
22
import {LngLat, LngLatLike} from '../lng_lat';
33
import {IReadonlyTransform, ITransform} from '../transform_interface';
4-
import {cameraBoundsWarning, CameraForBoxAndBearingHandlerResult, EaseToHandlerResult, EaseToHandlerOptions, FlyToHandlerResult, FlyToHandlerOptions, ICameraHelper, MapControlsDeltas} from './camera_helper';
4+
import {cameraBoundsWarning, CameraForBoxAndBearingHandlerResult, EaseToHandlerResult, EaseToHandlerOptions, FlyToHandlerResult, FlyToHandlerOptions, ICameraHelper, MapControlsDeltas, updateRotation} from './camera_helper';
55
import {CameraForBoundsOptions} from '../../ui/camera';
66
import {PaddingOptions} from '../edge_insets';
77
import {LngLatBounds} from '../lng_lat_bounds';
88
import {normalizeCenter, scaleZoom, zoomScale} from '../transform_helper';
9-
import {degreesToRadians} from '../../util/util';
9+
import {degreesToRadians, rollPitchBearingToQuat} from '../../util/util';
1010
import {projectToWorldCoordinates, unprojectFromWorldCoordinates} from './mercator_utils';
1111
import {interpolates} from '@maplibre/maplibre-gl-style-spec';
12+
import {quat} from 'gl-matrix';
1213

1314
/**
1415
* @internal
@@ -26,9 +27,10 @@ export class MercatorCameraHelper implements ICameraHelper {
2627
};
2728
}
2829

29-
handleMapControlsPitchBearingZoom(deltas: MapControlsDeltas, tr: ITransform): void {
30+
handleMapControlsRollPitchBearingZoom(deltas: MapControlsDeltas, tr: ITransform): void {
3031
if (deltas.bearingDelta) tr.setBearing(tr.bearing + deltas.bearingDelta);
3132
if (deltas.pitchDelta) tr.setPitch(tr.pitch + deltas.pitchDelta);
33+
if (deltas.rollDelta) tr.setRoll(tr.roll + deltas.rollDelta);
3234
if (deltas.zoomDelta) tr.setZoom(tr.zoom + deltas.zoomDelta);
3335
}
3436

@@ -119,9 +121,12 @@ export class MercatorCameraHelper implements ICameraHelper {
119121

120122
handleEaseTo(tr: ITransform, options: EaseToHandlerOptions): EaseToHandlerResult {
121123
const startZoom = tr.zoom;
122-
const startBearing = tr.bearing;
123-
const startPitch = tr.pitch;
124124
const startPadding = tr.padding;
125+
const startRotation = rollPitchBearingToQuat(tr.roll, tr.pitch, tr.bearing);
126+
const endRoll = options.roll === undefined ? tr.roll : options.roll;
127+
const endPitch = options.pitch === undefined ? tr.pitch : options.pitch;
128+
const endBearing = options.bearing === undefined ? tr.bearing : options.bearing;
129+
const endRotation = rollPitchBearingToQuat(endRoll, endPitch, endBearing);
125130

126131
const optionsZoom = typeof options.zoom !== 'undefined';
127132

@@ -149,11 +154,8 @@ export class MercatorCameraHelper implements ICameraHelper {
149154
if (isZooming) {
150155
tr.setZoom(interpolates.number(startZoom, endZoom, k));
151156
}
152-
if (startBearing !== options.bearing) {
153-
tr.setBearing(interpolates.number(startBearing, options.bearing, k));
154-
}
155-
if (startPitch !== options.pitch) {
156-
tr.setPitch(interpolates.number(startPitch, options.pitch, k));
157+
if (!quat.equals(startRotation, endRotation)) {
158+
updateRotation(startRotation, endRotation, {roll: endRoll, pitch: endPitch, bearing: endBearing}, tr, k);
157159
}
158160
if (doPadding) {
159161
tr.interpolatePadding(startPadding, options.padding, k);

src/geo/projection/mercator_transform.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ describe('transform', () => {
5050
0, 1, 0, 0,
5151
0, 0, 1, 0,
5252
0, 0, 0, 1], 6);
53-
expect([...transform.modelViewProjectionMatrix.values()]).toEqual([3, 0, 0, 0, 0, -2.954423259036624, -0.1780177690666898, -0.17364817766693033, 0, 0.006822967915294533, -0.013222891287479163, -0.012898324631281611, -786432, 774484.3308168967, 47414.91102496082, 46270.827886319785]);
53+
expect([...transform.modelViewProjectionMatrix.values()]).toEqual([3, 0, 0, 0, 0, -2.954423259036624, -0.1780177690666898, -0.17364817766693033, -0, 0.006822967915294533, -0.013222891287479163, -0.012898324631281611, -786432, 774484.3308168967, 47414.91102496082, 46270.827886319785]);
5454
expect(fixedLngLat(transform.screenPointToLocation(new Point(250, 250)))).toEqual({lng: 0, lat: 0});
5555
expect(fixedCoord(transform.screenPointToMercatorCoordinate(new Point(250, 250)))).toEqual({x: 0.5, y: 0.5, z: 0});
5656
expect(transform.locationToScreenPoint(new LngLat(0, 0))).toEqual({x: 250, y: 250});
@@ -83,6 +83,17 @@ describe('transform', () => {
8383
expect(fixedLngLat(transform.screenPointToLocation(new Point(15, 45)))).toEqual({lng: 13, lat: 10});
8484
});
8585

86+
test('setLocationAt tilted rolled', () => {
87+
const transform = new MercatorTransform(0, 22, 0, 60, true);
88+
transform.resize(500, 500);
89+
transform.setZoom(4);
90+
transform.setPitch(50);
91+
transform.setRoll(50);
92+
expect(transform.center).toEqual({lng: 0, lat: 0});
93+
transform.setLocationAtPoint(new LngLat(13, 10), new Point(15, 45));
94+
expect(fixedLngLat(transform.screenPointToLocation(new Point(15, 45)))).toEqual({lng: 13, lat: 10});
95+
});
96+
8697
test('has a default zoom', () => {
8798
const transform = new MercatorTransform(0, 22, 0, 60, true);
8899
transform.resize(500, 500);

0 commit comments

Comments
 (0)