Optimizing optimizations

Last week I mention that my next goal with Crimild was to tackle several issues regarding the Terrain Library. And that’s what I’m doing. The goal that I’m trying to accomplish with this code review is to ensure not only a cleaner and more developer-friendly API for terrains, but also to improve some optimization that were implemented in the past but never actually completed. But before discussing about the optimization details let me explain how the Terrain library is composed of:

HeightMap

As its name suggests, the HeightMap class store the elevation information that is later used to build the landscape. But since elevation data might come in different forms, the HeightMap class only declares a common interface for all the actual implementations. As I’m writing this post the library already suports elevation data in the form of raw data files, image files (with support for both 8-bit and 24-bit images) and even a procedural heightmap generated through the use of fractal calculations.

TerrainNode

This class is one of the two terrain implementations available in Crimild. In particular, this is the brute force approach. It just read through all the information contained in the heightmap and creates the entire landscape with the maximum level of detail. Although there is no mesh optimization, this class does provide a couple of tricks in order to speed up rendering. The terrain is divided into several patches and group them in order to create a node hierarchy, allowing for fast culling. For those of you wandering, a patch is just a geometry node that contains only the graphical data for the particular portion of the terrain it represents.

The following picture shows the TerrainNode class in action

The TerrainNode class in action

The TerrainNode class in action

Maximum detail for every patch, even when they are too far away to notice it

Notice that all patches have the same amount of detail regarding their actual position relative to the camera view point.

CLODTerrainNode

In contrast with TerrainNode, the CLODTerrainNode class does provide a mesh optimization in order to reduce the amount of vertex information sent to the graphics card. The algorithm I’m using is based on Geomipmapping (see references) and ensures that the level of detail for a given patch increases as the camera moves closer to it. A LOD value is assigned to each patch based on the viewer’s distance and the patch is tessellated whenever that value changes. The amount of patches that are tessellated between each frame depends on the subdivision policy and the camera movement, but during my testings it was always below ten.

Here’s an example of the the CLODTerrainNode works.

Minimum level of detail (the camera is too far away)

As the camera gets closer...

... some patches gets more detail

As the camera moves closer to the terrain, the patches at the bottom of the screen gain more detail.

Cracks will appear on the borders between patches with different level of details. In this iteration I’m using vertical skirts along the patch border to prevent those holes in the terrain. Instead of avoiding the formation of cracks in the surface, the skirt just fill the blanks.

The results

I still need to perform further tests, but the results so far are optimistic in both performance and memory requirements. Improving the terrain library is imperative for the iPhone extensions due to the hardware limitations. I’m going to freeze any further change in the optimization algorithms in order to make some progress in the remaining subjects. The next step is to provide some lighting for our landscapes as well as improving the texture generator.

Revisiting the Terrain Library

It’s been a while since I’ve done anything about the Terrain Library. During the last months I spent all of my free time in the scene editor, leaving all those landscapes out there with several bugs and inconsistencies. For example, the following is a screenshot of how terrains are rendered today:

Cracks everywhere... but the sky looks nice

 

Yes, there are cracks everywhere. Performance can be improved as well. And the code should be cleaned up and documented if I ever want this to be usable by anyone but myself.

So, I decided to go back and finish the fight (at least for a couple of months). And I’m planning to leave a log of everything I’m doing. I guess that will be the challenging part 😛

Stay tuned for more development insights about Crimild and the Terrain Library.

Cya.

H