Although I've been providing updated screenshots, I found a nifty new program called "Mr. Captor" that lets me use software to capture the game in real-time. In the past I used the video out of my video card to my video camera, then I had to use a fire-wire to capture it back into the computer to make it available, and that was just too big a pain. This new software works pretty well, and although the resolution isn't perfect, I think it's at least as good as what I was doing before, and probably better. Because standard TV is low-res, so are video cameras. This capture software allows me to capture at the same resolution I'm running the engine at, so it's not too bad. I had tried other similar programs in the past, but they killed the frame rate so bad, I couldn't use them. This one seems to work much better that I had no problem using it.
Here is the link to the latest video on the terrain engine. There are a few things special about the engine that I want to clarify:
1. This video is not edited at all. The only thing I did post production was to add the voice over. The entire video was done in a single engine, real-time, as I just ran it and did a walk through.
2. In the video you will see three planets, without much of a pause to switch planets. This is really how the engine works. There is no more overhead to switch planets then there is simply walking over the terrain of a large planet
3. The planet is not loaded as one height map, but many hundreds or thousands of them, managed dynamically as you travel over the terrain
4. You'll see there was no load time to start the program. There isn't. Starting the program, traveling over the terrain or switching planets has the same minimal overhead.
Enjoy the video: STARQuest 2005-12-13 Terrain Demo
It's pretty large, and my connection speed isn't the fastest, so I apologize for slow or annoying downloads.
Below I am including some details on how I designed and built the terrain subsystem. It's a bit different I think then many of the other systems out there, but I built it the way I did to meet my specific needs. I hope you find it interesting and maybe it'll help some of you who are in the beginning stages of your own terrain engine.
My philosophy is simple is better. If it looks good, then it is good. I didn't get all caught up in existing methodologies for doing terrain and/or LOD, in short, it's so simple it almost seems too obvious. This current engine is 98% just me. With the exception of some help from great forum people like yourselves, a friend helped with the model loading class for the player character, which comes from the Microsoft demos; Otherwise, it's all my code.
The terrain starts out as a height map, but instead of a 128x128 or 256x256, I want something huge for an entire planet, so it might be 50,000 x 50,0000 or larger. Since no graphics programs can load this large an image I use a height map generator which uses common noise and other algorithms to generate. I also want greater than the normal 256 gray scale height range, so I use an RGBA (int) value for the height ranges. I'm not done coding the height generator, so all of my current planets are limited to 256 color gray scale and were done with photoshop. My largest planet today is 12,000x12,000 which I was able to do in photoshop, but the terrain code is dynamic to handle anything.
Next I perform a pre processing step to split the height map into manageable 64x64 cells. This could be any size but I'm using 64. The trick here is that the last edge of each cell has to be the first edge of the next cell, so I don't have holes when they are lined up next to each other. Also the very first cell edge and the very last cell edge must be the same. I automate this in my split program.
Then to render the terrain I perform the following steps:
1. I load a minimum of either 3x3 cells or 5x5 cells (configurable based on system speed). The 5x5 variation gives greater visibility and is what I'm using in all of the screen shots. On a P4 3.2ghz with an Nvidia 6800GT I'm getting about 200fps which includes tree rendering discussed below, but the tree hierarchy isn't complete yet, so I'm rendering a few thousand trees brute force.
2. The player is always standing in the center cell, and I calculate what cells to load around the player
3. Using culling, I don't draw the cells that are outside of the view port, although I always keep them loaded (3x3 or 5x5)
4. When the player crosses the edge between cells I shift the entire row or column and unload the row or column that falls off and load the next row or column on the opposite side. This way I only ever load 9 cells worst case, but 5 on average for a 5x5 grid. The load time for 9 cells is sub second, and only loaded when the player crosses the edge, so its very fast, and unnoticeable.
5. It would kill the local file system to store all of the cells locally, and given a terrain the size of a planet, the player will never be able to travel to every cell anyway.
6. An average cell size (depending on the scaling which I can tune) is about 5 miles
7. I will store all the cells for a planet in a database on the server, and have a separate thread who's responsibility is to calculate the cells for a 10x10 grid around the player and always keep those cells on the local file system. This way by the time I actually need to load the cell it's already been downloaded, and the number of files being managed on the local file system is negligible.
8. I can also allow the planet terrain to change this way, so if a bomb makes a crater, I can update the database and all the clients will see the crater (if and when they travel to that part of the planet)
9. Not all of the code is done, but has been prototyped. The only parts not 100% done are the server side storage and caching thread. In the sample screen shots the entire planet is stored locally. My current largest planet is around 40,000 cells, which is about 2/3 of the US if I recall.
10. In a sense I have two types of LOD, one I already mentioned in that I can render a 3x3 grouping of cells vs. a 5x5 grouping. The other used only with the 5x5 option is that the outer most edge can be scaled down by skipping every other vertex and rendering them as a 32x32 cell instead of a 64x64. This is done when the frame rate is in between the point of full 3x3 vs 5x5. The reason it's only the outer most edge is because its always far enough that the frame-rate is slightly improved but the local terrain is still hires.
11. When texturing, I use two sets of textures, one are low-res (blurred) textures used over the entire terrain, then a second pass uses hires textures only around the immediate player area. Also, if the player were flying, as their distance from the ground increases, the texture tiling is dynamically adjusted to minimize the tiling artifact until such point that only the low-res textures are rendered. Eventually I might change the base low-res texture to blur dynamically, but for now this cheat works quite well, and as I said, "Keep it simple"
The texturing of the terrain is dynamic using attributes of the planet to define the algorithm used for blending. I define up to 4 different textures based on elevation, along with randomization where textures can overlap. This gives a nice blending of dirt, grass, rocks, etc. I would like to increase this to 8 textures, but haven't done so yet. For systems that support pixel shaders I use them for blending. Otherwise, I perform multi-pass.
Water is rendered as an animated texture based on a height attribute. Today it's the same height across the whole planet, but I'm considering if I need to be more selective. For now, I think it's sufficient. Because planets are so big, we can truly have oceans, not just small lakes or rivers.
Trees, grass, bushes, etc... are still being coded, but I've designed a hierarchal class manager to group trees to cells, and further group many clusters of trees to a cell. I then only need to deal with the groupings that are tied to the cells being rendered, and I can further perform crude distance checks on each cluster and make the decision:
o not to render
o render the cluster as a distant billboard
o Render the trees as individual billboards (fading them in as the distance gets closer)
o Render them as full 3d objects when close enough
Although none of the pictures have buildings or structures, the buildings, cities, blocks, etc.... are all stored as a hierarchy associated with the cell, similar to the trees.
All objects and the contents within are rendered using a portal technique, so instead of using a BSP tree or other common structure, a building for example is just a model of the exterior with various polys tagged as openings, and each opening is linked to another separate object (a room for example). Since the hierarchy is a list of sorts, it's easy and instantaneous to add or remove objects real-time, so if a building gets destroyed it can be removed in its entirety or even replaced with a different object. Also, as clans build their own bases, buildings and cities can be added dynamically with no performance impact or special processing needs.
Hope all that makes sense. Let me know if you have any further detailed questions.