Cryptovoxels is my virtual world that runs on the Ethereum blockchain. Part of making the world explorable and discoverable, was to create a good quality map, so that people could see where their parcel was and who their neighbours are. The best neighbourhoods are ones where the neighbours are doing high quality builds.
So, to build out this top-down map, I used a few tools:
- Mapnik
- PostGIS
- Leaflet
- Chrome headless
Mapnik
Mapnik is a fantastic mapping library that takes an XML description of your map (with styles and data sources specified using an easy XML markup) and turns those maps into tiles. I use the node.js version of mapnik, and a little map server that I rolled myself to serve the tiles. I have nginx in front of mapnik to cache the tiles. One problem I found is that with all the raster tiles that make up the preview of the world, the map server was running quite slow on a 1gb Digital Ocean droplet. Bumping that server up to 2gb and the map server runs nice and fast again.
PostGIS
I’ve used PostGIS as part of Cryptovoxels from early on. The streets and parcels are all generated on a WGS84 map, with 100 metres to a degree of latitude (this is why the world is limited to 36km x 18km. PostGIS adds geometry columns to your database, so I can specify the borders of the parcels, and the coordinates of the streets. Mapnik has PostGIS support built in, so you can query the database for visible streets and render them.
Leaflet
We use leaflet to take the map tiles and display them in a slippy map that works well on mobile or desktop. With a little bit of css (filter: greyscale()) we can make it black and white to match the cryptovoxels theme. Currently we’re not using many of the Leaflet features (like polylines or fancier interactions), but later on it’d be great to be able to show groups of parcels, or tours or various points of interest. Imagine a tour of the art galleries in Cryptovoxels, with a polyline giving you turn by turn directions.
Chrome Headless
Pretty quickly after we started generating tiles with just streets and parcel boundaries, it was obvious we wanted to be able to actually see what was in the world. So after a quick bit of playing around with chrome headless, we could get the web client rendering top down tiles. We then iterate over all the parcels in the world, take a 512x512px screenshot of them, and then add them to the map as a raster layer. It takes around 20 minutes to regenerate top down preview tiles of the entire world, then we restart the map server to pick upt he changes, and you can see what everyone is building.
Making the map tiles top down, but slightly skewed, in an orthographic projection was a tricky problem. We initially started by rotating an orthographic camera, but in the end we had to do some tricky matrix maths (with help from Nick at indigorenderer.com, but we got images that tile almost perfectly.
There is a problem that tall parcels will sometimes be sectioned, because the camera isn’t far enough from the ground, we’ll hopefully get that bug sorted out with time.