It’s been a while since the last post, I went for about a week or so without being able to work on DaggerXL very much. Since then there has been some more progress on the terrain system.
The foliage positions are now generated directly from the terrain vertices. The effect of this is that foliage no longer shows up in location blocks, like it did sometimes before. It is also generated at the correct height now. You can see the effect in the screenshots below. Look at the hill in the background.
Locations & Collision
As before locations are still flat and the entire location is placed at the global altitude map height for that map pixel. This means that ground collision and Flat/NPC heights are adjusted accordingly. In addition the terrain now “connects” to the locations so that it is continuous. Right now it can be somewhat jarring, but I plan on smoothing out the transitions so that it looks natural. When the player walks on the bumpy terrain, the collision now works correctly. Rather then colliding with the polygons themselves, when terrain tiles are generated around the player the heights are saved. To figure out the height at the player’s position, the engine figures out which quad the player is standing on and determines the height using bilinear interpolation.
This turned out to be more of a task than I originally thought. Most engines have a few repeating textures and then some global blend maps (or vertex blending) to blend between them. Daggerfall had 56 tiles, all derived from 4 basic terrain textures (water, grass, dirt, rock – for temperate climates). The first thing DaggerXL does it pack these textures into an atlas for each climate. The engine automatically generates a small border around each texture by extruding the edges, so that filtering works correctly. As you’ll see later, I have to make the border larger, there are still artifacts (edges visible around the quads) at lower mip-levels.
Here’s the atlas generated for temperate terrain:
In order for each quad in the mesh to map to a different tile, extra vertices have to be generated (4 per quad) – though this doesn’t affect the polygon count or index buffer size. Anyway when each terrain tile is generated, a 16×16 tile index is generated, from which the texture coordinates are derived.
A screenshot of random texture tiles applied, just to verify the texture coordinates are generated correctly:
So the next step is to choose one of the base terrain tiles for each vertex, from which the final tile will be generated. The terrain tile index is generated from coherent noise, with probabilities generated based on altitude and proximity to the shore line. This means that each terrain cell can be generated independently and the textures still match up, as you’ll see later.
A screenshot of the base texture tiles being generated with no transitions:
If you look at the terrain atlas again, you’ll notice that most of the tiles represent transitions between different base tiles. For each quad, the base texture tiles generated for the 4 vertices making up that quad are used to determine the proper transition tile. Using Marching Squares, for a transition between 2 different tile types within a quad, there are 16 transitions (lines or curves if generating an isoline or isocurve). In Daggerfall, to preserve space, those transitions are generated from a much smaller set of tiles using horizontal flipping, vertical flipping and 90 degree rotation. So I pack the vertex base tile types into an unsigned long which then accesses a table that specifies the tile index, 1 bit for u flip, 1 bit for v flip and 1 bit for 90-degree rotation. The following screenshots show this off, however only transitions between grass and dirt have been finished, though the rest will be in soon.
I have to finish the terrain transition table, handle texturing along coastlines and then I can release the next version. 🙂