1. "HANGOVER" (ASCII-encoded)
2. 0 (32bit int)
3. Terrain.TilesX (32bit int)
4. Terrain.TilesZ (32bit int)
5. Tile.Width (32bit float)
6. Tile.Length (32bit float)
7. Tile.Height (32bit float)
8. Tile.MeshResolutionX (32bit int)
9. Tile.MeshResolutionY (32bit int)
10. Tile.MeshResolutionZ (32bit int)
11. Tile.VoxelsX (32bit int)
12. Tile.VoxelsY (32bit int)
13. Tile.VoxelsZ (32bit int)
14. terrain data
The terrain data has the following structure.
The space that the terrain resides in is divided in the X and Z directions in so-called 3D tiles.
The following pattern describes the order of tiles in the terrain and stacks in a tile (Terrain.TilesX = 3, Terrain.TilesZ = 2):
0 1 2
3 4 5
In the terrain data, there is a sequence of all tiles in the terrain, laid out according to the pattern.
Each tile in the terrain data consists of only its stack data.
A tile contains Tile.VoxelsX*Y*Z voxels.
All voxels for a given combination of X and Z reside in a stack starting at the bottom of the tile.
Each stack is made of stack elements.
A stack element is a pair of two bytes (h, t): The height of the stack element and the material type of the stack element.
A stack ends either when the added heights of its elements are equal to Tile.VoxelsY or when the pair (h = 0, t = *) is used to "finish" that stack (* = whatever byte, that one's ignored).
When reading such a .ho.dat file and interpreting it as voxel data, you need to do the following:
- read all data until you reach the terrain data; the total voxel space has these dimensions: (Terrain.TilesX*Tile.VoxelsX, Tile.VoxelsY, Terrain.TilesZ*Tile.VoxelsZ)
- read the voxel data as follows: for each tile (for each stack (read stack elements until either stack height Tile.VoxelsY is reached or the stack element (h = 0, t = *) is encountered))
- fill your voxel space according to the stack data
Do note that when you read stacks within tiles, the pattern looks like this (numbers = tile indices, letters = stack indices):
0A 0B 1A 1B 2A 2B
0C 0D 1C 1D 2C 2D
3A 3B 4A 4B 5A 5B
3C 3D 4C 4D 5C 5D
A long time after my thesis was submitted and evaluated, we figured out one problem: Contrary to how the marching cubes algorithm should be implemented, I calculated the values for the normals only after offsetting/interpolating the grid points.
That calculation must be done before
that interpolation is done.
You may also notice that there are gaps appearing in the model: Those come from the natural ambiguities of the original marching cubes algorithm and can be alleviated by using more sample points in those situations.