Arranging Mountains
2022-05-09
Some nights when I can’t get to sleep, I think about hard problems until I fall asleep. Last night I thought about what would be the way to arrange the mountains in a way that would look aesthetically pleasing but also algorithmically so it also isn’t manual.
There’s enough manual things I’m doing already with collecting the data that I want the rest of it to be algorithmic as much as possible.
I went and tried to play around with Observable. I’m a heavy user of d3, and think Observable is probably the best designed data-vis platform around, built by the creator of d3. I used it to prototype my initial rendering of the Japan outline so here I’m going to try use it to play with different layout algorithms.
The first thing though was just to get the data to load, so I built up a way to just draw the rectangles that represent the size of the resort. I draw out all the rectangles manually on my “data input days”, so it’s nice to see them all in one map, like a ski resort constellation.
It’s such a thing of beauty to see it all working. However, I encountered a weird bug and resulting knowledge.
All the bounding boxes for the ski resorts are drawn by hand myself. I have been steadily using an open source GeoJSON editor to allow me to draw shapes on a map that I then export into GeoJSON, stored in a database (Firestore). For this visualization, I exported all that data into a single GeoJSON file and loaded it in. Once loaded, I used d3-geo to map the lat lons to screen coordinates, output an SVG path and the label of the resort area on the map.
However, when I first did this, there were a few issues, one was that some areas would render as huge world size rectangles and second, some of the areas, the centroid could not be found using the regular path.centroid()
methods. I was stumped as to why.
After a good night’s sleep, I imagined that maybe the Polygon vertices had directionality (aka winding rule). Since I had seen that you can define a hole that could be cut out of a polygon, I imagined that the polygons follow some sort of winding rule. And indeed, that was the reason, Since I had haphazardly draw these bounding box manually, sometimes I would draw the bounding box clockwise, sometimes anti-clockwise, and so all the anti-clockwise ones ended up being negative-space polygons causing d3-geo to get confused by them.
I used turfjs to convert the polygon into a LineString, detect whether it the clockwise-ness booleanClockwise
and then reverse the order of the points if it was. That fixed the problem for me. And so now I have a beautiful collection of bounding boxes.
2022-05-14
Fixed some fallout from my refactoring from a few days where I made the mountain rendering code work across a few different projects. Using Vue has been great to be able to share the same general renderer across different views. However, there is the part where I want to render all the mountains in a single WebGL instance which means I can’t share the Vue component, but have to share the internals.
I had been looking at react-three-fiber and also trios (Vue equivalent) and I really like the declarative way to construct a scene and possibly allow for reuse. I am tempted to rewrite all my rendering code to take advantage of that model, but I’m not sure if I’ll regret it. Maybe I’ll leave that for later.
I fixed the minor issues I had after my refactoring to get my multi-mountain renderer working again — this time, instead of rendering just a few mountains, its rendering 300 mountains which makes it really slow. The whole render took 11 minutes to do, without any of the trees and lift lines! This is a proof of concept render to see if I could render that many mountains in the scene. I had to make a few adjustments like expanding the clipping plane.
A few things are missing still, obviously the models that sit on top of the mountains, and also the texture maps I want to put on the top. I’m expecting that adding those will increase the render time more. I want to add back the shadows by adding a light per mountain, or maybe just faking the shadows using ambient occulsion. I’d like to figure out a way to draw a perspective label on each mountain.
The final piece which I’m using Observable to do, is to develop an algorithm to place each mountain in the scene. Right now the mountains are all in a grid which already looks nice, but I want to make it a little more packed, more space around the big mountain like Shiga Kogen and less space between the tiny mountains.
2022-05-15
I managed to write a pretty rudimentry box packing algorithm that laid boxes out from the top and pushing boxes up into the gaps where it would fit. The algorithm works ok but a little bit of randomness is needed to minimize the gap. Maybe I can run a regression over it.
The result is in Observable as a prototype which I’ll move the implementation into my codebase to run for the 3D map.
2022-05-17
I want to try making the rectangular mountain areas to be circular. So I’ve started doing some work to calculate the geometry. My initial problem to solve is to work out the arc equation. First off, trying to find where the circular area will intersect with the edge of the map tiles so that I can figure out how they clip. I suspect it will be a full week of maths for me.
A weird thing happened in the last few days where I couldn’t push my debugging console that is on Firebase. The few times I tried to push, my internet would stop working. It turns out firebase hosting doesn’t like it when I tried to deploy something like 1000 PNG files. So instead, I moved all the textures and maps on to cloudstorage instead of deploy with the firebase hosting.