Thursday, March 24, 2016

Planets

Creating a square section of artificial terrain was just a warm-up!
Today, I'd like to show you what happens if we apply the same logic to a sphere.

First of all, our input height matrix will have different dimensions. In case of the square, it was just a 2x2 matrix. A "minimal" sphere can be defined by eight vertices: two poles and two circles with three vertices each, as such:


The interpolation logic remains the same, except for a few details: when interpolating between a pole and a circle, a new minimal (three vertices) circle will be created. For example, if we had to run one iteration on the minimal sphere, we would start by interpolating new heights for the existing two circles then we would interpolate new circles between the the existing circles and the poles. Here's a visual explanation:


Contrary to what happened with the square section, not every row in the "matrix" has the same length. It means that, sometimes, new rows have to be interpolated from two rows of different length: for example between a pole and a circle. In this case, not all vertices are used to interpolate a new row but that's OK because the height information contained in these vertices is indirectly present in the used vertices through previous interpolations.

Let's see how a planet would look like after a few more iterations:


You can notice that the terrain looks quite detailed and realistic around the equator but, near the poles, it looks smeared, giving the planet a cotton candy look. This is due to the way our algorithm functions. Because heights are interpolated inside each circle and between circles, height information propagates mostly in two directions: longitudinally and latitudinally, but that's not the issue.

The problem is anisotropy, in other words, uneven resolution. If we counted the number of vertices on each circle and divided it by the circle's length for this particular example, we would find out that it varies between roughly 0.3 and 0.7. This longitudinal resolution tends to be higher around the equator and lower near the poles. What's more, the latitudinal resolution at the prime meridian is even higher and equals around 1.2. To solve this problem, we could increase longitudinal resolution to match the latitudinal one as it's the maximum. This can be simply accomplished by interpolating heights for circles that have insufficient resolution.

Let's see how the planet looks like after adding the densification step at the end of each iteration:


Much better! The total number of triangles tripled, but the resolution is very even which adds a lot of realism to the planet. Of course it's not completely uniform because sometimes the number of vertices is doubles for two consecutive circles but that's just a drawback of using this algorithm.

Finally, I'd like to show you a couple of worlds generated with more realistic height maps:




In case you didn't notice, these two planets are supposed to look like Earth and Venus.

Remember, none of this uses any textures, only colors. Imagine how amazing these models could have looked like if we used textures instead! But for now, I have other priorities.

By the way, 10 iterations and 100 million triangles is a lot. With the current structure of my algorithm, I cannot go beyond that without running out of memory. I'm not an expert but I'm sure there are many ways to improve that. However, it is not my focus right now.

The rendering uses about 5 GB of memory and the computation takes only 7 minutes on a modern computer. The FPS drops to about 18. Naturally, if I was looking at the planet from the point of view of a person standing on its surface, I would only need to render a fraction of all the triangles and I could further improve performance by using levels of detail (LODs).

Anyway, that's all for now.

Saturday, March 19, 2016

First steps

Creating artificial terrain that looks "pretty good" isn't actually that hard. However, achieving a "realistic" look demands a lot more effort. Today, I'll show you how to do "pretty good"...

Let's say there's a rectangle with height values associated to each of its corners. If we divide this rectangle into 4 identical rectangles, we can see that there are now 5 new vertices (points) for which we could calculate height values.

Now we have to figure out a rule that interpolates (calculates) a new height value from the existing ones.

I decided to go with height variability variable and a constant "roughness" factor that divides height variability at every iteration. New heights are first interpolated for each row, then new rows are interpolated between existing rows.

We could imagine many different ways to interpolate heights but, for the sake of simplicity, ill stick to this one.

All that is left to do is to render the result using a game engine. I used the "Panda3D" engine, which has a Python/C++ API.

Here are three examples using a uniform probability law, for the same random seed, with an initial height variability of 10 and different values of roughness:




Roughness = 1.5 seems to yield the best looking terrain but this method has a problem: the height gradient is too uniform, in other words, you will never find a mountain right next to a valley. To fix this, I introduced more randomness to the height interpolation process. When a new height is interpolated, a mean height value used by probability laws is calculated from the two input heights, which basically means that each height is multiplied by a "weight" of 0,5.

What if that weight was a random number instead?


I was lucky enough to get a nice valley with a tall cliff on the right side, which illustrates my point.

Assigning a random weight was a small manipulation that improved the result, but there is still a lot to do we want our terrain to look believable. We could imagine generating several of such terrain sections with different parameters (to make them look like mountains/hills/plains), then sticking them together. In this case, the heights along the rim of a section would serve as a boundary condition for the adjacent section.

I will leave you with an image of the same terrain with an earth-like color map:


Next time: Planets!

Introduction

Hello!
Programming is my passion and I'd like to share it with you by showing you some of my projects.

The universe is filled with an unimaginable number of planets, yet the only ones we've seen so far are those inside our solar system. We've learned a lot by studying them but they're only a glimpse of the diversity that lies beyond. Chances are that any planet we can imagine exists somewhere in the universe.

To satisfy my curiosity I decided to start working on a project that involves artificial terrain generation on a planetary scale. My goal is to create a procedurally generated fractal planet and then improve it by adding physical processes, such as erosion and plate tectonics.
The idea in fractal generation is that complexity is achieved by applying a simple operation onto an object then iterating by doing the same with the obtained sub-objects. By the same principle, I hope to create a realistic world through the superposition of procedural generation and simple physical models.

My biggest inspiration was a  documentary about fractals called "Hunting the Hidden Dimension"
that I've seen a few years ago so I encourage you to check it out!