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

Flat Map World Origin is Offset at Lower Zoom Levels #208

Closed
thefoofighter opened this issue Aug 14, 2017 · 11 comments
Closed

Flat Map World Origin is Offset at Lower Zoom Levels #208

thefoofighter opened this issue Aug 14, 2017 · 11 comments

Comments

@thefoofighter
Copy link

thefoofighter commented Aug 14, 2017

Hi,

Perhaps I am doing something really wrong or my understanding of Flat Terrain Maps and how they work in Unity is incorrect.

I am working from the Develop branch which at the moment is pretty much rel v1.10

What I have in my Scene are two Flat Terrain Map Visualizers which I basically took from the Map Generation Basics Example. I have given them separate but identical factories that just render the Dark map data.
They are both located at 0,0,0 with one on top of the other, Both are loaded at the same time.

The only difference between each map renderer is their Zoom Level, One is set to 3 and the other is set to 6.
The coordinates I am using are 37.7648, -122.463 for San Francisco.

The Abstract Maps Unity Tile size is 100
I am using a Range Tile Provider with all parameters set to 2.

The Red Dot below represents Unity 0,0,0 transform

Zoom Level 3 Looks like this:

image

Zoom Level 6 Looks like this:

image

Zoom Level 12 gets even closer:

image

You can see that the Lower Zoom levels are way way off San Francisco while the higher Levels get closer, I imagine Level 20/22 is right on top of my input 37.7648, -122.463

My question is, Why are the lower levels centering the tiles so far from the input coordinates?
I was assuming that my input coordinates would translate to Unity 0,0,0 irregardless of level

Is this precision related?
Is there another step I should take to keep the map data centered on my input which should get centered to unity 0,0,0?

What I need to do is "zoom" between different Map ZoomLevels with a unity camera somewhat like a custom LOD system but if the coordinates between ZoomLevels are offset like this my zoom will not function as desired.

Zoom Level 3 from Editor View showing the Grid:

image

Thank you,
Cathal

@NinjaDanz3r
Copy link

NinjaDanz3r commented Aug 15, 2017

IIRC, when you request a tile using lat/lon the Mapbox SDK will provide you a tile which contains your coordinate, not a tile centered on your coordinate.
Thus as you go up in levels tiles will encompass a larger area in which your requested coordinate will be located (and as such it will be farther away from the center of the tile).

I think you can use the functions in the conversions namespace to translate the world in order to center your location

@david-rhodes
Copy link

Spot on @NinjaDanz3r! Thank you.

@thefoofighter Yes, you will need to find the offset between your desired location and the tile's center. An example might look something like this:

_root.localPosition = -Conversions.GeoToWorldPosition(_mapCenterLatitudeLongitude.x, _mapCenterLatitudeLongitude.y, _mapCenterMercator, _worldRelativeScale).ToVector3xz();

Though, looking at the code, it's a bit misleading that we've called it _mapCenterLatitudeLongitude. That's actually the map's original request and source of the center tile.

@thefoofighter
Copy link
Author

thefoofighter commented Aug 16, 2017

Hi @NinjaDanz3r & @david-rhodes

Thank you for pointing me in the right direction, I have it working now.

Can I ask if there is a reason when requesting a Tile via lat/lon that the returned tile doesn't center on your requested co-ordinates?

Is it perhaps a limitation or can I modify the request to return raster data centering on a tile or centered to an array of tiles?

Thanks again for the support!

@david-rhodes
Copy link

@thefoofighter I'm not sure I follow. You have it working, but you want to modify the request?

This isn't a limitation, but a specific implementation detail that we leave up to developers. For example, some developers may want to move the map to center, some may move the camera, and others may not wish to do either. If you want a map covering a specific geographic bounding box, you can do so with TileCover.Get().

Maybe you can elaborate on your use-case?

@thefoofighter
Copy link
Author

thefoofighter commented Aug 16, 2017

@david-rhodes

Apologies, I did not mean to confuse you. What i got working was what you suggested above which moves the root location of all the 3D Tiles so that my Lat/Lon input is at Unity 0,0,0 which is great and might even be able to work with that.

What i was hoping to achieve was not to offset or move the 3d tiles in unity but rather to request raster data that is already offset where my input lon/lat is at Unity 0,0,0.

I will try to explain ^^
Red sphere represents Unity 0,0,0

Consider the Range Tile provider with
North = 2
East = 2
West = 2
South = 2

this gives me a 5*5 Grid array of Unity Tiles something like this:
image

So My Center tile contains raster data which includes my lon/lat target (Sáo Paulo) but Sao Paulo itself is at the bottom of this middle tile:
image

With your suggested change the 3d tiles move to place Sao Paulo at the center of the Unity World.
image

I want my 3D tiles to stay where they spawn and for the raster data to render Sao Paulo at the Dead center of my middle tile.
centeredonlatlong

If this functioned and I have a Grid of 4*4 tiles Sao Paulo would be at the center junction/cross between the 4 Center tiles

Basically what I am trying to do is hack together a system where the camera looks directly down on a map and I fade between zoom levels. So to have my location centered at all times would save me hacking my camera to follow 3d worldspace offsets.

Does this help explain it at all?

Thank you

@brnkhy
Copy link
Contributor

brnkhy commented Aug 16, 2017

@thefoofighter I think there's no easy way to achieve that and handling camera movement would be much easier. The problem is, our api doesn't serve the image you have in that last pic for example, Sao Paulo in the middle.
Another option here would be moving whole map, in case you have some complex camera logic there.
I don't know much about your application of course but you have Sao Paulo position, can't you recalculate it on every zoom level change and simply make camera a child of that red sphere?

@thefoofighter
Copy link
Author

@brnkhy Hi, I figured that it might be a difficult issue. Nothing complex is going on with the camera and I was also going to go the route you just mentioned as a backup. I was just wondering if centering the raster data would be possible somehow :)

How i imagined how this worked is that Mapbox stores some kind of giant image of the worlds atlas and when the mapbox sdk makes a request for a tile that the api uses the given co-ordinates as an anchor to snip 512px squares around that anchor.. Are the Tiles for each zoom level pre-rendered and served when requested?

I was also thinking ahead to a potential usecase I may have of keeping the 3d tiles static and scrolling the raster data on the tiles (after messing with UV's and such) or one big tile, that way i can keep the camera center and move the world around 0,0,0 which for navigation would be useful if the avatar/user was also at 0,0,0

This would be possible like you mentioned with some parenting and updating of offsets albeit a little hacky :P

Thank you for clarifying,

@brnkhy
Copy link
Contributor

brnkhy commented Aug 16, 2017

@thefoofighter
Are the Tiles for each zoom level pre-rendered and served when requested?
exactly, it's same for height and vector data as well. And its using TMS (tile map service). You can check this page showing both google maps and tms systems, it shows the structure quite well I think; http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/

keeping the 3d tiles static and scrolling the raster data on the tiles
you mean by moving UV coordinates instead of the objects? I'm afraid that won't work either because you'll have 9 small textures instead of one huge one in your case and each tile will repeat individually
when you move uvs.

@thefoofighter
Copy link
Author

@brnkhy
That makes more sense Thank you.

As for modifying/shifting the UV coordinates I was thinking of also using a custom shader along with a control script to avoid the repeating issue with 3-4 extra texture inputs depending on what direction a user is scrolling but that is overkill, messy and even a headache to think about tracking those inputs for each tile ^^ I'll just stick with the easier option :)

That pretty much wraps up this query/non-issue

Thank you all for your support :)
Much appreciated!

I really love what you all are creating here at Mapbox for Unity especially your use of modular factories and styles. Its really impressive! Keep the updates coming :)

@david-rhodes
Copy link

@thefoofighter You could potentially generate an atlas at runtime from your fetched textures: https://docs.unity3d.com/ScriptReference/Texture2D.GenerateAtlas.html.

@thefoofighter
Copy link
Author

@david-rhodes I fear that running this at runtime and then applying it to a big quad or something will be too slow for my needs but I have yet to test it,

I actually have tried this with your awesome new globe sample just to have a neat 8k atlas of earth but Texture2D.GenerateAtlas seems to start to write the input array images into the big atlas from the lower left hand corner while Mapbox's globe tiles start in the upper left hand corner,

In hindsight guess I could have rearranged the array of Texture2Ds and then called GenerateAtlas but i opted for a custom loop in conjunction with setPixels & getPixels

Thanks again :)

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

No branches or pull requests

4 participants