Visualize OpenStreetMap data in 3D on the fly with Unity3D
Background

Some time ago, due to the availability of free time, I thought about using cards to solve any interesting and non-standard problems. One of the ideas that interested me was the idea of using maps for rendering the world in a game engine with the possibility of interactive interaction: the destruction of the McDonald's in the chosen city, the local apocalypse from neighbors in the garden, and the like, are nice, but only in the case of a virtual world, little things.
However, despite the primitiveness of the idea, no ready-made solutions were found for the conditions formulated by me:
- Open source
- Real time rendering of the world in the game engine
- Support for major platforms (mobile, web, desktop)
- Preferably C # as the main development language
Of course, the idea of rendering maps in 3D is absolutely not new and there are ready-made solutions both with open source and proprietary ones (in no case do I pretend to be a complete list):
Typically, such solutions use OpenStreetMap data to render the world in 3D, as This feature is in the cards and is actively developing . Also, a huge plus of OSM is the ability to download a complete dump of data from the entire planet or from a specific part / city (for example, geofabrik or metro-extracts ), moreover, without strict license restrictions.
Actionstreetmap
Thus, it was decided to start developing your project from scratch under the name ActionStreetMap, which, in theory, should remind of the nature of the source data and the way they are used. Unity3d was chosen as the game engine, which is absolutely not surprising due to the last condition (C # development language) and the developed community, since this is my first experience in the field of game development.

The project started more than a year ago and is in an active stage of development, even though I am still the only developer. The following are the main features that are currently implemented:
- Flat shading style
- Rendering of the main OSM objects (buildings, roads, fences, trees, rivers, parks, POI ...)
- Using SRTM data to create elevation maps
- Autoload maps from OSM server and SRTM data from NASA server
- Offline maps (supports import from the main OSM data formats - pbf, xml, o5m)
- Primitive offline search support
- Modification support for some objects (experimental feature)
- Asynchronous loading of everything and everything (using Reactive Extensions)
- Customization option
I would like to dwell on the first and last points in more detail, despite the fact that I do not set a goal to describe the internal structure of the project in this article.
Flat shading
After experimenting with building textures and unity terrain, it was decided to abandon the attempt to render a “plausible” city. The reasons are trivial:
- Lack of real data on building facades and other objects (the Khrushchev texture on the facade of the Reichstag looks funny at first, but over time it starts to strain ..)
- Performance
As a result, the approach with triangles was chosen, although the opportunity to render something of their own in a different style is still present.
Customization
When I became acquainted with OSM maps, I was interested in the idea of using CSS of a similar language to describe which objects should be rendered and how. As a result, a similar approach with some features was used in ASM. For example, buildings are partially defined by the following rules:
area[building] { builder: building; height:12; min_height: 0; levels: 5; fill-color:gradient(#c0c0c0, #a9a9a9 50%, #808080); facade-builder:empty; material:Materials/Buildings/Building; }
area[building:levels] { height: eval(num(tag('building:levels')) * num(3.2)); }
area[min_height] { min_height: eval(num(tag('min_height'))); }
area[building:height] { height: eval(num(tag('building:height'))); }
area[building:height][roof:height] { height: eval(num(tag('building:height')) - num(tag('roof:height'))); }
area[building:cladding=brick] { fill-color:gradient(#0fff96, #0cc775 50%, #066139); }
area[roof:material=brick] { roof-color:gradient(#0fff96, #0cc775 50%, #066139); }
This approach removed the rule parsing logic from C # classes, and in combination with the Composition Root and Dependency Injection patterns used in the project greatly simplified the task of customizing the rendering of OSM objects and added the ability to create “themes” (for example, winter, summer theme, etc. .), which can be changed without recompiling the source code.
Source code
At the moment, the source code for the demo project is available in Unity Editor, as well as web build with a small part of the map of Moscow.
The framework itself is not yet on github, but with the unity of the community interested in its development, it can be published.