-
-
Notifications
You must be signed in to change notification settings - Fork 789
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 image rendered partially on terrain #5598
base: main
Are you sure you want to change the base?
Fix image rendered partially on terrain #5598
Conversation
…o issue-1559-image-rendered-partially-on-terrain
…o issue-1559-image-rendered-partially-on-terrain
@@ -8,6 +8,13 @@ import {type ICanonicalTileID, type IMercatorCoordinate} from '@maplibre/maplibr | |||
import {MAX_TILE_ZOOM, MIN_TILE_ZOOM} from '../util/util'; | |||
import {isInBoundsForTileZoomXY} from '../util/world_bounds'; | |||
|
|||
export type CanonicalTileRange = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a bbox type, what's the difference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Values there reference tile X and Y number, while bbox I could find in the repo were abould LngLat. Unless I missed some other type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a geojson.bbox type that is simply an array of 4 numbers, but it might not be a great fit here, IDK...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I missed that.
Hmm... I still think separate type here is a better fit. GeoJSON BBox implies that it contains geographic coordinates - longitude and latitude, while here we store canonical tile numbers. Also having values in an array is a bit less robust, that having them explicitly named.
Let me know if this rationale sounds good for you.
* This object is used to store the range of terrain tiles that overlap with this tile. | ||
* It is relevant for image tiles, as the image exceeds single tile boundaries. | ||
*/ | ||
terrainTileRanges: {[zoom: string]: CanonicalTileRange}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels a bit odd to me as this is not a "regular" property of a single tile, can this be stored somewhere else perhaps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it was difficult to find such logical place. I chose OverscaledTileID
for following reasons:
- it already contains specific information for terrain tile, it seems logical to me to keep them in the same place
- TileID-kind type seems valid for such information, as it describes placement of the tile. It is not about the data as an example.
- This is the type we provide to
TerrainSourceCache.getTerrainCoords
inRenderToTexture.prepareForRender
method - which seems logical, and we don't have to change that.
this.terrain.sourceCache.freeRtt(e.tile.tileID); | ||
|
||
const source = this.style.getSource(e.sourceId); | ||
if (source?.type === 'image') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to move this logic so that map doesn't need to do something special for the case of image source?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tbh this entire fragment of code (_terrainDataCallback
) seems a bit special - I will take a closer look on that, I would try to move it somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't able to find better placement for this logic.
We have to clear all terrain tiles for image source because we don't know which terrain tiles were affected, for two reasons:
- image can exceed its tile (however we can use new range object introduced in this PR),
- image could be moved from one tile to another, but we only get information about new tile.
I don't see the way to fix that without some more major refactoring.
What I tried:
- add
hasCustomTerrainRange
method toOverscaledTileID
, then we can ready from tileId inTerrainSourceCache.freeRtt
that this tile is in fact an image tile - but it is very implicit, the logic won't be clear in my opinion - pass information about the source to
freeRtt
but it is also bad, asfreeRtt
method probably also should not be aware of source
This place seems the best, as it contains already logic that decides when to clear terrain tiles based on event-related circumstances - eg. when style changes, clear all.
Fixes issue #1559 - image was rendered partially on terrain.
Description of the cause.
Image is always in always assigned to one tile, but the content could exceed that tile. This approach doesn't work for terrain. Content of each terrain tile is rendered separately, and for each terrain tile MapLibre renders only overlapping tiles (children, parents and same tile). This is why sometimes image is not rendered - because it is on the tile that does not belong to some terrain tile.
As the solution I added optional information to the OverscaledTileID what tiles on various zoom levels are overlapping with this tile. This way while computing tiles to render for each terrain tile, we are able to render image tile as well, even if canonical tile itself are not overlapping (but the content is).
For fixing animated image it was neccesary to clear all terrain tiles textures (changes in
src/ui/map.ts
).I also found another way to fix this problem - however I'm not sure if it is doable that way. As the image is applied to single tile, we could do it to tile 0/0/0. However, this creates issues with unsufficient precision of transformation matrix, also there is another issue with terrain tiles, which I didn't figure out wih that approach.
Before:

After:

For testing you can use scripts provided in issue thread:
Launch Checklist
CHANGELOG.md
under the## main
section.