3D maps, and their applications
Generate 3D maps from anywhere in the world … what is it for?
Well, besides being visually shocking, it can be useful in some fields like architecture, tracking applications and video games.
In fact that last one is the main reason of the module (addon) that I created in Godot 3.0.
How does it work
First I decided to use what MapBox makes available: satellite images and elevation maps.
The API is easy to use and you only need to create an account and get the token.
The process of generating the maps uses the heightmap to draw the 3D model, and a satellite image of the same area for the color of each polygon drawn.
Soon I plan to add texture and normals (which would allow to increase the level of detail, or reduce the number of polygons without losing quality), also if possible, automatic LOD
Elevation maps
Elevation maps use images whose elevation information is encoded in their colors:
Each color component (red, green and blue) corresponds to an amount (in meters). And that, according to the official documentation, is decoded with this formula:
var altitude = -10000 + ((r * 256 * 256 + g * 256 + b) * 0.1)
So it is noteworthy that the elevation maps are not a false coloration that indicates elevation.
For this reason, the shape of the object can not always be understood from the elevation image.
In my implementation each pixel corresponds to a quad, or 2 triangles that take as elevation the analyzed pixel and its contiguous pixels, in this way:
var bottomleft = Vector3 (i * dist - half_size, ht * altitude_multiplier, j * dist - half_size) var bl_color = ht[i][j]["color"] var upperleft = Vector3 (i * dist - half_size, ht * altitude_multiplier, (j + 1) * dist - half_size) var ul_color = bl_color.linear_interpolate (ht, 0.5) var upperright = Vector3 ((i + 1) * dist - half_size, ht * altitude_multiplier, (j + 1) * dist - half_size) var ur_color = bl_color.linear_interpolate (ht, 0.5) var bottomright = Vector3 ((i + 1) * dist - half_size, ht * altitude_multiplier, (j) * dist - half_size) var br_color = bl_color.linear_interpolate (ht, 0.5) surf_tool.add_color (bl_color) surf_tool.add_vertex (bottomleft) surf_tool.add_color (br_color) surf_tool.add_vertex (bottomright) surf_tool.add_color (ul_color) surf_tool.add_vertex (upperleft) surf_tool.add_color (br_color) surf_tool.add_vertex (bottomright) surf_tool.add_color (ur_color) surf_tool.add_vertex (upperright) surf_tool.add_color (ul_color) surf_tool.add_vertex (upperleft)
It is noteworthy that at the time of rendering the colors are not exactly the same as the texture, that due to the interplation of colors, aspect that I will improve in the next versions.
Satellite image (texture)
The satellite image, or texture, is used to give a color for each triangle drawn in 3D.
So vertex that is added takes the color of the corresponding pixel.
Get the data from MapBox
Another important element of this implementation is the service that MapBox makes available (truthfully, I searched through the data that NASA makes available, but I did not find a quick response, and I decided to go the easiest route, since I am familiar with the MapBox APIs).
By simply decoding the coordinates in the corresponding tile, the elevation and satellite images are obtained. I took advantage of this need (to decode latitude, longitude and zoom in the corresponding tile), to create a small library that allows me this and other decodings.
Final result and technical problems
Well, how is it always said, an image says more than a thousand words, so here you can see the final result.
It should be noted that due to unresolved problems, each image results in the rendering of 4 or up to 16 tiles, or mesh, smaller, which results in the misalignment, in certain cases, of the adjacent tiles, as can be seen in the animation.