Monday, July 11, 2016

Geometry is Destiny Part 2

This is a continuation of an earlier post. That post ended in a literal, virtual cliffhanger. We generated continent shapes and we used tectonic plate simulation to compute where mountain ranges would appear.

The remaining step was to assign biomes. We wanted biome placement to be believable so we did a bit of research on what biomes are where and why they appear.

Scientists have distilled this to a very convenient set of rules, which are captured by the following chart:


I stole this particular image from Mugan's Biology Page, but you will find it pretty much everywhere occurrence of biomes on Earth is discussed. This is a classification made by Robert Whittaker based on annual precipitation and average temperate. His study suggests temperature and humidity are enough to determine biome occurrence.

This made it simple for us. We only needed to compute two parameters across the continent: temperature and humidity.

Let's start with the easiest, which is temperature. We figured out some of this would have to be user input. as we did not know the latitude for the continent we would not be able to determine how cold or hot it was. Instead of asking how much sun the landmass was getting (which is what latitude means in this case), we chose to ask temperature values for each corner of the map:


To get the temperature for any position within the map we just do a linear interpolation from these four corner values.

Temperature also changes with elevation. This ranges from -6 to -10 degrees Celcius for each extra kilometer in altitude. We had a rough elevation map from the tectonic plate simulation, with this additional piece we are able to compute a fairly good temperature value for any point on the map. This is the horizontal axis of the Whittaker chart.

The vertical axis is rainfall or humidity percentage as other biome charts have it. This one is trickier. In real life, water evaporates from large water masses like the sea into clouds. Air rises when it meets higher elevation. There it cools down losing some of its ability to hold water. The water excess becomes rainfall.

We chose to simulate exactly that process. We knew the continent would be surrounded by ocean water. This would be the main source of water. The next step would be to determine wind direction. Continents are exposed to different wind systems depending on where they are on the planet. Global wind simulation was out of scope for us, so we chose again to ask the user:


The input is quite simple, just a wind direction for each map of the corner. With this, we would be able to produce a wind vector field for the entire map.

If you remember the previous post, a key aspect of this simulation framework was the use of a mesh instead of a regular 2D grid:


This came handy for simulating water transfer. Each node is seeded with an initial amount of water. Nodes over the ocean would get 100% and nodes over the landmass would get zero.

Then we perform multiple simulation steps. Each step looks at each pair of connected nodes and figures out how much water moved from one node to the next and how much was lost as precipitation.

Assume two connected nodes, A and B. The dot product between the wind vector at A, and the vector that goes from A to B will tell us how able the wind is to carry water from A to B. Then based on the water already contained in A and B, and the temperature changes, we can compute how much water moved and how much rainfall there is.

After sufficient simulation steps to cover the node graph, the following pattern emerges:


Here the wind comes from the south. The grayscale shows humidity. The red areas show where the mountains are. As you can see most of the moisture carried by the wind precipitates right after entering the continent, leaving most of the land behind very dry.

If we switch wind direction to the north, a very different pattern emerges:


Once both temperature and humidity are known, assigning biomes is trivial. You can think of the Whittaker chart as a 2D matrix. Humidity determines which row you would use and temperature the column:


This could be generalized to other biome types by providing a different matrix, but I have not paid too much attention to other-worldly biome systems. I have not found any good examples of biome attribution beyond temperature and humidity.

Once you know the biome for each node in the mesh, obtaining a 2D map is a matter of drawing each triangle in the mesh to a bitmap. We had a software rasterizer for occlusion culling that came pretty handy here.

I leave you with a few examples of what happens when you play with wind directions and base temperatures:


13 comments:

  1. Replies
    1. Your biome system looks really promising!

      I am impressed that you came up with the idea to use the wind directions, annual precipitation and average temperature as parameters.

      There was one blogpost
      ( http://procworld.blogspot.de/2013/10/water-bodies.html )
      were you showed of the generation of water bodies and water-sources to create rivers flowing down the hills.

      Are you still working on that system or do you already thought about a new way to generate realistic rivers and lakes?

      Offtopic: Are you still gonna make a minecraft clone ;) (or at least another game?)

      Delete
    2. Using precipitation and temperature is not my idea. I encountered this concept in Amit's blog for the first time: http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/#biomes

      The lake system goes on top of this. The output of this stage is very coarse, each pixel may cover 10 kilometers. Lakes and rivers operate at a much higher resolution, at the next octave if you will.

      There is so much to do in the platform we have put all plans for a game on hold.

      Delete
  2. So, the wind is decided for each corner separately? So you could have wind coming in from all sides?

    Also, this looks really really interesting, It'll definitely be fun to play around with, and worldbuilders (even just the hobbyists) might find this very useful!

    ReplyDelete
    Replies
    1. Yes you could have wind blowing from each corner into the center of the continent. You would have a point where wind velocity is zero. Apparently it is the same on planet Earth.

      Beyond game and virtual worlds in general, I like this as a toy. It is fun for me to explore the places it is creating. There are many layers of content we need to put in place yet, but I think this is a good foundation.

      Delete
  3. That's what first drew me to this blog, just seeing how far you can go with procedurally creating worlds =).

    Speaking of which, would the procedural nation/city stuff you created ages ago still work on the current system?

    ReplyDelete
    Replies
    1. The nation -> province -> city -> building lot generation would go on top of this. We are getting closer :)

      Delete
    2. Can't wait to see it all work together =D.
      You guys are getting really close to making an entire abandoned continent, aren't you? =P.

      Delete
    3. Getting close, yes. Something interesting about these mesh-based methods is they apply to other configurations than just planes. Most of this would work over a sphere with no modification required, giving you planets.

      Delete
  4. Thanks for the great article! How do you determine the amount of condensed precipitation? Is it dependent on altitude, temperature or both?

    ReplyDelete
    Replies
    1. In real life it depends on temperature and pressure, but we assume pressure to be constant so it is temperature only.

      But then temperature depends on altitude, so while you won't find any references to altitude in the condensation formula, somehow its effects are baked in there.

      Delete
  5. in real life, wind systems sometimes shift seasonally, or have a certain amount of variability in direction. Could your system handle this (maybe run two or three times with different wind directions and take the average?)

    ReplyDelete
    Replies
    1. Yes, it would be a minor modification.

      You can still use the average wind direction as input for a single simulation run. I wonder if the results are noticeably different. Any thoughts?

      Delete